Gammu internals  1.38.0
usb.c
Go to the documentation of this file.
1 
11 #include <gammu-config.h>
12 
13 #include <ctype.h>
14 #include <string.h>
15 
16 #ifdef LIBUSB_FOUND
17 #include <libusb.h>
18 #endif
19 
20 #include "../../gsmstate.h"
21 #if defined(GSM_ENABLE_DKU2PHONET) && defined(GSM_ENABLE_USBDEVICE)
22 #include "usb.h"
23 
24 #include "../../gsmcomon.h"
25 
26 #include "../../../helper/string.h"
27 
31 #define NOKIA_VENDOR_ID 0x0421
32 
36 #define USB_CDC_CLASS 0x02
37 
40 #define USB_CDC_FBUS_SUBCLASS 0xfe
41 
45 struct cdc_union_desc {
46  u_int8_t bLength;
47  u_int8_t bDescriptorType;
48  u_int8_t bDescriptorSubType;
49 
50  u_int8_t bMasterInterface0;
51  u_int8_t bSlaveInterface0;
52 } __attribute__ ((packed));
53 
54 struct cdc_extra_desc {
55  u_int8_t bLength;
56  u_int8_t bDescriptorType;
57  u_int8_t bDescriptorSubType;
58 } __attribute__ ((packed));
59 
60 /* CDC header types (bDescriptorSubType) */
61 #define CDC_HEADER_TYPE 0x00
62 #define CDC_UNION_TYPE 0x06
63 #define CDC_FBUS_TYPE 0x15
64 
65 /* Interface descriptor (bDescriptorType) */
66 #define USB_DT_CS_INTERFACE 0x24
67 
68 
69 GSM_Error GSM_USB_Error(GSM_StateMachine *s, enum libusb_error code)
70 {
71  switch (code) {
72  case LIBUSB_SUCCESS:
73  smprintf(s, "Success (no error)\n");
74  return ERR_NONE;
75 
76  case LIBUSB_ERROR_IO:
77  smprintf(s, "Input/output error\n");
78  return ERR_DEVICEWRITEERROR;
79 
80  case LIBUSB_ERROR_INVALID_PARAM:
81  smprintf(s, "Invalid parameter\n");
82  return ERR_BUG;
83 
84  case LIBUSB_ERROR_ACCESS:
85  smprintf(s, "Access denied (insufficient permissions)\n");
87 
88  case LIBUSB_ERROR_NO_DEVICE:
89  smprintf(s, "No such device (it may have been disconnected)\n");
90  return ERR_DEVICENOTEXIST;
91 
92  case LIBUSB_ERROR_NOT_FOUND:
93  smprintf(s, "Entity not found\n");
94  return ERR_DEVICENOTEXIST;
95 
96  case LIBUSB_ERROR_BUSY:
97  smprintf(s, "Resource busy\n");
98  return ERR_DEVICEBUSY;
99 
100  case LIBUSB_ERROR_TIMEOUT:
101  smprintf(s, "Operation timed out\n");
102  return ERR_TIMEOUT;
103 
104  case LIBUSB_ERROR_OVERFLOW:
105  smprintf(s, "Overflow\n");
106  return ERR_BUG;
107 
108  case LIBUSB_ERROR_PIPE:
109  smprintf(s, "Pipe error\n");
110  return ERR_BUG;
111 
112  case LIBUSB_ERROR_INTERRUPTED:
113  smprintf(s, "System call interrupted (perhaps due to signal)\n");
114  return ERR_BUG;
115 
116  case LIBUSB_ERROR_NO_MEM:
117  smprintf(s, "Insufficient memory\n");
118  return ERR_MOREMEMORY;
119 
120  case LIBUSB_ERROR_NOT_SUPPORTED:
121  smprintf(s, "Operation not supported or unimplemented on this platform\n");
122  return ERR_NOTSUPPORTED;
123 
124  case LIBUSB_ERROR_OTHER:
125  smprintf(s, "Other error\n");
126  return ERR_UNKNOWN;
127 
128  default:
129  smprintf(s, "Unknown error\n");
130  return ERR_UNKNOWN;
131  }
132 }
133 
134 GSM_Error GSM_USB_ParseDevice(GSM_StateMachine *s, int *vendor, int *product, int *bus, int *deviceid, char **serial)
135 {
136  char *endptr, *next;
137  int num;
138 
139  *vendor = -1;
140  *product = -1;
141  *bus = -1;
142  *deviceid = -1;
143  *serial = NULL;
144 
145  if (s->CurrentConfig->Device[0] == 0) {
146  return ERR_NONE;
147  }
148 
149  if (strncasecmp(s->CurrentConfig->Device, "serial:", 7) == 0) {
150  *serial = s->CurrentConfig->Device + 7;
151  } else if (strncasecmp(s->CurrentConfig->Device, "serial :", 8) == 0) {
152  *serial = s->CurrentConfig->Device + 8;
153  }
154  if (*serial != NULL) {
155  while (isspace(**serial) && **serial != 0) {
156  *serial = *serial + 1;
157  }
158  smprintf(s, "Will search for serial = %s\n", *serial);
159  return ERR_NONE;
160  }
161 
162  if (!isdigit(s->CurrentConfig->Device[0])) {
163  return ERR_NONE;
164  }
165 
166  num = strtol(s->CurrentConfig->Device, &endptr, 10);
167  if (*endptr == 'x') {
168  num = strtol(s->CurrentConfig->Device, &endptr, 16);
169  }
170  if (*endptr == 0) {
171  *deviceid = num;
172  smprintf(s, "Will search for deviceid = %d\n", *deviceid);
173  return ERR_NONE;
174  }
175  if (*endptr == ':') {
176  *vendor = num;
177  next = endptr + 1;
178  num = strtol(next, &endptr, 10);
179  if (*endptr == 'x') {
180  num = strtol(next, &endptr, 16);
181  }
182  *product = num;
183  smprintf(s, "Will search for vendor = 0x%04x, deviceid = 0x%04x\n", *vendor, *product);
184  if (*endptr == 0) {
185  return ERR_NONE;
186  } else {
187  return ERR_UNKNOWN;
188  }
189  }
190  if (*endptr == '.') {
191  *bus = num;
192  next = endptr + 1;
193  num = strtol(next, &endptr, 10);
194  if (*endptr == 'x') {
195  num = strtol(next, &endptr, 16);
196  }
197  *deviceid = num;
198  smprintf(s, "Will search for bus = %d, deviceid = %d\n", *bus, *deviceid);
199  if (*endptr == 0) {
200  return ERR_NONE;
201  } else {
202  return ERR_UNKNOWN;
203  }
204  }
205  return ERR_UNKNOWN;
206 }
207 
208 GSM_Error GSM_USB_Probe(GSM_StateMachine *s, GSM_USB_Match_Function matcher)
209 {
210  libusb_device **devs;
211  libusb_device *dev;
212  GSM_Device_USBData *d = &s->Device.Data.USB;
213  ssize_t cnt;
214  int rc;
215  int i = 0;
216  struct libusb_device_descriptor desc;
217  struct libusb_config_descriptor *config;
218  GSM_Error error;
219  int vendor = -1, product = -1, bus = -1, deviceid = -1;
220  char *serial = NULL;
221  char buffer[300];
222  gboolean do_match;
223 
224  /* Device selection */
225  GSM_USB_ParseDevice(s, &vendor, &product, &bus, &deviceid, &serial);
226  do_match = (vendor != -1 || product != -1 || bus != -1 || deviceid != -1 || serial != NULL);
227 
228  cnt = libusb_get_device_list(d->context, &devs);
229  if (cnt < 0) {
230  smprintf(s, "Failed to list USB devices (%d)!\n", (int)cnt);
231  return GSM_USB_Error(s, cnt);
232  }
233 
234  /* Check all devices */
235  i = 0;
236  while ((dev = devs[i++]) != NULL) {
237  rc = libusb_get_device_descriptor(dev, &desc);
238  if (rc < 0) {
239  smprintf(s, "Failed to get device descriptor (%d)!\n", rc);
240  GSM_USB_Error(s, rc);
241  continue;
242  }
243 
244  smprintf(s, "Checking %04x:%04x (bus %d, device %d)\n",
245  desc.idVendor, desc.idProduct,
246  libusb_get_bus_number(dev), libusb_get_device_address(dev));
247 
248  if (do_match) {
249  if (vendor != -1 && vendor != desc.idVendor) {
250  smprintf(s, "Vendor does not match requested 0x%04x, ignoring\n", vendor);
251  continue;
252  }
253  if (product != -1 && product != desc.idProduct) {
254  smprintf(s, "Product does not match requested 0x%04x, ignoring\n", product);
255  continue;
256  }
257  if (bus != -1 && bus != libusb_get_bus_number(dev)) {
258  smprintf(s, "Bus does not match requested %d, ignoring\n", bus);
259  continue;
260  }
261  if (deviceid != -1 && deviceid != libusb_get_device_address(dev)) {
262  smprintf(s, "Device address does not match requested %d, ignoring\n", deviceid);
263  continue;
264  }
265  if (serial != NULL && desc.iSerialNumber) {
266  rc = libusb_open(dev, &d->handle);
267  if (rc != 0) {
268  smprintf(s, "Failed to read serial!\n");
269  } else {
270  libusb_get_string_descriptor_ascii(d->handle, desc.iSerialNumber, buffer, sizeof(buffer) - 1);
271  smprintf(s, "Device serial: %s\n", buffer);
272  libusb_close(d->handle);
273  if (strcasecmp(buffer, serial) != 0) {
274  smprintf(s, "Device serial does not match requested %s, ignoring\n", serial);
275  continue;
276  }
277  }
278  }
279  }
280 
281  if (matcher(s, dev, &desc)) {
282  break;
283  }
284  }
285 
286  if (dev == NULL) {
287  error = ERR_DEVICENOTEXIST;
288  goto done;
289  }
290 
291  smprintf(s, "Trying to open device, config=%d, c_iface=%d, c_alt=%d, d_iface=%d, d_alt=%d\n",
293 
294  rc = libusb_open(dev, &d->handle);
295  if (rc != 0) {
296  d->handle = NULL;
297  error = GSM_USB_Error(s, rc);
298  goto done;
299  }
300 
301  /* Unhook kernel driver */
302  rc = libusb_get_active_config_descriptor(dev, &config);
303  if (rc != 0) {
304  smprintf(s, "Failed to get current device configuration!\n");
305  libusb_close(d->handle);
306  d->handle = NULL;
307  error = GSM_USB_Error(s, rc);
308  goto done;
309  }
310 
311  /* Do we have to change configuration? */
312  if (config->bConfigurationValue != d->configuration) {
313  smprintf(s, "Will change configuration, unhooking all interfaces!\n");
314  for (i = 0; i < config->bNumInterfaces; i++) {
315  if (libusb_kernel_driver_active(d->handle, i) == 1) {
316  smprintf(s, "Detaching kernel driver from interface %d\n", i);
317  rc = libusb_detach_kernel_driver(d->handle, i);
318  if (rc != 0) {
319  smprintf(s, "Failed to detach kernel driver!\n");
320  libusb_free_config_descriptor(config);
321  libusb_close(d->handle);
322  d->handle = NULL;
323  error = GSM_USB_Error(s, rc);
324  goto done;
325  }
326  }
327  }
328 
329 
330  smprintf(s, "Configuring USB device...\n");
331  rc = libusb_set_configuration(d->handle, d->configuration);
332  if (rc != 0) {
333  smprintf(s, "Failed to set device configuration %d (%d)!\n", d->configuration, rc);
334  libusb_free_config_descriptor(config);
335  libusb_close(d->handle);
336  d->handle = NULL;
337  error = GSM_USB_Error(s, rc);
338  goto done;
339  }
340  } else {
341  smprintf(s, "Configuration change not required, unhooking only required interfaces!\n");
342 
343  if (libusb_kernel_driver_active(d->handle, d->control_iface) == 1) {
344  smprintf(s, "Detaching kernel driver from interface %d\n", d->control_iface);
345  rc = libusb_detach_kernel_driver(d->handle, d->control_iface);
346  if (rc != 0) {
347  smprintf(s, "Failed to detach kernel driver!\n");
348  libusb_free_config_descriptor(config);
349  libusb_close(d->handle);
350  d->handle = NULL;
351  error = GSM_USB_Error(s, rc);
352  goto done;
353  }
354  }
355 
356  if (libusb_kernel_driver_active(d->handle, d->data_iface) == 1) {
357  smprintf(s, "Detaching kernel driver from interface %d\n", d->data_iface);
358  rc = libusb_detach_kernel_driver(d->handle, d->data_iface);
359  if (rc != 0) {
360  smprintf(s, "Failed to detach kernel driver!\n");
361  libusb_free_config_descriptor(config);
362  libusb_close(d->handle);
363  d->handle = NULL;
364  error = GSM_USB_Error(s, rc);
365  goto done;
366  }
367  }
368  }
369  libusb_free_config_descriptor(config);
370 
371  smprintf(s, "Claiming USB control interface...\n");
372  rc = libusb_claim_interface(d->handle, d->control_iface);
373  if (rc != 0) {
374  smprintf(s, "Failed to set claim control interface %d (%d)!\n", d->control_iface, rc);
375  libusb_close(d->handle);
376  d->handle = NULL;
377  error = GSM_USB_Error(s, rc);
378  goto done;
379  }
380 
381  smprintf(s, "Configuring USB control interface...\n");
382  rc = libusb_set_interface_alt_setting(d->handle, d->control_iface, d->control_altsetting);
383  if (rc != 0) {
384  smprintf(s, "Failed to set control alt setting %d (%d)!\n", d->control_altsetting, rc);
385  libusb_close(d->handle);
386  d->handle = NULL;
387  error = GSM_USB_Error(s, rc);
388  goto done;
389  }
390 
391  smprintf(s, "Claiming USB data interface...\n");
392  rc = libusb_claim_interface(d->handle, d->data_iface);
393  if (rc != 0) {
394  smprintf(s, "Failed to set claim data interface %d (%d)!\n", d->data_iface, rc);
395  libusb_close(d->handle);
396  d->handle = NULL;
397  error = GSM_USB_Error(s, rc);
398  goto done;
399  }
400 
401  smprintf(s, "Configuring USB data interface...\n");
402  rc = libusb_set_interface_alt_setting(d->handle, d->data_iface, d->data_altsetting);
403  if (rc != 0) {
404  smprintf(s, "Failed to set data alt setting %d (%d)!\n", d->data_altsetting, rc);
405  libusb_close(d->handle);
406  d->handle = NULL;
407  error = GSM_USB_Error(s, rc);
408  goto done;
409  }
410 
411  smprintf(s, "Connected!\n");
412  error = ERR_NONE;
413 
414 done:
415 
416  return error;
417 }
418 
419 GSM_Error GSM_USB_Init(GSM_StateMachine *s)
420 {
421  GSM_Device_USBData *d = &s->Device.Data.USB;
422  int rc;
423 
424  d->handle = NULL;
425 
426  rc = libusb_init(&d->context);
427  if (rc != 0) {
428  d->context = NULL;
429  smprintf(s, "Failed to init libusb (%d)!\n", rc);
430  return GSM_USB_Error(s, rc);
431  }
432 
433  return ERR_NONE;
434 }
435 
436 GSM_Error GSM_USB_Terminate(GSM_StateMachine *s)
437 {
438  GSM_Device_USBData *d = &s->Device.Data.USB;
439  int rc;
440 
441  if (d->handle != NULL) {
442  rc = libusb_set_interface_alt_setting(d->handle, d->data_iface, d->data_idlesetting);
443  if (rc != 0) {
444  smprintf(s, "Failed to set idle settings\n");
445  return GSM_USB_Error(s, rc);
446  }
447  rc = libusb_release_interface(d->handle, d->control_iface);
448  if (rc != 0) {
449  smprintf(s, "Failed to release control interface\n");
450  return GSM_USB_Error(s, rc);
451  }
452  rc = libusb_release_interface(d->handle, d->data_iface);
453  if (rc != 0) {
454  smprintf(s, "Failed to release data interface\n");
455  return GSM_USB_Error(s, rc);
456  }
457  libusb_close(d->handle);
458  }
459 
460  libusb_exit(d->context);
461 
462  d->handle = NULL;
463  d->context = NULL;
464 
465  return ERR_NONE;
466 }
467 
468 int GSM_USB_Read(GSM_StateMachine *s, void *buf, size_t nbytes)
469 {
470  GSM_Device_USBData *d = &s->Device.Data.USB;
471  int rc = LIBUSB_ERROR_TIMEOUT, ret = 0, repeat = 0;
472 
473  while (repeat < 10 && (rc == LIBUSB_ERROR_TIMEOUT || rc == LIBUSB_ERROR_INTERRUPTED || rc == LIBUSB_ERROR_OTHER || rc == LIBUSB_ERROR_NO_MEM)) {
474  rc = libusb_bulk_transfer(d->handle, d->ep_read, buf, nbytes, &ret, 1000);
475  /* This seems to be some strange failure on partial data transfer */
476  if (rc == LIBUSB_ERROR_OTHER && ret != 0) {
477  smprintf(s, "Other error while reading, but got some data\n");
478  rc = 0;
479  break;
480  }
481  if (rc == LIBUSB_ERROR_TIMEOUT && ret != 0) {
482  smprintf(s, "Timeout while reading, but got some data\n");
483  rc = 0;
484  break;
485  }
486  if (rc != 0) {
487  smprintf(s, "Failed to read from usb (%d)!\n", rc);
488  GSM_USB_Error(s, rc);
489  }
490  repeat++;
491  usleep(1000);
492  }
493  if (rc != 0) {
494  return -1;
495  }
496  return ret;
497 }
498 
499 int GSM_USB_Write(GSM_StateMachine *s, const void *buf, size_t nbytes)
500 {
501  GSM_Device_USBData *d = &s->Device.Data.USB;
502  int rc = LIBUSB_ERROR_TIMEOUT, ret = 0, repeat = 0;
503 
504  while (repeat < 10 && (rc == LIBUSB_ERROR_TIMEOUT || rc == LIBUSB_ERROR_INTERRUPTED || rc == LIBUSB_ERROR_OTHER || rc == LIBUSB_ERROR_NO_MEM)) {
505  rc = libusb_bulk_transfer(d->handle, d->ep_write, (void *)buf, nbytes, &ret, 1000);
506  /* This seems to be some strange failure on partial data transfer */
507  if (rc == LIBUSB_ERROR_OTHER && ret != 0) {
508  smprintf(s, "Other error while writing, but got some data\n");
509  rc = 0;
510  break;
511  }
512  if (rc == LIBUSB_ERROR_TIMEOUT && ret != 0) {
513  smprintf(s, "Timeout while write, but some data were written\n");
514  rc = 0;
515  break;
516  }
517  if (rc != 0) {
518  smprintf(s, "Failed to write to usb (%d)!\n", rc);
519  GSM_USB_Error(s, rc);
520  }
521  repeat++;
522  usleep(1000);
523  }
524  if (rc != 0) {
525  return -1;
526  }
527  return ret;
528 }
529 
533 gboolean FBUSUSB_Match(GSM_StateMachine *s, libusb_device *dev, struct libusb_device_descriptor *desc)
534 {
535  int c, i, a;
536  int rc;
537  struct libusb_config_descriptor *config;
538  GSM_Device_USBData *d = &s->Device.Data.USB;
539  const unsigned char *buffer;
540  int buflen;
541  struct cdc_extra_desc *extra_desc;
542  struct cdc_union_desc *union_desc = NULL;
543  const struct libusb_endpoint_descriptor *ep1, *ep2;
544 
545  /* We care only about Nokia */
546  if (desc->idVendor != NOKIA_VENDOR_ID) return FALSE;
547 
548  /* Find configuration we want */
549  for (c = 0; c < desc->bNumConfigurations; c++) {
550  rc = libusb_get_config_descriptor(dev, c, &config);
551  if (rc != 0) {
552  GSM_USB_Error(s, rc);
553  return FALSE;
554  }
555  /* Find interface we want */
556  for (i = 0; i < config->bNumInterfaces; i++) {
557  for (a = 0; a < config->interface[i].num_altsetting; a++) {
558  /* We want only CDC FBUS settings */
559  if (config->interface[i].altsetting[a].bInterfaceClass == USB_CDC_CLASS
560  && config->interface[i].altsetting[a].bInterfaceSubClass == USB_CDC_FBUS_SUBCLASS
561  ) {
562  /* We have it */
563  goto found_control;
564  }
565  }
566  }
567  libusb_free_config_descriptor(config);
568  }
569  return FALSE;
570 found_control:
571  /* Remember configuration which is interesting */
572  d->configuration = config->bConfigurationValue;
573 
574  /* Remember control interface */
575  d->control_iface = config->interface[i].altsetting[a].bInterfaceNumber;
576  d->control_altsetting = config->interface[i].altsetting[a].bAlternateSetting;
577 
578  /* Find out data interface */
579 
580  /* Process extra descriptors */
581  buffer = config->interface[i].altsetting[a].extra;
582  buflen = config->interface[i].altsetting[a].extra_length;
583 
584  /* Each element has length as first byte and type as second */
585  while (buflen > 0) {
586  extra_desc = (struct cdc_extra_desc *)buffer; /* Convenience */
587  if (extra_desc->bDescriptorType != USB_DT_CS_INTERFACE) {
588  smprintf(s, "Extra CDC header: %d\n", extra_desc->bDescriptorType);
589  goto next_el;
590  }
591 
592  switch (extra_desc->bDescriptorSubType) {
593  case CDC_UNION_TYPE:
594  union_desc = (struct cdc_union_desc *)buffer;
595  break;
596  case CDC_HEADER_TYPE:
597  case CDC_FBUS_TYPE:
598  /* We know these, but ignore them */
599  break;
600  default:
601  smprintf(s, "Extra CDC subheader: %d\n", extra_desc->bDescriptorSubType);
602  break;
603  }
604 next_el:
605  buflen -= extra_desc->bLength;
606  buffer += extra_desc->bLength;
607  }
608 
609  if (union_desc == NULL) {
610  smprintf(s, "Failed to find data end points!\n");
611  libusb_free_config_descriptor(config);
612  return FALSE;
613  }
614  d->data_iface = union_desc->bSlaveInterface0;
615  d->data_altsetting = -1;
616  d->data_idlesetting = -1;
617 
618  /* Find out end points and settings from data_iface */
619  for (i = 0; i < config->bNumInterfaces; i++) {
620  for (a = 0; a < config->interface[i].num_altsetting; a++) {
621  /* We want only data interface we found */
622  if (config->interface[i].altsetting[a].bInterfaceNumber == d->data_iface) {
623  /* We have it */
624  if (config->interface[i].altsetting[a].bNumEndpoints == 2) {
625  /* Active config */
626  ep1 = &(config->interface[i].altsetting[a].endpoint[0]);
627  ep2 = &(config->interface[i].altsetting[a].endpoint[1]);
628  if ((ep1->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK ||
629  (ep2->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK) {
630  /* We want only bulk transfer */
631  continue;
632  }
633  if ((ep1->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN &&
634  (ep2->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
635  d->ep_read = ep1->bEndpointAddress;
636  d->ep_write = ep2->bEndpointAddress;
637  } else if ((ep2->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN &&
638  (ep1->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
639  d->ep_read = ep2->bEndpointAddress;
640  d->ep_write = ep1->bEndpointAddress;
641  } else {
642  continue;
643  }
644  d->data_altsetting = config->interface[i].altsetting[a].bAlternateSetting;
645  } else if (config->interface[i].altsetting[a].bNumEndpoints == 0) {
646  /* Idle config */
647  d->data_idlesetting = config->interface[i].altsetting[a].bAlternateSetting;
648  }
649  }
650  }
651  }
652  if (d->data_altsetting == -1 || d->data_idlesetting == -1) {
653  smprintf(s, "Failed to find data interface (%d)\n", d->data_iface);
654  libusb_free_config_descriptor(config);
655  return FALSE;
656  }
657 
658  /* Free config descriptor */
659  libusb_free_config_descriptor(config);
660  return TRUE;
661 }
662 
663 GSM_Error FBUSUSB_Open(GSM_StateMachine *s)
664 {
665  GSM_Error error;
666 
667  error = GSM_USB_Init(s);
668  if (error != ERR_NONE) return error;
669 
670  error = GSM_USB_Probe(s, FBUSUSB_Match);
671  if (error != ERR_NONE) return error;
672 
673  return ERR_NONE;
674 }
675 
676 
677 GSM_Device_Functions FBUSUSBDevice = {
678  FBUSUSB_Open,
679  GSM_USB_Terminate,
680  NONEFUNCTION,
681  NONEFUNCTION,
682  NONEFUNCTION,
683  GSM_USB_Read,
684  GSM_USB_Write
685 };
686 #endif
687 
688 /* How should editor hadle tabs in this file? Add editor commands here.
689  * vim: noexpandtab sw=8 ts=8 sts=8:
690  */
int configuration
Definition: usb.h:29
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
int data_iface
Definition: usb.h:32
union GSM_Device::@0 Data
#define NONEFUNCTION
Definition: gsmcomon.h:12
GSM_Error
Definition: gammu-error.h:23
gboolean(* GSM_USB_Match_Function)(GSM_StateMachine *s, libusb_device *dev, struct_libusb_device_descriptor *desc)
Definition: usb.h:39
int data_idlesetting
Definition: usb.h:34
int data_altsetting
Definition: usb.h:33
unsigned char ep_write
Definition: usb.h:36
int control_altsetting
Definition: usb.h:31
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
libusb_device_handle * handle
Definition: usb.h:28
int control_iface
Definition: usb.h:30
#define TRUE
Definition: gammu-types.h:28
unsigned char ep_read
Definition: usb.h:35
libusb_context * context
Definition: usb.h:27
GSM_Device Device
Definition: gsmstate.h:1429
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261
#define libusb_device
Definition: usb.h:21