aura  0.1
All Data Structures Functions Variables Modules Pages
usb-helpers.c
1 #include <aura/aura.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <libusb.h>
7 #include <aura/usb_helpers.h>
8 
9 
10 void ncusb_print_libusb_transfer(struct libusb_transfer *p_t)
11 {
12  if ( NULL == p_t){
13  slog(4, SLOG_INFO, "No libusb_transfer...");
14  }
15  else {
16  slog(4, SLOG_INFO, "libusb_transfer structure:");
17  slog(4, SLOG_INFO, "flags =%x ", p_t->flags);
18  slog(4, SLOG_INFO, "endpoint=%x ", p_t->endpoint);
19  slog(4, SLOG_INFO, "type =%x ", p_t->type);
20  slog(4, SLOG_INFO, "timeout =%d ", p_t->timeout);
21 // length, and buffer are commands sent to the device
22  slog(4, SLOG_INFO, "length =%d ", p_t->length);
23  slog(4, SLOG_INFO, "actual_length =%d ", p_t->actual_length);
24  slog(4, SLOG_INFO, "buffer =%p ", p_t->buffer);
25  slog(4, SLOG_INFO, "status =%d/%d ", p_t->status, LIBUSB_TRANSFER_OVERFLOW);
26  }
27  return;
28 }
29 
30 
31 int ncusb_match_string(libusb_device_handle *dev, int index, const char* string)
32 {
33  unsigned char tmp[256];
34  int ret = libusb_get_string_descriptor_ascii(dev, index, tmp, 256);
35  if (ret <= 0)
36  return 0;
37 
38  slog(4, SLOG_DEBUG, "cmp idx %d str %s vs %s", index, tmp, string);
39  if (string == NULL)
40  return 1; /* NULL matches anything */
41  return (strcmp(string, (char*) tmp)==0);
42 }
43 
44 
45 struct libusb_device_handle *ncusb_try_device(struct libusb_context *ctx,
46  libusb_device *device,
47  int vid, int pid,
48  const char *vendor_name,
49  const char *product_name,
50  const char *serial)
51 {
52  int err;
53  libusb_device_handle *handle;
54  struct libusb_device_descriptor desc;
55 
56  err = libusb_open(device, &handle);
57  if (err)
58  return NULL;
59 
60  err = libusb_get_device_descriptor( device, &desc );
61  if (err)
62  goto errclose;
63 
64  if ( desc.idVendor == vid && desc.idProduct == pid &&
65  ncusb_match_string(handle, desc.iManufacturer, vendor_name) &&
66  ncusb_match_string(handle, desc.iProduct, product_name) &&
67  ncusb_match_string(handle, desc.iSerialNumber, serial)
68  )
69  {
70  return handle;
71  }
72 
73 errclose:
74  libusb_close(handle);
75  return NULL;
76 }
77 
78 struct libusb_device_handle *ncusb_find_and_open(struct libusb_context *ctx,
79  int vendor, int product,
80  const char *vendor_name,
81  const char *product_name,
82  const char *serial)
83 {
84  libusb_device_handle *found = NULL;
85  libusb_device **list;
86  ssize_t cnt = libusb_get_device_list(ctx, &list);
87  ssize_t i = 0;
88 
89  if (cnt < 0){
90  slog(0, SLOG_ERROR, "no usb devices found" );
91  return NULL;
92  }
93 
94  for(i = 0; i < cnt; i++) {
95  int err = 0;
96  libusb_device *device = list[i];
97  struct libusb_device_descriptor desc;
98  libusb_device_handle *handle;
99  err = libusb_open(device, &handle);
100  if (err)
101  continue;
102 
103  int r = libusb_get_device_descriptor( device, &desc );
104  if (r) {
105  libusb_close(handle);
106  continue;
107  }
108 
109  if ( desc.idVendor == vendor && desc.idProduct == product &&
110  ncusb_match_string(handle, desc.iManufacturer, vendor_name) &&
111  ncusb_match_string(handle, desc.iProduct, product_name) &&
112  ncusb_match_string(handle, desc.iSerialNumber, serial)
113  )
114  {
115  found = handle;
116  }
117 
118  if (found)
119  break;
120 
121  }
122  libusb_free_device_list(list, 1);
123 
124  return found;
125 }
126 
127 
128 static int hotplug_callback_fn(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data)
129 {
130  struct ncusb_devwatch_data* d = user_data;
131  struct libusb_device_handle *hndl = ncusb_try_device(ctx, device,
132  d->vid, d->pid,
133  d->vendor, d->product, d->serial);
134  if (hndl) {
135  d->device_found_func(hndl, d->arg);
136  /* Thanks, we're good from now on */
137  return 1;
138  }
139 
140  return 0;
141 }
142 
143 static void pollfd_added_cb(int fd, short events, void *user_data)
144 {
145  slog(4, SLOG_DEBUG, "usb-helpers: Adding fd %d evts %x to node", fd, events);
146  aura_add_pollfds(user_data, fd, events);
147 }
148 
149 static void pollfd_removed_cb(int fd, void *user_data)
150 {
151  slog(4, SLOG_DEBUG, "usb-helpers: Removing fd %d from node", fd);
152  aura_del_pollfds(user_data, fd);
153 }
154 
155 void ncusb_start_descriptor_watching(struct aura_node *node, libusb_context *ctx)
156 {
157  /* Fetch all existing descriptors from the library */
158  const struct libusb_pollfd** fds_data = libusb_get_pollfds(ctx);
159  const struct libusb_pollfd** fds = fds_data;
160 
161  while (*fds != NULL) {
162  pollfd_added_cb((*fds)->fd, (*fds)->events, node);
163  fds++;
164  }
165  free(fds_data);
166  /* Register a callback */
167  libusb_set_pollfd_notifiers(ctx, pollfd_added_cb, pollfd_removed_cb, node);
168 }
169 
170 int ncusb_watch_for_device(libusb_context *ctx,
171  struct ncusb_devwatch_data* dwatch)
172 {
173  return libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
174  LIBUSB_HOTPLUG_ENUMERATE, dwatch->vid, dwatch->pid,
175  LIBUSB_HOTPLUG_MATCH_ANY,
176  hotplug_callback_fn,
177  dwatch, NULL);
178 }