20 #include "../../gsmstate.h" 21 #if defined(GSM_ENABLE_DKU2PHONET) && defined(GSM_ENABLE_USBDEVICE) 24 #include "../../gsmcomon.h" 26 #include "../../../helper/string.h" 31 #define NOKIA_VENDOR_ID 0x0421 36 #define USB_CDC_CLASS 0x02 40 #define USB_CDC_FBUS_SUBCLASS 0xfe 45 struct cdc_union_desc {
47 u_int8_t bDescriptorType;
48 u_int8_t bDescriptorSubType;
50 u_int8_t bMasterInterface0;
51 u_int8_t bSlaveInterface0;
52 } __attribute__ ((packed));
54 struct cdc_extra_desc {
56 u_int8_t bDescriptorType;
57 u_int8_t bDescriptorSubType;
58 } __attribute__ ((packed));
61 #define CDC_HEADER_TYPE 0x00 62 #define CDC_UNION_TYPE 0x06 63 #define CDC_FBUS_TYPE 0x15 66 #define USB_DT_CS_INTERFACE 0x24 80 case LIBUSB_ERROR_INVALID_PARAM:
84 case LIBUSB_ERROR_ACCESS:
85 smprintf(s,
"Access denied (insufficient permissions)\n");
88 case LIBUSB_ERROR_NO_DEVICE:
89 smprintf(s,
"No such device (it may have been disconnected)\n");
92 case LIBUSB_ERROR_NOT_FOUND:
96 case LIBUSB_ERROR_BUSY:
100 case LIBUSB_ERROR_TIMEOUT:
101 smprintf(s,
"Operation timed out\n");
104 case LIBUSB_ERROR_OVERFLOW:
108 case LIBUSB_ERROR_PIPE:
112 case LIBUSB_ERROR_INTERRUPTED:
113 smprintf(s,
"System call interrupted (perhaps due to signal)\n");
116 case LIBUSB_ERROR_NO_MEM:
117 smprintf(s,
"Insufficient memory\n");
120 case LIBUSB_ERROR_NOT_SUPPORTED:
121 smprintf(s,
"Operation not supported or unimplemented on this platform\n");
124 case LIBUSB_ERROR_OTHER:
154 if (*serial != NULL) {
155 while (isspace(**serial) && **serial != 0) {
156 *serial = *serial + 1;
158 smprintf(s,
"Will search for serial = %s\n", *serial);
167 if (*endptr ==
'x') {
172 smprintf(s,
"Will search for deviceid = %d\n", *deviceid);
175 if (*endptr ==
':') {
178 num = strtol(next, &endptr, 10);
179 if (*endptr ==
'x') {
180 num = strtol(next, &endptr, 16);
183 smprintf(s,
"Will search for vendor = 0x%04x, deviceid = 0x%04x\n", *vendor, *product);
190 if (*endptr ==
'.') {
193 num = strtol(next, &endptr, 10);
194 if (*endptr ==
'x') {
195 num = strtol(next, &endptr, 16);
198 smprintf(s,
"Will search for bus = %d, deviceid = %d\n", *bus, *deviceid);
216 struct libusb_device_descriptor desc;
217 struct libusb_config_descriptor *config;
219 int vendor = -1, product = -1, bus = -1, deviceid = -1;
225 GSM_USB_ParseDevice(s, &vendor, &product, &bus, &deviceid, &serial);
226 do_match = (vendor != -1 || product != -1 || bus != -1 || deviceid != -1 || serial != NULL);
228 cnt = libusb_get_device_list(d->
context, &devs);
230 smprintf(s,
"Failed to list USB devices (%d)!\n", (
int)cnt);
231 return GSM_USB_Error(s, cnt);
236 while ((dev = devs[i++]) != NULL) {
237 rc = libusb_get_device_descriptor(dev, &desc);
239 smprintf(s,
"Failed to get device descriptor (%d)!\n", rc);
240 GSM_USB_Error(s, rc);
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));
249 if (vendor != -1 && vendor != desc.idVendor) {
250 smprintf(s,
"Vendor does not match requested 0x%04x, ignoring\n", vendor);
253 if (product != -1 && product != desc.idProduct) {
254 smprintf(s,
"Product does not match requested 0x%04x, ignoring\n", product);
257 if (bus != -1 && bus != libusb_get_bus_number(dev)) {
258 smprintf(s,
"Bus does not match requested %d, ignoring\n", bus);
261 if (deviceid != -1 && deviceid != libusb_get_device_address(dev)) {
262 smprintf(s,
"Device address does not match requested %d, ignoring\n", deviceid);
265 if (serial != NULL && desc.iSerialNumber) {
266 rc = libusb_open(dev, &d->
handle);
268 smprintf(s,
"Failed to read serial!\n");
270 libusb_get_string_descriptor_ascii(d->
handle, desc.iSerialNumber, buffer,
sizeof(buffer) - 1);
271 smprintf(s,
"Device serial: %s\n", buffer);
273 if (strcasecmp(buffer, serial) != 0) {
274 smprintf(s,
"Device serial does not match requested %s, ignoring\n", serial);
281 if (matcher(s, dev, &desc)) {
291 smprintf(s,
"Trying to open device, config=%d, c_iface=%d, c_alt=%d, d_iface=%d, d_alt=%d\n",
294 rc = libusb_open(dev, &d->
handle);
297 error = GSM_USB_Error(s, rc);
302 rc = libusb_get_active_config_descriptor(dev, &config);
304 smprintf(s,
"Failed to get current device configuration!\n");
307 error = GSM_USB_Error(s, rc);
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);
319 smprintf(s,
"Failed to detach kernel driver!\n");
320 libusb_free_config_descriptor(config);
323 error = GSM_USB_Error(s, rc);
330 smprintf(s,
"Configuring USB device...\n");
334 libusb_free_config_descriptor(config);
337 error = GSM_USB_Error(s, rc);
341 smprintf(s,
"Configuration change not required, unhooking only required interfaces!\n");
347 smprintf(s,
"Failed to detach kernel driver!\n");
348 libusb_free_config_descriptor(config);
351 error = GSM_USB_Error(s, rc);
360 smprintf(s,
"Failed to detach kernel driver!\n");
361 libusb_free_config_descriptor(config);
364 error = GSM_USB_Error(s, rc);
369 libusb_free_config_descriptor(config);
371 smprintf(s,
"Claiming USB control interface...\n");
377 error = GSM_USB_Error(s, rc);
381 smprintf(s,
"Configuring USB control interface...\n");
387 error = GSM_USB_Error(s, rc);
391 smprintf(s,
"Claiming USB data interface...\n");
397 error = GSM_USB_Error(s, rc);
401 smprintf(s,
"Configuring USB data interface...\n");
407 error = GSM_USB_Error(s, rc);
429 smprintf(s,
"Failed to init libusb (%d)!\n", rc);
430 return GSM_USB_Error(s, rc);
444 smprintf(s,
"Failed to set idle settings\n");
445 return GSM_USB_Error(s, rc);
449 smprintf(s,
"Failed to release control interface\n");
450 return GSM_USB_Error(s, rc);
454 smprintf(s,
"Failed to release data interface\n");
455 return GSM_USB_Error(s, rc);
471 int rc = LIBUSB_ERROR_TIMEOUT, ret = 0, repeat = 0;
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);
476 if (rc == LIBUSB_ERROR_OTHER && ret != 0) {
477 smprintf(s,
"Other error while reading, but got some data\n");
481 if (rc == LIBUSB_ERROR_TIMEOUT && ret != 0) {
482 smprintf(s,
"Timeout while reading, but got some data\n");
487 smprintf(s,
"Failed to read from usb (%d)!\n", rc);
488 GSM_USB_Error(s, rc);
502 int rc = LIBUSB_ERROR_TIMEOUT, ret = 0, repeat = 0;
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);
507 if (rc == LIBUSB_ERROR_OTHER && ret != 0) {
508 smprintf(s,
"Other error while writing, but got some data\n");
512 if (rc == LIBUSB_ERROR_TIMEOUT && ret != 0) {
513 smprintf(s,
"Timeout while write, but some data were written\n");
518 smprintf(s,
"Failed to write to usb (%d)!\n", rc);
519 GSM_USB_Error(s, rc);
537 struct libusb_config_descriptor *config;
539 const unsigned char *buffer;
541 struct cdc_extra_desc *extra_desc;
542 struct cdc_union_desc *union_desc = NULL;
543 const struct libusb_endpoint_descriptor *ep1, *ep2;
546 if (desc->idVendor != NOKIA_VENDOR_ID)
return FALSE;
549 for (c = 0; c < desc->bNumConfigurations; c++) {
550 rc = libusb_get_config_descriptor(dev, c, &config);
552 GSM_USB_Error(s, rc);
556 for (i = 0; i < config->bNumInterfaces; i++) {
557 for (a = 0; a < config->interface[i].num_altsetting; a++) {
559 if (config->interface[i].altsetting[a].bInterfaceClass == USB_CDC_CLASS
560 && config->interface[i].altsetting[a].bInterfaceSubClass == USB_CDC_FBUS_SUBCLASS
567 libusb_free_config_descriptor(config);
575 d->
control_iface = config->interface[i].altsetting[a].bInterfaceNumber;
581 buffer = config->interface[i].altsetting[a].extra;
582 buflen = config->interface[i].altsetting[a].extra_length;
586 extra_desc = (
struct cdc_extra_desc *)buffer;
587 if (extra_desc->bDescriptorType != USB_DT_CS_INTERFACE) {
588 smprintf(s,
"Extra CDC header: %d\n", extra_desc->bDescriptorType);
592 switch (extra_desc->bDescriptorSubType) {
594 union_desc = (
struct cdc_union_desc *)buffer;
596 case CDC_HEADER_TYPE:
601 smprintf(s,
"Extra CDC subheader: %d\n", extra_desc->bDescriptorSubType);
605 buflen -= extra_desc->bLength;
606 buffer += extra_desc->bLength;
609 if (union_desc == NULL) {
610 smprintf(s,
"Failed to find data end points!\n");
611 libusb_free_config_descriptor(config);
619 for (i = 0; i < config->bNumInterfaces; i++) {
620 for (a = 0; a < config->interface[i].num_altsetting; a++) {
622 if (config->interface[i].altsetting[a].bInterfaceNumber == d->
data_iface) {
624 if (config->interface[i].altsetting[a].bNumEndpoints == 2) {
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) {
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;
644 d->
data_altsetting = config->interface[i].altsetting[a].bAlternateSetting;
645 }
else if (config->interface[i].altsetting[a].bNumEndpoints == 0) {
654 libusb_free_config_descriptor(config);
659 libusb_free_config_descriptor(config);
667 error = GSM_USB_Init(s);
668 if (error !=
ERR_NONE)
return error;
670 error = GSM_USB_Probe(s, FBUSUSB_Match);
671 if (error !=
ERR_NONE)
return error;
GSM_Config * CurrentConfig
union GSM_Device::@0 Data
gboolean(* GSM_USB_Match_Function)(GSM_StateMachine *s, libusb_device *dev, struct_libusb_device_descriptor *desc)
libusb_device_handle * handle
int smprintf(GSM_StateMachine *s, const char *format,...)