]> xenbits.xen.org Git - xenclient/ioemu-pq.git/commitdiff
Repleace hid-linux.c with a better version
authorroot <root@kiffu-2.uk.xensource.com>
Mon, 3 Aug 2009 12:26:12 +0000 (13:26 +0100)
committerroot <root@kiffu-2.uk.xensource.com>
Mon, 3 Aug 2009 12:26:12 +0000 (13:26 +0100)
master/new-input-code [new file with mode: 0644]
master/series

diff --git a/master/new-input-code b/master/new-input-code
new file mode 100644 (file)
index 0000000..9b172f0
--- /dev/null
@@ -0,0 +1,969 @@
+diff --git a/hid-linux.c b/hid-linux.c
+index f2e0bce..8cb3e30 100644
+--- a/hid-linux.c
++++ b/hid-linux.c
+@@ -43,11 +43,8 @@
+ #include <time.h>
+ #include <sys/time.h>
+-#define HID_LINUX_XS_PATH             "/local/domain/0/hid_linux"
++#define HID_LINUX_XS_PATH             "/local/domain/0/linux_hid_driver"
+ #define ABS(x)                        ((x) > 0 ? (x) : -(x))
+-#define EVENT_PATH                            "/dev/input/event"
+-#define HID_LINUX_MAX_DEV             16
+-#define HID_LINUX_MAX_DEV_NO          64
+ #define DEBUG_HID_LINUX
+@@ -64,468 +61,592 @@ while (0);
+ # define DEBUG(_format_, args...) (void)0
+ #endif
+-static struct hid_linux_driver
++
++#define N_DEVS 64
++
++#define HID_TYPE_KEYBOARD     1
++#define HID_TYPE_MOUSE                2
++
++
++static struct linux_hid_driver
+ {
+-    int               keyboard_fds[HID_LINUX_MAX_DEV / 2];
+-    int               mouse_fds[HID_LINUX_MAX_DEV / 2];
+-    char      *controller_paths[HID_LINUX_MAX_DEV];
+-    int               mouse_button_state;
+-    int               key_status[256];
+-    void      (*secure_key)(int ascii);
+-} hid_linux_driver;
+-
+-struct hid_linux_binding
++  QEMUTimer *scan_timer;
++  int keyboard_grabbed;
++  int mouse_grabbed;
++  int types[N_DEVS];
++  int fds[N_DEVS];
++  int mouse_button_state;
++  int key_status[256];
++  void (*secure_key) (int ascii);
++} linux_hid_driver;
++
++struct linux_hid_binding
+ {
+-    int       *binding;
+-    void      (*cb)(void *);
+-    void      *payload;
++  int *binding;
++  void (*cb) (void *);
++  void *payload;
+ };
+-static struct hid_linux_binding *hid_linux_binding = NULL;
++static struct linux_hid_binding *linux_hid_binding = NULL;
+-static const int ascii2keycode_table[] =
+-{
+-    KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
+-    KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
+-    KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
++static const int ascii2keycode_table[] = {
++  KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
++  KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
++  KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
+ };
+-static char keycode2ascii(int keycode)
++static char
++keycode2ascii (int keycode)
+ {
+-    int i = 0;
++  int i = 0;
+-    switch (keycode)
++  switch (keycode)
+     {
+-      case KEY_ESC: return 27;
+-      case KEY_BACKSPACE: return 8;
+-      case KEY_ENTER: return 10;
+-      case KEY_LEFT: return 17;
+-      case KEY_RIGHT: return 18;
+-      case KEY_DELETE: return 127;
+-      case KEY_HOME: return 2;
+-      case KEY_END: return 3;
+-      case KEY_INSERT: return 19;
+-      case KEY_SPACE: return 20;
+-      default:
+-              for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
+-                  if (ascii2keycode_table[i] == keycode)
+-                      return i + 'a';
++    case KEY_ESC:
++      return 27;
++    case KEY_BACKSPACE:
++      return 8;
++    case KEY_ENTER:
++      return 10;
++    case KEY_LEFT:
++      return 17;
++    case KEY_RIGHT:
++      return 18;
++    case KEY_DELETE:
++      return 127;
++    case KEY_HOME:
++      return 2;
++    case KEY_END:
++      return 3;
++    case KEY_INSERT:
++      return 19;
++    case KEY_SPACE:
++      return 20;
++    default:
++      for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
++        if (ascii2keycode_table[i] == keycode)
++          return i + 'a';
+     }
+-    return 0;
++  return 0;
+ }
+-static int ascii2keycode(char ascii)
++static int
++ascii2keycode (char ascii)
+ {
+-    return ascii2keycode_table[ascii - 'a'];
++  return ascii2keycode_table[ascii - 'a'];
+ }
+-static char *hid_linux_xs_read(const char *key)
++static char *
++hid_linux_xs_read (const char *key)
+ {
+-    char *path = NULL;
+-    char *ret;
+-
+-    if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1)
+-      return NULL;
+-    ret = xenstore_read(path);
+-    free(path);
+-    return ret;
++  char *path = NULL;
++  char *ret;
++
++  if (asprintf (&path, HID_LINUX_XS_PATH "/%s", key) == -1)
++    return NULL;
++  ret = xenstore_read (path);
++  free (path);
++  return ret;
+ }
+-void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload)
++void
++hid_linux_add_binding (const int *tab, void (*cb) (void *), void *payload)
+ {
+-    int i = 0, j = 0;
+-
+-    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
+-      ;
+-    hid_linux_binding = realloc(hid_linux_binding,
+-                              (i + 2) * sizeof (struct hid_linux_binding));
+-    hid_linux_binding[i + 1].cb = NULL;
+-    hid_linux_binding[i].cb = cb;
+-    hid_linux_binding[i].payload = payload;
+-    hid_linux_binding[i].binding = NULL;
+-
+-    j = 0;
+-    do
++  int i = 0, j = 0;
++
++  for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++)
++    ;
++  linux_hid_binding = realloc (linux_hid_binding,
++                               (i + 2) * sizeof (struct linux_hid_binding));
++  linux_hid_binding[i + 1].cb = NULL;
++  linux_hid_binding[i].cb = cb;
++  linux_hid_binding[i].payload = payload;
++  linux_hid_binding[i].binding = NULL;
++
++  j = 0;
++  do
+     {
+-      hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding,
+-                                             (j + 1) * sizeof (int));
+-      hid_linux_binding[i].binding[j] = tab[j];
++      linux_hid_binding[i].binding = realloc (linux_hid_binding[i].binding,
++                                              (j + 1) * sizeof (int));
++      linux_hid_binding[i].binding[j] = tab[j];
+     }
+-    while (tab[j++] != -1);
++  while (tab[j++] != -1);
+ }
+-static int hid_linux_detect_binding(void)
++static int
++hid_linux_detect_binding (void)
+ {
+-    int i, j;
++  int i, j;
+-    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
++  for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++)
+     {
+-      int *tab = hid_linux_binding[i].binding;
+-
+-      for (j = 0; tab[j] != -1; j++)
+-          if (hid_linux_driver.key_status[tab[j]] == 0)
+-              break;
+-      if (tab[j] != -1)
+-          continue;
+-      else /* We match a binding */
+-      {
+-          DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload));
+-          hid_linux_binding[i].cb(hid_linux_binding[i].payload);
+-          hid_linux_reset_keyboard();
+-          return 1;
+-      }
++      int *tab = linux_hid_binding[i].binding;
++
++      for (j = 0; tab[j] != -1; j++)
++        if (linux_hid_driver.key_status[tab[j]] == 0)
++          break;
++      if (tab[j] != -1)
++        continue;
++      else                      /* We match a binding */
++        {
++          DEBUG ("binding payload %d\n",
++                 (int) (linux_hid_binding[i].payload));
++          linux_hid_binding[i].cb (linux_hid_binding[i].payload);
++          linux_hid_reset_keyboard ();
++          return 1;
++        }
+     }
+-    return 0;
++  return 0;
+ }
+-static void hid_linux_key_inject(int code, uint32_t keycode)
++static void
++hid_linux_key_inject (int code, uint32_t keycode)
+ {
+-    int first = 0;
++  int first = 0;
+-    switch (keycode)
++  switch (keycode)
+     {
+-      case KEY_F11:       keycode = 0X57; break; /* F11 */
+-      case KEY_F12:       keycode = 0X58; break; /* F12 */
+-      case KEY_INSERT:    keycode = 0X52; break;
+-      case KEY_HOME:      keycode = 0X47; break;
+-      case KEY_PAGEUP:    keycode = 0X49; break;
+-      case KEY_DELETE:    keycode = 0X53; break;
+-      case KEY_END:       keycode = 0X4F; break;
+-      case KEY_PAGEDOWN:  keycode = 0x51; break;
+-      case KEY_UP:        keycode = 0X48; break;
+-      case KEY_LEFT:      keycode = 0X4B; break;
+-      case KEY_DOWN:      keycode = 0X50; break;
+-      case KEY_RIGHT:     keycode = 0X4D; break;
+-      case KEY_RIGHTALT:  keycode = 0x38; first = 0xe0; break;
+-      case KEY_LEFTMETA:  keycode = 0x5B; first = 0xe0; break;
+-      case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break;
++    case KEY_F11:
++      keycode = 0X57;
++      break;                    /* F11 */
++    case KEY_F12:
++      keycode = 0X58;
++      break;                    /* F12 */
++    case KEY_INSERT:
++      keycode = 0X52;
++      break;
++    case KEY_HOME:
++      keycode = 0X47;
++      break;
++    case KEY_PAGEUP:
++      keycode = 0X49;
++      break;
++    case KEY_DELETE:
++      keycode = 0X53;
++      break;
++    case KEY_END:
++      keycode = 0X4F;
++      break;
++    case KEY_PAGEDOWN:
++      keycode = 0x51;
++      break;
++    case KEY_UP:
++      keycode = 0X48;
++      break;
++    case KEY_LEFT:
++      keycode = 0X4B;
++      break;
++    case KEY_DOWN:
++      keycode = 0X50;
++      break;
++    case KEY_RIGHT:
++      keycode = 0X4D;
++      break;
++    case KEY_RIGHTALT:
++      keycode = 0x38;
++      first = 0xe0;
++      break;
++    case KEY_LEFTMETA:
++      keycode = 0x5B;
++      first = 0xe0;
++      break;
++    case KEY_RIGHTMETA:
++      keycode = 0x5C;
++      first = 0xe0;
++      break;
+     }
+-    if (first)
+-      kbd_put_keycode(first);
++  if (first)
++    kbd_put_keycode (first);
+-    if (code == 0)
+-      kbd_put_keycode(keycode | 0x80);
+-    else
+-      kbd_put_keycode(keycode & 0x7f);
++  if (code == 0)
++    kbd_put_keycode (keycode | 0x80);
++  else
++    kbd_put_keycode (keycode & 0x7f);
+ }
+-static void hid_linux_key_event(int code, uint32_t keycode)
++static void
++linux_hid_key_event (int code, uint32_t keycode)
+ {
+-    if (code == 1)
+-      if (hid_linux_detect_binding())
+-          return;
+-    hid_linux_key_inject(code, keycode);
++  if (code == 1)
++    if (linux_hid_detect_binding ())
++      return;
++  linux_hid_key_inject (code, keycode);
+ }
+-static void hid_linux_read(void *opaque)
++
++static int
++hid_linux_read (int fd)
+ {
+-    struct input_event  event[5];
+-    int                 i = 0;
+-    int                 read_sz = 0;
+-    int                 fd = *(int *)opaque;
++  struct input_event event[5];
++  int i = 0;
++  int read_sz = 0;
++
++  read_sz = read (fd, event, sizeof (event));
++  if (read_sz <= 0)
++    return -1;
+-    read_sz = read(fd, event, sizeof (event));
+-    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
++  for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+     {
+-      if (event[i].type == EV_KEY)
+-      {
+-          if (event[i].code >= BTN_MOUSE)
+-          {
+-              /* Mouse Key */
+-              int     type = 0;
+-
+-              switch(event[i].code)
+-              {
+-                  case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+-                  case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+-                  case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break;
+-              }
+-
+-              if (event[i].value)
+-                  hid_linux_driver.mouse_button_state |= type;
+-              else
+-                  hid_linux_driver.mouse_button_state &= ~type;
+-              kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state);
+-          }
+-          else
+-          {
+-              hid_linux_driver.key_status[event[i].code] = event[i].value;
+-              hid_linux_key_event(event[i].value, event[i].code);
+-          }
+-      }
+-
+-      if (event[i].type == EV_REL || event[i].type == EV_ABS)
+-      {
+-          /* Mouse motion */
+-          int x = 0, y = 0, z = 0;
+-
+-          if (event[i].type == EV_REL)
+-              switch (event[i].code)
+-              {
+-                  case REL_X : x = event[i].value; break;
+-                  case REL_Y : y = event[i].value; break;
+-                  case REL_WHEEL : z = -event[i].value; break;
+-              }
+-          if (event[i].type == EV_ABS)
+-          {
+-              static int last_x = 1, last_y = 1;
+-              int px = 0, py = 0, l = 50;
+-              double div = 1;
+-              char *str = NULL;
+-
+-              str = hid_linux_xs_read("touchpad-limit");
+-              if (str)
+-                  l = strtol(str, NULL, 10);
+-              str = hid_linux_xs_read("touchpad-div");
+-              if (str)
+-                  div = strtol(str, NULL, 10) / 1000.;
+-
+-              switch (event[i].code)
+-              {
+-                  case ABS_X : x = event[i].value; break;
+-                  case ABS_Y : y = event[i].value; break;
+-              }
+-
+-              if (x)
+-              {
+-                  px = x - last_x;
+-                  last_x = x;
+-              }
+-              if (y)
+-              {
+-                  py = y - last_y;
+-                  last_y = y;
+-              }
+-
+-              x = (ABS(px) < l ? px : 0) / div;
+-              y = (ABS(py) < l ? py : 0) / div;
+-          }
+-
+-          kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state);
+-      }
++      if (event[i].type == EV_KEY)
++        {
++          if (event[i].code >= BTN_MOUSE)
++            {
++              /* Mouse Key */
++              int type = 0;
++
++              switch (event[i].code)
++                {
++                case BTN_LEFT:
++                  type = MOUSE_EVENT_LBUTTON;
++                  break;
++                case BTN_RIGHT:
++                  type = MOUSE_EVENT_RBUTTON;
++                  break;
++                case BTN_MIDDLE:
++                  type = MOUSE_EVENT_MBUTTON;
++                  break;
++                }
++
++              if (event[i].value)
++                linux_hid_driver.mouse_button_state |= type;
++              else
++                linux_hid_driver.mouse_button_state &= ~type;
++              kbd_mouse_event (0, 0, 0, linux_hid_driver.mouse_button_state);
++            }
++          else
++            {
++              linux_hid_driver.key_status[event[i].code] = event[i].value;
++              linux_hid_key_event (event[i].value, event[i].code);
++            }
++        }
++
++      if (event[i].type == EV_REL || event[i].type == EV_ABS)
++        {
++          /* Mouse motion */
++          int x = 0, y = 0, z = 0;
++
++          if (event[i].type == EV_REL)
++            switch (event[i].code)
++              {
++              case REL_X:
++                x = event[i].value;
++                break;
++              case REL_Y:
++                y = event[i].value;
++                break;
++              case REL_WHEEL:
++                z = -event[i].value;
++                break;
++              }
++          if (event[i].type == EV_ABS)
++            {
++              static int last_x = 1, last_y = 1;
++              int px = 0, py = 0, l = 50;
++              double div = 1;
++              char *str = NULL;
++
++              str = linux_hid_xs_read ("touchpad-limit");
++              if (str)
++                l = strtol (str, NULL, 10);
++              str = linux_hid_xs_read ("touchpad-div");
++              if (str)
++                div = strtol (str, NULL, 10) / 1000.;
++
++              switch (event[i].code)
++                {
++                case ABS_X:
++                  x = event[i].value;
++                  break;
++                case ABS_Y:
++                  y = event[i].value;
++                  break;
++                }
++
++              if (x)
++                {
++                  px = x - last_x;
++                  last_x = x;
++                }
++              if (y)
++                {
++                  py = y - last_y;
++                  last_y = y;
++                }
++
++              x = (ABS (px) < l ? px : 0) / div;
++              y = (ABS (py) < l ? py : 0) / div;
++            }
++
++          kbd_mouse_event (x, y, z, linux_hid_driver.mouse_button_state);
++        }
+     }
++  return 0;
+ }
+-void hid_linux_reset_keyboard(void)
++void
++hid_linux_reset_keyboard (void)
+ {
+-    int i = 0;
+-
+-    for (i = 0; i < 256; i++)
+-      if (hid_linux_driver.key_status[i])
+-      {
+-          hid_linux_key_inject(0, i);
+-          hid_linux_driver.key_status[i] = 0;
+-      }
++  int i = 0;
++
++  for (i = 0; i < 256; i++)
++    if (linux_hid_driver.key_status[i])
++      {
++        linux_hid_key_inject (0, i);
++        linux_hid_driver.key_status[i] = 0;
++      }
++}
++
++
++static int
++hid_linux_secure_read (int fd)
++{
++  struct input_event event[5];
++  int i = 0;
++  int read_sz = 0;
++
++  assert (linux_hid_driver.secure_key);
++
++  read_sz = read (fd, event, sizeof (event));
++
++  if (read_sz <= 0)
++    return -1;
++
++  for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
++    if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
++        event[i].value > 0)
++      linux_hid_driver.secure_key (keycode2ascii (event[i].code));
++
++  return 0;
+ }
+-static void hid_linux_redirect_fds(int *fd, IOHandler *cb)
++static int hid_linux_do_read (void *opaque)
+ {
+-    assert(fd != NULL);
++  int result;
++  int slot = (int) opaque;
+-    while (*fd != -1)
++  if (slot < 0)
++    return 0;
++  if (slot >= N_DEVS)
++    return 0;
++
++  if (linux_hid_driver.secure_key)
++    result = hid_linux_secure_read (linux_hid_driver.fds[slot]);
++  else
++    result = hid_linux_read (linux_hid_driver.fds[slot]);
++
++  if (result)
+     {
+-      qemu_set_fd_handler(*fd, cb, NULL, fd);
+-      fd++;
++      /* The read failed - stop watching and close the fd */
++
++      fprintf(stderr,"read failed on /dev/input/event%d fd=%d dropping it\n",slot,linux_hid_driver.fds[slot]);
++
++      qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL);
++      close (linux_hid_driver.fds[slot]);
++      linux_hid_driver.fds[slot] = -1;
+     }
++
++  return 0;
+ }
+-static void hid_linux_secure_read(void *opaque)
++
++void
++hid_linux_secure_keyboard (void (*cb) (int ascii))
+ {
+-    struct input_event  event[5];
+-    int                 i = 0;
+-    int                 read_sz = 0;
+-    int                 fd = *(int *)opaque;
+-
+-    assert(hid_linux_driver.secure_key);
+-
+-    read_sz = read(fd, event, sizeof (event));
+-    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+-      if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
+-              event[i].value > 0)
+-          hid_linux_driver.secure_key(keycode2ascii(event[i].code));
++  linux_hid_driver.secure_key = cb;
+ }
+-void hid_linux_secure_keyboard(void (*cb)(int ascii))
++
++static void
++set_handler (int slot, int onoff)
+ {
+-    hid_linux_driver.secure_key = cb;
+-    if (cb)
+-      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
+-              hid_linux_secure_read);
+-    else
+-      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
+-              hid_linux_read);
++
++  if (onoff)
++    qemu_set_fd_handler (linux_hid_driver.fds[slot], hid_linux_do_read, NULL,
++                         (void *) slot);
++  else
++    qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL);
++
+ }
+-static int hid_linux_grab_devices(int grab, int *fd)
++
++static int
++try_to_grab (int fd, int grab)
+ {
+-    int rc = 0;
+-    int try = 10;
++  int try = 10;
+-    assert(fd != NULL && *fd != -1);
+-    for (; *fd != -1; fd++)
++  while (try--)
+     {
+-      while (try--)
+-      {
+-          if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1)
+-          {
+-              char *er;
+-
+-              if (errno == EBUSY)
+-                  continue;
+-              er = strerror(errno);
+-              DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er);
+-              return 0;
+-          }
+-          else
+-              break;
+-      }
+-      assert(try);
+-
+-      DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd);
+-
+-      if (grab)
+-          qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd);
+-      else
+-          qemu_set_fd_handler(*fd, NULL, NULL, fd);
++      char *er;
++      if (!ioctl (fd, EVIOCGRAB, grab))
++        return 0;
++
++      if (errno != EBUSY)
++        {
++          er = strerror (errno);
++          DEBUG ("ioctl(%d, EVOCGRAB) failed, %s\n", fd, er);
++          return -1;
++        }
++
++      /*FIXME -- backoff */
+     }
+-    return 1;
++
++  return -1;
+ }
+-int hid_linux_grab_keyboard(int grab)
++
++static int
++do_grab (int type, int grab)
+ {
+-    return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds);
++  int i;
++  int fail = 0;
++
++  for (i = 0; i < N_DEVS; ++i)
++    {
++      if (linux_hid_driver.fds[i] < 0)
++        continue;
++      if (linux_hid_driver.types[i] != type)
++        continue;
++
++      if (try_to_grab (linux_hid_driver.fds[i], grab))
++        {
++          fail++;
++          fprintf (stderr, "Failed to grab /dev/input/event%d\n", i);
++        }
++
++      set_handler (i, grab);
++
++    }
++
++  return fail ? 0 : 1;
+ }
+-int hid_linux_grab_mouse(int grab)
++int
++hid_linux_grab_keyboard (int grab)
+ {
+-    return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds);
++  linux_hid_driver.keyboard_grabbed = grab; /*So new devices know which mode to be in */
++  return do_grab (HID_TYPE_KEYBOARD, grab);
+ }
+-static int hid_linux_open_timeout(const char *path, int flags)
++int
++hid_linux_grab_mouse (int grab)
+ {
+-   int        try = 10;
+-   int  fd = 0;
+-
+-   while (try-- && ((fd = open(path, flags)) == -1))
+-       usleep(100000); /* 10 ms */
+-   if (try == 0)
+-       return 0;
+-   return fd == -1 ? 0 : fd;
++  linux_hid_driver.mouse_grabbed = grab; /*So new devices know which mode to be in */
++  return do_grab (HID_TYPE_MOUSE, grab);
+ }
+-static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2)
++
++static int
++consider_device (int slot)
+ {
+-   int        try = 10;
++  int fd = linux_hid_driver.fds[slot];
+-   while (try-- && ioctl(fd, arg1, arg2) == -1)
+-       usleep(100000); /* 10 ms */
+-   if (try == 0)
+-       return 0;
+-   return 1;
+-}
++  char name[128] = { 0 };
++  struct input_id id;
+-void hid_linux_probe(int grab)
+-{
+-    int                 i = 0, j = 0, c = 0;
+-    int                 fd = -1;
+-    int                 keyboard = 0, mouse = 0;
+-    char                path[strlen(EVENT_PATH) + 3];
+-    char                name[128];
+-    int                       *controllers;
+-    struct input_id     id;
+-    struct stat       st;
+-
+-    while (1)
++  if (ioctl (fd, EVIOCGNAME (sizeof (name)), name) == -1)
++    return -1;
++  if (ioctl (fd, EVIOCGID, &id) == -1)
++    return -1;
++
++  if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
++    return -1;
++
++  name[sizeof (name) - 1] = 0;
++
++
++
++  if (strcasestr (name, "keyboard"))
++    {
++      fprintf (stderr, "/dev/input/event%d added keyboard on fd %d (%s)\n",
++               slot, fd, name);
++      linux_hid_driver.types[slot] = HID_TYPE_KEYBOARD;
++
++      set_handler (slot, linux_hid_driver.keyboard_grabbed);
++
++    }
++  else
+     {
+-        if (fd != -1)
+-            close(fd);
++      fprintf (stderr, "/dev/input/event%d added mouse on fd %d (%s)\n",
++               slot, fd, name);
++      linux_hid_driver.types[slot] = HID_TYPE_MOUSE;
++      set_handler (slot, linux_hid_driver.mouse_grabbed);
++    }
+-      sprintf(path, "%s%i", EVENT_PATH, i++);
+-      if (i>=HID_LINUX_MAX_DEV_NO)
+-              break;
++  return 0;
++}
+-      if (stat(path, &st) == -1)
+-              continue;
+-      for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++)
+-          if (!strcmp(hid_linux_driver.controller_paths[c], path))
+-              break;
+-      assert(c != HID_LINUX_MAX_DEV);
+-      if (hid_linux_driver.controller_paths[c])
+-          continue;
+-      if ((fd = open(path, O_RDONLY)) == -1)
+-          break;
+-      if (ioctl(fd, EVIOCGNAME(128), name) == -1)
+-      {
+-          DEBUG("Input get name failed on %s\n", path);
+-            break;
+-      }
++static void
++hid_linux_scan (void *opaque)
++{
++  char name[128];
++  int i;
+-        if (ioctl(fd, EVIOCGID, &id) == -1)
+-      {
+-          DEBUG("Input get id failed on %s\n", path);
+-            continue;
+-      }
++  fprintf (stderr, "hid_linux_scan()\n");
+-        /* Only get devices on usb and i8042 */
+-        if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
+-            continue;
+-        if (strcasestr(name, "keyboard"))
+-        {
+-            DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype);
+-            controllers = hid_linux_driver.keyboard_fds;
+-        }
+-        else
+-        {
+-            DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype);
+-            controllers = hid_linux_driver.mouse_fds;
+-        }
++  for (i = 0; i < N_DEVS; ++i)
++    {
+-      for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++)
+-          ;
+-      assert(j != (HID_LINUX_MAX_DEV / 2));
++/* Do We already have this device open and working */
++      if (linux_hid_driver.fds[i] >= 0)
++        continue;
+-      controllers[j] = fd;
+-      controllers[j + 1] = -1;
++      sprintf (name, "/dev/input/event%d", i);
+-      if (grab)
+-      {
+-          if (!hid_linux_grab_devices(1, controllers + j))
+-          {
+-              DEBUG("Grabing failed, try next time...\n");
+-              controllers[j] = -1;
+-              break;
+-          }
+-      }
++/* Check to see if we can open it */
++      linux_hid_driver.fds[i] = open (name, O_RDONLY);
++      if (linux_hid_driver.fds[i] < 0)
++        continue;               /* No */
+-      hid_linux_driver.controller_paths[c] = strdup(path);
+-      hid_linux_driver.controller_paths[c + 1] = NULL;
++/* Switch to NBIO*/
++      {
++        long arg;
++        arg = fcntl (linux_hid_driver.fds[i], F_GETFL, arg);
++        arg |= O_NONBLOCK;
++        fcntl (linux_hid_driver.fds[i], F_SETFL, arg);
++      }
++
++/* See if we like it and set up input notify if we do*/
++      if (consider_device (i))
++        {
++          close (linux_hid_driver.fds[i]);
++          linux_hid_driver.fds[i] = -1;
++          continue;
++        }
+-      fd = -1;
+     }
+-    if (fd != -1)
+-      close(fd);
++
++/* Schedule ourselves */
++  qemu_mod_timer (linux_hid_driver.scan_timer, qemu_get_clock (rt_clock) + 2000);
++
+ }
+-void hid_linux_init(void)
++
++
++void
++hid_linux_init (void)
+ {
+-    hid_linux_driver.keyboard_fds[0] = -1;
+-    hid_linux_driver.mouse_fds[0] = -1;
+-    hid_linux_driver.controller_paths[0] = NULL;
++  int i;
+-    while (hid_linux_driver.keyboard_fds[0] == -1)
+-    {
+-      hid_linux_probe(0);
+-      usleep(100000); /* 10 ms */
+-    }
++  for (i = 0; i < N_DEVS; ++i)
++    linux_hid_driver.fds[i] = -1;
++
++  linux_hid_driver.keyboard_grabbed = 0;
++  linux_hid_driver.mouse_grabbed = 0;
++
++/* Kick off the periodic scan for devices */
++  if (!linux_hid_driver.scan_timer)
++    linux_hid_driver.scan_timer = qemu_new_timer (rt_clock, hid_linux_scan, NULL);
++
++  linux_hid_scan ();
+ }
index 222690b2a439c151d00773accd77cabb27f29bf1..f8289386a93007f99bb329120f73f4dfda03d127 100644 (file)
@@ -22,3 +22,4 @@ audio-volume-control
 dont-remap-passthrough-mmio
 fix-drop-mouse-keyboard
 fix-imobile-mouse
+new-input-code