Logo Search packages:      
Sourcecode: libjsw version File versions

attributes.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "../include/string.h"

#include "../include/jsw.h"


js_attribute_struct *JSGetAttributesList(
        int *total, const char *calibration
);
void JSFreeAttributesList(js_attribute_struct *list, int total);


#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))


/*
 *      Fetches attributes for all joysticks accessable (configured
 *      or not) on the system. Does not matter if the joystick is
 *      already opened or not. Returned values need to be free()'ed
 *      with a call to JSFreeAttributeList().
 *
 *      If the given calibration file calibration is NULL then some values
 *    may not be set in the attrib structure (ie is_configured and name).
 */
js_attribute_struct *JSGetAttributesList(
      int *total, const char *calibration
)
{
      int total_attribs = 0;
      js_attribute_struct *attrib = NULL, *attrib_ptr;


      if(total != NULL)
          (*total) = 0;

#ifdef __linux__
      /* Begin fetching list of device attributes for Linux. */
      if(1)
      {
          int i, n, j, fd, total_device_names;
          const char *cstrptr;
          char **device_name;
          char tmp_path[PATH_MAX + NAME_MAX];
          js_data_struct tmp_jsd;
          struct stat stat_buf;


/* Allocates a new js_attribute_struct to the attrib list and
 * sets attrib_ptr to point to the new structure. Note that
 * attrib_ptr can be NULL on error.
 */
#define DO_ALLOCATE     \
{ \
 /* Allocate more pointers. */ \
 n = total_attribs; \
 total_attribs = n + 1; \
 attrib = (js_attribute_struct *)realloc( \
  attrib, \
  total_attribs * sizeof(js_attribute_struct) \
 ); \
 if(attrib == NULL) \
 { \
  /* Allocate error, reset contexts. */ \
  n = -1; \
  total_attribs = 0; \
  attrib_ptr = NULL; \
 } \
 else \
 { \
  /* Get pointer to new structure and reset values. */ \
  attrib_ptr = &attrib[n]; \
  memset(attrib_ptr, 0x00, sizeof(js_attribute_struct)); \
 } \
}

          /* Begin searching for each device untill one is missing,
           * look in the "/dev/js#" paths where # is a number.
           */
          for(i = 0; 1; i++)
          {
            /* Format joystick device file path. */
            sprintf(tmp_path, "/dev/js%i", i);

            /* Joystick device file does not exist? */
            if(stat(tmp_path, &stat_buf))
                 break;

            /* Allocate a new attrib structure, set values to it. */
            DO_ALLOCATE
            if(attrib_ptr != NULL)
            {
                /* Record device name. */
                free(attrib_ptr->device_name);
                attrib_ptr->device_name = strdup(tmp_path);

                /* See if we can open it. */
                fd = open(tmp_path, O_RDONLY);
                if(fd < 0)
                {
                  /* Could not open it, handle errno. */
                  switch(errno)
                  {
                    case ENODEV: case ENFILE:
                      attrib_ptr->not_accessable = 1;
                      break;

                    default:
                      /* All else assume is in use. */
                      attrib_ptr->is_in_use = 1;
                      break;
                  }
                }
                else
                {
                  /* Opened it just fine, now close it. */
                  close(fd);
                }
                /* From here fd is invalid. */
            }
          }

            /* Repeat the above, except for USB devices, begin searching
           * in the "/dev/input/js#" paths where # is a number.
             */
            for(i = 0; 1; i++)
            {
                /* Format joystick device file path. */
                sprintf(tmp_path, "/dev/input/js%i", i);

                /* Joystick device file does not exist? */
                if(stat(tmp_path, &stat_buf))
                     break;

                /* Allocate a new attrib structure, set values to it. */
                DO_ALLOCATE
                if(attrib_ptr != NULL)
                {
                    /* Record device name. */
                    free(attrib_ptr->device_name);
                    attrib_ptr->device_name = strdup(tmp_path);

                    /* See if we can open it. */
                    fd = open(tmp_path, O_RDONLY);
                    if(fd < 0)
                    {
                        /* Could not open it, handle errno. */
                        switch(errno)
                        {
                          case ENODEV: case ENFILE:
                            attrib_ptr->not_accessable = 1;
                            break;

                          default:
                            /* All else assume is in use. */
                            attrib_ptr->is_in_use = 1;
                            break;
                        }
                    }
                    else
                    {
                        /* Opened it just fine, now close it. */
                        close(fd);
                    }
                /* From here fd is invalid. */
                }
            }


          /* Most attributes have been fetched and devices that exist
           * have been checked for. Now scan through calibration file
           * (if calibration is not NULL) and see which devices are
           * configured properly.
           */
          device_name = JSLoadDeviceNamesUNIX(
            &total_device_names, calibration
          );

          /* Itterate through newly allocated attrib list. */
          for(i = 0; i < total_attribs; i++)
          {
            attrib_ptr = &attrib[i];

            /* Device name must be specified on the attribute
             * structure.
             */
            if(attrib_ptr->device_name == NULL)
                continue;

            /* Itterate through device names, see if a device name in
             * the list matches this device's name.
             */
            for(j = 0; j < total_device_names; j++)
            {
                cstrptr = device_name[j];
                if(cstrptr == NULL)
                  continue;

                /* Device name does not match device name on current
                 * attribute structure?
                 */
                if(strcmp(cstrptr, attrib_ptr->device_name))
                    continue;

                /* This device is in the device names list, so
                 * mark it as being configured properly.
                 */
                attrib_ptr->is_configured = 1;

                /* Get calibration info for this device, first reset 
                 * values on the tmp_jsd and then set the device name
                 * on the tmp_jsd and call the calibration file loader.
                 */
                memset(&tmp_jsd, 0x00, sizeof(js_data_struct));
                tmp_jsd.fd = -1;
                tmp_jsd.device_name = strdup(cstrptr);
                    tmp_jsd.calibration_file = (calibration != NULL) ?
                  strdup(calibration) : NULL;
                JSLoadCalibrationUNIX(&tmp_jsd);

                /* Update values to attribute. */
                free(attrib_ptr->name);
                attrib_ptr->name = (tmp_jsd.name != NULL) ?
                  strdup(tmp_jsd.name) : NULL;

                /* Deallocate resources loaded by calibration file. */
                JSClose(&tmp_jsd);

                break;
            }
          }

          /* Free loaded device names. */
          StringFreeArray(device_name, total_device_names);

#undef DO_ALLOCATE
      }
#else
      /* Some other platform. */

/* Write support for fetching attributes for different platforms
 * here.
 */


#endif

      /* Update returns. */
        if(total != NULL)
            (*total) = total_attribs;
 
      return(attrib);
}

/*
 *      Frees a list of js_attribute_structs and their substructures.
 */
void JSFreeAttributesList(js_attribute_struct *list, int total)
{
      int i;
      js_attribute_struct *ptr;


      for(i = 0; i < total; i++)
      {
          ptr = &list[i];

          free(ptr->name);
          free(ptr->device_name);
      }
      free(list);
}


Generated by  Doxygen 1.6.0   Back to index