Esempio n. 1
0
/* ljoy_init_joystick: [primary thread]
 *  Initialise the joystick driver.
 */
static bool ljoy_init_joystick(void)
{
    _al_vector_init(&joysticks, sizeof(ALLEGRO_JOYSTICK_LINUX *));
    num_joysticks = 0;

    if (!(config_mutex = al_create_mutex())) {
        return false;
    }

    // Scan for joysticks
    ljoy_scan(false);
    ljoy_merge();

#ifdef SUPPORT_HOTPLUG
    if (!(hotplug_mutex = al_create_mutex())) {
        al_destroy_mutex(config_mutex);
        return false;
    }
    if (!(hotplug_cond = al_create_cond())) {
        al_destroy_mutex(config_mutex);
        al_destroy_mutex(hotplug_mutex);
        return false;
    }
    if (!(hotplug_thread = al_create_thread(hotplug_proc, NULL))) {
        al_destroy_mutex(config_mutex);
        al_destroy_mutex(hotplug_mutex);
        al_destroy_cond(hotplug_cond);
        return false;
    }

    al_start_thread(hotplug_thread);

    inotify_fd = inotify_init();
    if (inotify_fd != -1) {
        fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
        /* Modern Linux probably only needs to monitor /dev/input. */
        inotify_add_watch(inotify_fd, "/dev/input", IN_CREATE|IN_DELETE);
        _al_unix_start_watching_fd(inotify_fd, ljoy_config_dev_changed, NULL);
        ALLEGRO_INFO("Hotplugging enabled\n");
    }
    else {
        ALLEGRO_WARN("Hotplugging not enabled\n");
        if (inotify_fd != -1) {
            close(inotify_fd);
            inotify_fd = -1;
        }
    }
#endif

    return true;
}
Esempio n. 2
0
/* lkeybd_init_keyboard: [primary thread]
 *  Initialise the keyboard driver.
 */
static bool lkeybd_init_keyboard(void)
{
   bool can_restore_termio_and_kbmode = false;

   memset(&the_keyboard, 0, sizeof the_keyboard);

/*
   if (__al_linux_use_console())
      return false;
*/
   the_keyboard.fd = open("/dev/tty", O_RDWR);

   /* Save the current terminal attributes, which we will restore when
    * we close up shop.
    */
   if (tcgetattr(the_keyboard.fd, &the_keyboard.startup_termio) != 0) {
      goto Error;
   }

   /* Save previous keyboard mode (probably XLATE). */
   if (ioctl(the_keyboard.fd, KDGKBMODE, &the_keyboard.startup_kbmode) != 0) {
      //goto Error;
   }

   can_restore_termio_and_kbmode = false;

   /* Set terminal attributes we need.
    *
    * Input modes (c_iflag): We want to disable:
    *  - stripping bytes to 7 bits
    *  - ignoring of carriage returns
    *  - translating of carriage returns to newlines, and vice versa
    *  - start/stop control on input and output
    *
    * Control modes (c_cflag): We want 8 bits per byte.
    *
    * Local modes (c_lflag: We want to disable:
    *  - canonical (line by line) input
    *  - echoing input back to the display
    *  - interpretation of signal characters
    *
    * The c_iflag, c_lflag settings come from svgalib. Allegro 4
    * simply set them to 0, which is a bit crude.
    */
   the_keyboard.work_termio = the_keyboard.startup_termio;
   the_keyboard.work_termio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
   the_keyboard.work_termio.c_cflag &= ~CSIZE;
   the_keyboard.work_termio.c_cflag |= CS8;
   the_keyboard.work_termio.c_lflag &= ~(ICANON | ECHO | ISIG);

   if (tcsetattr(the_keyboard.fd, TCSANOW, &the_keyboard.work_termio) != 0) {
      goto Error;
   }

   /* Set the keyboard mode to mediumraw. */
   if (ioctl(the_keyboard.fd, KDSKBMODE, K_MEDIUMRAW) != 0) {
      //goto Error;
   }

   the_keyboard.three_finger_flag = true;
   the_keyboard.key_led_flag = true;

   const char *value = al_get_config_value(al_get_system_config(),
         "keyboard", "enable_three_finger_exit");
   if (value) {
      the_keyboard.three_finger_flag = !strncmp(value, "true", 4);
   }
   value = al_get_config_value(al_get_system_config(),
         "keyboard", "enable_key_led_toggle");
   if (value) {
      the_keyboard.key_led_flag = !strncmp(value, "true", 4);
   }

   ALLEGRO_DEBUG("Three finger flag enabled: %s\n",
      the_keyboard.three_finger_flag ? "true" : "false");
   ALLEGRO_DEBUG("Key LED toggle enabled: %s\n",
      the_keyboard.key_led_flag ? "true" : "false");

   /* Initialise the keyboard object for use as an event source. */
   _al_event_source_init(&the_keyboard.parent.es);

   /* Start watching for data on the fd. */
   _al_unix_start_watching_fd(the_keyboard.fd, process_new_data, NULL);

   /* Get the pid, which we use for the three finger salute */
   main_pid = getpid();

   return true;

  Error:

   if (can_restore_termio_and_kbmode) {
      tcsetattr(the_keyboard.fd, TCSANOW, &the_keyboard.startup_termio);
      ioctl(the_keyboard.fd, KDSKBMODE, the_keyboard.startup_kbmode);
   }

   close(the_keyboard.fd);

/*
   __al_linux_leave_console();
*/

   return false;
}
Esempio n. 3
0
static void ljoy_scan(bool configure)
{
    int fd;
    ALLEGRO_JOYSTICK_LINUX *joy, **joypp;
    int num;
    ALLEGRO_USTR *device_name;
    unsigned i;

    /* Clear mark bits. */
    for (i = 0; i < _al_vector_size(&joysticks); i++) {
        joypp = _al_vector_ref(&joysticks, i);
        joy = *joypp;
        joy->marked = false;
    }

    device_name = al_ustr_new("");

    /* This is a big number, but there can be gaps and other unrelated event
     * device files.  Perhaps it would be better to use glob() here.
     */
    for (num = 0; num < 32; num++) {
        if (!ljoy_detect_device_name(num, device_name))
            continue;

        joy = ljoy_by_device_name(device_name);
        if (joy) {
            ALLEGRO_DEBUG("Device %s still exists\n", al_cstr(device_name));
            joy->marked = true;
            continue;
        }

        /* Try to open the device. The device must be opened in O_RDWR mode to
         * allow writing of haptic effects! The haptic driver for linux
         * reuses the joystick driver's fd.
         */
        fd = open(al_cstr(device_name), O_RDWR|O_NONBLOCK);
        if (fd == -1) {
            ALLEGRO_WARN("Failed to open device %s\n", al_cstr(device_name));
            continue;
        }

        /* The device must have at least one joystick-related axis, and one
         * joystick-related button.  Some devices, such as mouse pads, have ABS_X
         * and ABS_Y axes like a joystick but not joystick-related buttons.  By
         * checking for both axes and buttons, such devices can be excluded.
         */
        if (!have_joystick_button(fd) || !have_joystick_axis(fd)) {
            ALLEGRO_DEBUG("Device %s not a joystick\n", al_cstr(device_name));
            close(fd);
            continue;
        }

        ALLEGRO_DEBUG("Device %s is new\n", al_cstr(device_name));

        joy = ljoy_allocate_structure();
        joy->fd = fd;
        joy->device_name = al_ustr_dup(device_name);
        joy->config_state = LJOY_STATE_BORN;
        joy->marked = true;
        config_needs_merging = true;

        if (ioctl(fd, EVIOCGNAME(sizeof(joy->name)), joy->name) < 0)
            strcpy(joy->name, "Unknown");

        /* Map Linux input API axis and button numbers to ours, and fill in
         * information.
         */
        if (!fill_joystick_axes(joy, fd) || !fill_joystick_buttons(joy, fd)) {
            ALLEGRO_ERROR("fill_joystick_info failed %s\n", al_cstr(device_name));
            inactivate_joy(joy);
            close(fd);
            continue;
        }

        /* Register the joystick with the fdwatch subsystem.  */
        _al_unix_start_watching_fd(joy->fd, ljoy_process_new_data, joy);
    }

    al_ustr_free(device_name);

    /* Schedule unmarked structures to be inactivated. */
    for (i = 0; i < _al_vector_size(&joysticks); i++) {
        joypp = _al_vector_ref(&joysticks, i);
        joy = *joypp;

        if (joy->config_state == LJOY_STATE_ALIVE && !joy->marked) {
            ALLEGRO_DEBUG("Device %s to be inactivated\n",
                          al_cstr(joy->device_name));
            joy->config_state = LJOY_STATE_DYING;
            config_needs_merging = true;
        }
    }

    /* Generate a configure event if necessary.
     * Even if we generated one before that the user hasn't responded to,
     * we don't know if the user received it so always generate it.
     */
    if (config_needs_merging && configure) {
        ljoy_generate_configure_event();
    }
}
Esempio n. 4
0
/* ljoy_get_joystick: [primary thread]
 *
 *  Returns the address of a ALLEGRO_JOYSTICK structure for the device
 *  number NUM.  The top-level joystick functions will not call this
 *  function if joystick number NUM was already gotten.  If the
 *  device cannot be opened, NULL is returned.
 */
static ALLEGRO_JOYSTICK *ljoy_get_joystick(int num)
{
   ALLEGRO_JOYSTICK_LINUX *joy;
   int fd;

   /* Try to open the device. */
   fd = try_open_joy_device(num);
   if (fd == -1)
      return NULL;

   /* Allocate a structure for the joystick. */
   joy = _AL_MALLOC(sizeof *joy);
   if (!joy) {
      close(fd);
      return NULL;
   }
   memset(joy, 0, sizeof *joy);

   /* Initialise the event source part of it. */
   _al_event_source_init(&joy->parent.es);

   /* Fill in the joystick information fields. */
   {
      /* char tmp[128], tmp1[128], tmp2[128]; */
      char num_axes;
      char num_buttons;
      int throttle;
      int s, a, b;

      ioctl(fd, JSIOCGAXES, &num_axes);
      ioctl(fd, JSIOCGBUTTONS, &num_buttons);

      if (num_axes > TOTAL_JOYSTICK_AXES)
         num_axes = TOTAL_JOYSTICK_AXES;

      if (num_buttons > _AL_MAX_JOYSTICK_BUTTONS)
         num_buttons = _AL_MAX_JOYSTICK_BUTTONS;

      /* XXX use configuration system when we get one */
      throttle = -1;
#if 0
      /* User is allowed to override our simple assumption of which
       * axis number (kernel) the throttle is located at. */
      snprintf(tmp, sizeof(tmp), "throttle_axis_%d", num);
      throttle = get_config_int("joystick", tmp, -1);
      if (throttle == -1) {
         throttle = get_config_int("joystick", 
                                   "throttle_axis", -1);
      }
#endif

      /* Each pair of axes is assumed to make up a stick unless it 
       * is the sole remaining axis, or has been user specified, in 
       * which case it is a throttle. */

      for (s = 0, a = 0;
           s < _AL_MAX_JOYSTICK_STICKS && a < num_axes;
           s++)
      {
         if ((a == throttle) || (a == num_axes-1)) {
            /* One axis throttle. */
            joy->parent.info.stick[s].flags = ALLEGRO_JOYFLAG_ANALOGUE;
            joy->parent.info.stick[s].num_axes = 1;
            joy->parent.info.stick[s].axis[0].name = "Throttle";
            char *name = joy->parent.info.stick[s].axis[0].name;
            joy->parent.info.stick[s].name = _AL_MALLOC_ATOMIC(strlen(name) + 1);
            strcpy(joy->parent.info.stick[s].name, name);
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 0;
            a++;
         }
         else {
            /* Two axis stick. */
            joy->parent.info.stick[s].flags = ALLEGRO_JOYFLAG_ANALOGUE;
            joy->parent.info.stick[s].num_axes = 2;
            joy->parent.info.stick[s].axis[0].name = "X";
            joy->parent.info.stick[s].axis[1].name = "Y";
            joy->parent.info.stick[s].name = _AL_MALLOC_ATOMIC (32);
            snprintf((char *)joy->parent.info.stick[s].name, 32, "Stick %d", s+1);
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 0;
            a++;
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 1;
            a++;
         }
      }

      joy->parent.info.num_sticks = s;

      /* Do the buttons. */

      for (b = 0; b < num_buttons; b++) {
         joy->parent.info.button[b].name = _AL_MALLOC_ATOMIC (32);
         snprintf((char *)joy->parent.info.button[b].name, 32, "B%d", b+1);
      }

      joy->parent.info.num_buttons = num_buttons;
   }

   joy->parent.num = num;

   joy->fd = fd;

   /* Register the joystick with the fdwatch subsystem.  */
   _al_unix_start_watching_fd(joy->fd, ljoy_process_new_data, joy);

   return (ALLEGRO_JOYSTICK *) joy;
}