diff options
Diffstat (limited to 'drivers/usb/atm/speedtch.c')
| -rw-r--r-- | drivers/usb/atm/speedtch.c | 167 |
1 files changed, 120 insertions, 47 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c1b47d74e206..7860c8a5800d 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
| @@ -35,12 +35,14 @@ | |||
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/stat.h> | 36 | #include <linux/stat.h> |
| 37 | #include <linux/timer.h> | 37 | #include <linux/timer.h> |
| 38 | #include <linux/types.h> | ||
| 39 | #include <linux/usb_ch9.h> | ||
| 38 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
| 39 | 41 | ||
| 40 | #include "usbatm.h" | 42 | #include "usbatm.h" |
| 41 | 43 | ||
| 42 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | 44 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" |
| 43 | #define DRIVER_VERSION "1.9" | 45 | #define DRIVER_VERSION "1.10" |
| 44 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION | 46 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION |
| 45 | 47 | ||
| 46 | static const char speedtch_driver_name[] = "speedtch"; | 48 | static const char speedtch_driver_name[] = "speedtch"; |
| @@ -66,31 +68,42 @@ static const char speedtch_driver_name[] = "speedtch"; | |||
| 66 | 68 | ||
| 67 | #define RESUBMIT_DELAY 1000 /* milliseconds */ | 69 | #define RESUBMIT_DELAY 1000 /* milliseconds */ |
| 68 | 70 | ||
| 69 | #define DEFAULT_ALTSETTING 1 | 71 | #define DEFAULT_BULK_ALTSETTING 1 |
| 72 | #define DEFAULT_ISOC_ALTSETTING 2 | ||
| 70 | #define DEFAULT_DL_512_FIRST 0 | 73 | #define DEFAULT_DL_512_FIRST 0 |
| 74 | #define DEFAULT_ENABLE_ISOC 0 | ||
| 71 | #define DEFAULT_SW_BUFFERING 0 | 75 | #define DEFAULT_SW_BUFFERING 0 |
| 72 | 76 | ||
| 73 | static int altsetting = DEFAULT_ALTSETTING; | 77 | static unsigned int altsetting = 0; /* zero means: use the default */ |
| 74 | static int dl_512_first = DEFAULT_DL_512_FIRST; | 78 | static int dl_512_first = DEFAULT_DL_512_FIRST; |
| 79 | static int enable_isoc = DEFAULT_ENABLE_ISOC; | ||
| 75 | static int sw_buffering = DEFAULT_SW_BUFFERING; | 80 | static int sw_buffering = DEFAULT_SW_BUFFERING; |
| 76 | 81 | ||
| 77 | module_param(altsetting, int, S_IRUGO | S_IWUSR); | 82 | module_param(altsetting, uint, S_IRUGO | S_IWUSR); |
| 78 | MODULE_PARM_DESC(altsetting, | 83 | MODULE_PARM_DESC(altsetting, |
| 79 | "Alternative setting for data interface (default: " | 84 | "Alternative setting for data interface (bulk_default: " |
| 80 | __MODULE_STRING(DEFAULT_ALTSETTING) ")"); | 85 | __MODULE_STRING(DEFAULT_BULK_ALTSETTING) "; isoc_default: " |
| 86 | __MODULE_STRING(DEFAULT_ISOC_ALTSETTING) ")"); | ||
| 81 | 87 | ||
| 82 | module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); | 88 | module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); |
| 83 | MODULE_PARM_DESC(dl_512_first, | 89 | MODULE_PARM_DESC(dl_512_first, |
| 84 | "Read 512 bytes before sending firmware (default: " | 90 | "Read 512 bytes before sending firmware (default: " |
| 85 | __MODULE_STRING(DEFAULT_DL_512_FIRST) ")"); | 91 | __MODULE_STRING(DEFAULT_DL_512_FIRST) ")"); |
| 86 | 92 | ||
| 93 | module_param(enable_isoc, bool, S_IRUGO | S_IWUSR); | ||
| 94 | MODULE_PARM_DESC(enable_isoc, | ||
| 95 | "Use isochronous transfers if available (default: " | ||
| 96 | __MODULE_STRING(DEFAULT_ENABLE_ISOC) ")"); | ||
| 97 | |||
| 87 | module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); | 98 | module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); |
| 88 | MODULE_PARM_DESC(sw_buffering, | 99 | MODULE_PARM_DESC(sw_buffering, |
| 89 | "Enable software buffering (default: " | 100 | "Enable software buffering (default: " |
| 90 | __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); | 101 | __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); |
| 91 | 102 | ||
| 103 | #define INTERFACE_DATA 1 | ||
| 92 | #define ENDPOINT_INT 0x81 | 104 | #define ENDPOINT_INT 0x81 |
| 93 | #define ENDPOINT_DATA 0x07 | 105 | #define ENDPOINT_BULK_DATA 0x07 |
| 106 | #define ENDPOINT_ISOC_DATA 0x07 | ||
| 94 | #define ENDPOINT_FIRMWARE 0x05 | 107 | #define ENDPOINT_FIRMWARE 0x05 |
| 95 | 108 | ||
| 96 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) | 109 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) |
| @@ -98,6 +111,8 @@ MODULE_PARM_DESC(sw_buffering, | |||
| 98 | struct speedtch_instance_data { | 111 | struct speedtch_instance_data { |
| 99 | struct usbatm_data *usbatm; | 112 | struct usbatm_data *usbatm; |
| 100 | 113 | ||
| 114 | unsigned int altsetting; | ||
| 115 | |||
| 101 | struct work_struct status_checker; | 116 | struct work_struct status_checker; |
| 102 | 117 | ||
| 103 | unsigned char last_status; | 118 | unsigned char last_status; |
| @@ -205,7 +220,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 205 | buffer, 0x200, &actual_length, 2000); | 220 | buffer, 0x200, &actual_length, 2000); |
| 206 | 221 | ||
| 207 | if (ret < 0 && ret != -ETIMEDOUT) | 222 | if (ret < 0 && ret != -ETIMEDOUT) |
| 208 | usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); | 223 | usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); |
| 209 | else | 224 | else |
| 210 | usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret); | 225 | usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret); |
| 211 | } | 226 | } |
| @@ -219,7 +234,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 219 | buffer, thislen, &actual_length, DATA_TIMEOUT); | 234 | buffer, thislen, &actual_length, DATA_TIMEOUT); |
| 220 | 235 | ||
| 221 | if (ret < 0) { | 236 | if (ret < 0) { |
| 222 | usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); | 237 | usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); |
| 223 | goto out_free; | 238 | goto out_free; |
| 224 | } | 239 | } |
| 225 | usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size); | 240 | usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size); |
| @@ -232,7 +247,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 232 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | 247 | buffer, 0x200, &actual_length, DATA_TIMEOUT); |
| 233 | 248 | ||
| 234 | if (ret < 0) { | 249 | if (ret < 0) { |
| 235 | usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); | 250 | usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); |
| 236 | goto out_free; | 251 | goto out_free; |
| 237 | } | 252 | } |
| 238 | usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length); | 253 | usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length); |
| @@ -246,7 +261,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 246 | buffer, thislen, &actual_length, DATA_TIMEOUT); | 261 | buffer, thislen, &actual_length, DATA_TIMEOUT); |
| 247 | 262 | ||
| 248 | if (ret < 0) { | 263 | if (ret < 0) { |
| 249 | usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); | 264 | usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); |
| 250 | goto out_free; | 265 | goto out_free; |
| 251 | } | 266 | } |
| 252 | } | 267 | } |
| @@ -259,7 +274,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 259 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | 274 | buffer, 0x200, &actual_length, DATA_TIMEOUT); |
| 260 | 275 | ||
| 261 | if (ret < 0) { | 276 | if (ret < 0) { |
| 262 | usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); | 277 | usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); |
| 263 | goto out_free; | 278 | goto out_free; |
| 264 | } | 279 | } |
| 265 | 280 | ||
| @@ -270,6 +285,11 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
| 270 | because we're in our own kernel thread anyway. */ | 285 | because we're in our own kernel thread anyway. */ |
| 271 | msleep_interruptible(1000); | 286 | msleep_interruptible(1000); |
| 272 | 287 | ||
| 288 | if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { | ||
| 289 | usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret); | ||
| 290 | goto out_free; | ||
| 291 | } | ||
| 292 | |||
| 273 | /* Enable software buffering, if requested */ | 293 | /* Enable software buffering, if requested */ |
| 274 | if (sw_buffering) | 294 | if (sw_buffering) |
| 275 | speedtch_set_swbuff(instance, 1); | 295 | speedtch_set_swbuff(instance, 1); |
| @@ -285,8 +305,8 @@ out: | |||
| 285 | return ret; | 305 | return ret; |
| 286 | } | 306 | } |
| 287 | 307 | ||
| 288 | static int speedtch_find_firmware(struct usb_interface *intf, int phase, | 308 | static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf, |
| 289 | const struct firmware **fw_p) | 309 | int phase, const struct firmware **fw_p) |
| 290 | { | 310 | { |
| 291 | struct device *dev = &intf->dev; | 311 | struct device *dev = &intf->dev; |
| 292 | const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice); | 312 | const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice); |
| @@ -295,24 +315,24 @@ static int speedtch_find_firmware(struct usb_interface *intf, int phase, | |||
| 295 | char buf[24]; | 315 | char buf[24]; |
| 296 | 316 | ||
| 297 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); | 317 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); |
| 298 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); | 318 | usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); |
| 299 | 319 | ||
| 300 | if (request_firmware(fw_p, buf, dev)) { | 320 | if (request_firmware(fw_p, buf, dev)) { |
| 301 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); | 321 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); |
| 302 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); | 322 | usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); |
| 303 | 323 | ||
| 304 | if (request_firmware(fw_p, buf, dev)) { | 324 | if (request_firmware(fw_p, buf, dev)) { |
| 305 | sprintf(buf, "speedtch-%d.bin", phase); | 325 | sprintf(buf, "speedtch-%d.bin", phase); |
| 306 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); | 326 | usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); |
| 307 | 327 | ||
| 308 | if (request_firmware(fw_p, buf, dev)) { | 328 | if (request_firmware(fw_p, buf, dev)) { |
| 309 | dev_warn(dev, "no stage %d firmware found!\n", phase); | 329 | usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase); |
| 310 | return -ENOENT; | 330 | return -ENOENT; |
| 311 | } | 331 | } |
| 312 | } | 332 | } |
| 313 | } | 333 | } |
| 314 | 334 | ||
| 315 | dev_info(dev, "found stage %d firmware %s\n", phase, buf); | 335 | usb_info(usbatm, "found stage %d firmware %s\n", phase, buf); |
| 316 | 336 | ||
| 317 | return 0; | 337 | return 0; |
| 318 | } | 338 | } |
| @@ -323,15 +343,16 @@ static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface | |||
| 323 | struct speedtch_instance_data *instance = usbatm->driver_data; | 343 | struct speedtch_instance_data *instance = usbatm->driver_data; |
| 324 | int ret; | 344 | int ret; |
| 325 | 345 | ||
| 326 | if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0) | 346 | if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0) |
| 327 | return ret; | 347 | return ret; |
| 328 | 348 | ||
| 329 | if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) { | 349 | if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) { |
| 330 | release_firmware(fw1); | 350 | release_firmware(fw1); |
| 331 | return ret; | 351 | return ret; |
| 332 | } | 352 | } |
| 333 | 353 | ||
| 334 | ret = speedtch_upload_firmware(instance, fw1, fw2); | 354 | if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0) |
| 355 | usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret); | ||
| 335 | 356 | ||
| 336 | release_firmware(fw2); | 357 | release_firmware(fw2); |
| 337 | release_firmware(fw1); | 358 | release_firmware(fw1); |
| @@ -428,7 +449,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) | |||
| 428 | int down_speed, up_speed, ret; | 449 | int down_speed, up_speed, ret; |
| 429 | unsigned char status; | 450 | unsigned char status; |
| 430 | 451 | ||
| 452 | #ifdef VERBOSE_DEBUG | ||
| 431 | atm_dbg(usbatm, "%s entered\n", __func__); | 453 | atm_dbg(usbatm, "%s entered\n", __func__); |
| 454 | #endif | ||
| 432 | 455 | ||
| 433 | ret = speedtch_read_status(instance); | 456 | ret = speedtch_read_status(instance); |
| 434 | if (ret < 0) { | 457 | if (ret < 0) { |
| @@ -441,9 +464,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) | |||
| 441 | 464 | ||
| 442 | status = buf[OFFSET_7]; | 465 | status = buf[OFFSET_7]; |
| 443 | 466 | ||
| 444 | atm_dbg(usbatm, "%s: line state %02x\n", __func__, status); | ||
| 445 | |||
| 446 | if ((status != instance->last_status) || !status) { | 467 | if ((status != instance->last_status) || !status) { |
| 468 | atm_dbg(usbatm, "%s: line state 0x%02x\n", __func__, status); | ||
| 469 | |||
| 447 | switch (status) { | 470 | switch (status) { |
| 448 | case 0: | 471 | case 0: |
| 449 | atm_dev->signal = ATM_PHY_SIG_LOST; | 472 | atm_dev->signal = ATM_PHY_SIG_LOST; |
| @@ -484,7 +507,7 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) | |||
| 484 | 507 | ||
| 485 | default: | 508 | default: |
| 486 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 509 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
| 487 | atm_info(usbatm, "Unknown line state %02x\n", status); | 510 | atm_info(usbatm, "unknown line state %02x\n", status); |
| 488 | break; | 511 | break; |
| 489 | } | 512 | } |
| 490 | 513 | ||
| @@ -583,11 +606,6 @@ static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_de | |||
| 583 | 606 | ||
| 584 | atm_dbg(usbatm, "%s entered\n", __func__); | 607 | atm_dbg(usbatm, "%s entered\n", __func__); |
| 585 | 608 | ||
| 586 | if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) { | ||
| 587 | atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret); | ||
| 588 | return ret; | ||
| 589 | } | ||
| 590 | |||
| 591 | /* Set MAC address, it is stored in the serial number */ | 609 | /* Set MAC address, it is stored in the serial number */ |
| 592 | memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); | 610 | memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); |
| 593 | if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { | 611 | if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { |
| @@ -678,20 +696,27 @@ static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_inte | |||
| 678 | 696 | ||
| 679 | static int speedtch_bind(struct usbatm_data *usbatm, | 697 | static int speedtch_bind(struct usbatm_data *usbatm, |
| 680 | struct usb_interface *intf, | 698 | struct usb_interface *intf, |
| 681 | const struct usb_device_id *id, | 699 | const struct usb_device_id *id) |
| 682 | int *need_heavy_init) | ||
| 683 | { | 700 | { |
| 684 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 701 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
| 685 | struct usb_interface *cur_intf; | 702 | struct usb_interface *cur_intf, *data_intf; |
| 686 | struct speedtch_instance_data *instance; | 703 | struct speedtch_instance_data *instance; |
| 687 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | 704 | int ifnum = intf->altsetting->desc.bInterfaceNumber; |
| 688 | int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; | 705 | int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; |
| 689 | int i, ret; | 706 | int i, ret; |
| 707 | int use_isoc; | ||
| 690 | 708 | ||
| 691 | usb_dbg(usbatm, "%s entered\n", __func__); | 709 | usb_dbg(usbatm, "%s entered\n", __func__); |
| 692 | 710 | ||
| 711 | /* sanity checks */ | ||
| 712 | |||
| 693 | if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { | 713 | if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { |
| 694 | usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); | 714 | usb_err(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); |
| 715 | return -ENODEV; | ||
| 716 | } | ||
| 717 | |||
| 718 | if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) { | ||
| 719 | usb_err(usbatm, "%s: data interface not found!\n", __func__); | ||
| 695 | return -ENODEV; | 720 | return -ENODEV; |
| 696 | } | 721 | } |
| 697 | 722 | ||
| @@ -704,25 +729,71 @@ static int speedtch_bind(struct usbatm_data *usbatm, | |||
| 704 | ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm); | 729 | ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm); |
| 705 | 730 | ||
| 706 | if (ret < 0) { | 731 | if (ret < 0) { |
| 707 | usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret); | 732 | usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, i, ret); |
| 708 | speedtch_release_interfaces(usb_dev, i); | 733 | speedtch_release_interfaces(usb_dev, i); |
| 709 | return ret; | 734 | return ret; |
| 710 | } | 735 | } |
| 711 | } | 736 | } |
| 712 | } | 737 | } |
| 713 | 738 | ||
| 714 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); | 739 | instance = kzalloc(sizeof(*instance), GFP_KERNEL); |
| 715 | 740 | ||
| 716 | if (!instance) { | 741 | if (!instance) { |
| 717 | usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__); | 742 | usb_err(usbatm, "%s: no memory for instance data!\n", __func__); |
| 718 | ret = -ENOMEM; | 743 | ret = -ENOMEM; |
| 719 | goto fail_release; | 744 | goto fail_release; |
| 720 | } | 745 | } |
| 721 | 746 | ||
| 722 | memset(instance, 0, sizeof(struct speedtch_instance_data)); | ||
| 723 | |||
| 724 | instance->usbatm = usbatm; | 747 | instance->usbatm = usbatm; |
| 725 | 748 | ||
| 749 | /* altsetting and enable_isoc may change at any moment, so take a snapshot */ | ||
| 750 | instance->altsetting = altsetting; | ||
| 751 | use_isoc = enable_isoc; | ||
| 752 | |||
| 753 | if (instance->altsetting) | ||
| 754 | if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { | ||
| 755 | usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret); | ||
| 756 | instance->altsetting = 0; /* fall back to default */ | ||
| 757 | } | ||
| 758 | |||
| 759 | if (!instance->altsetting && use_isoc) | ||
| 760 | if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) { | ||
| 761 | usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret); | ||
| 762 | use_isoc = 0; /* fall back to bulk */ | ||
| 763 | } | ||
| 764 | |||
| 765 | if (use_isoc) { | ||
| 766 | const struct usb_host_interface *desc = data_intf->cur_altsetting; | ||
| 767 | const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in; | ||
| 768 | int i; | ||
| 769 | |||
| 770 | use_isoc = 0; /* fall back to bulk if endpoint not found */ | ||
| 771 | |||
| 772 | for (i=0; i<desc->desc.bNumEndpoints; i++) { | ||
| 773 | const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; | ||
| 774 | |||
| 775 | if ((endpoint_desc->bEndpointAddress == target_address)) { | ||
| 776 | use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
| 777 | USB_ENDPOINT_XFER_ISOC; | ||
| 778 | break; | ||
| 779 | } | ||
| 780 | } | ||
| 781 | |||
| 782 | if (!use_isoc) | ||
| 783 | usb_info(usbatm, "isochronous transfer not supported - using bulk\n"); | ||
| 784 | } | ||
| 785 | |||
| 786 | if (!use_isoc && !instance->altsetting) | ||
| 787 | if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) { | ||
| 788 | usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret); | ||
| 789 | goto fail_free; | ||
| 790 | } | ||
| 791 | |||
| 792 | if (!instance->altsetting) | ||
| 793 | instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING; | ||
| 794 | |||
| 795 | usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); | ||
| 796 | |||
| 726 | INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); | 797 | INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); |
| 727 | 798 | ||
| 728 | instance->status_checker.timer.function = speedtch_status_poll; | 799 | instance->status_checker.timer.function = speedtch_status_poll; |
| @@ -749,13 +820,15 @@ static int speedtch_bind(struct usbatm_data *usbatm, | |||
| 749 | 0x12, 0xc0, 0x07, 0x00, | 820 | 0x12, 0xc0, 0x07, 0x00, |
| 750 | instance->scratch_buffer + OFFSET_7, SIZE_7, 500); | 821 | instance->scratch_buffer + OFFSET_7, SIZE_7, 500); |
| 751 | 822 | ||
| 752 | *need_heavy_init = (ret != SIZE_7); | 823 | usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0); |
| 753 | 824 | ||
| 754 | usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already"); | 825 | usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not"); |
| 755 | 826 | ||
| 756 | if (*need_heavy_init) | 827 | if (!(usbatm->flags & UDSL_SKIP_HEAVY_INIT)) |
| 757 | if ((ret = usb_reset_device(usb_dev)) < 0) | 828 | if ((ret = usb_reset_device(usb_dev)) < 0) { |
| 829 | usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret); | ||
| 758 | goto fail_free; | 830 | goto fail_free; |
| 831 | } | ||
| 759 | 832 | ||
| 760 | usbatm->driver_data = instance; | 833 | usbatm->driver_data = instance; |
| 761 | 834 | ||
| @@ -787,15 +860,15 @@ static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *in | |||
| 787 | ***********/ | 860 | ***********/ |
| 788 | 861 | ||
| 789 | static struct usbatm_driver speedtch_usbatm_driver = { | 862 | static struct usbatm_driver speedtch_usbatm_driver = { |
| 790 | .owner = THIS_MODULE, | ||
| 791 | .driver_name = speedtch_driver_name, | 863 | .driver_name = speedtch_driver_name, |
| 792 | .bind = speedtch_bind, | 864 | .bind = speedtch_bind, |
| 793 | .heavy_init = speedtch_heavy_init, | 865 | .heavy_init = speedtch_heavy_init, |
| 794 | .unbind = speedtch_unbind, | 866 | .unbind = speedtch_unbind, |
| 795 | .atm_start = speedtch_atm_start, | 867 | .atm_start = speedtch_atm_start, |
| 796 | .atm_stop = speedtch_atm_stop, | 868 | .atm_stop = speedtch_atm_stop, |
| 797 | .in = ENDPOINT_DATA, | 869 | .bulk_in = ENDPOINT_BULK_DATA, |
| 798 | .out = ENDPOINT_DATA | 870 | .bulk_out = ENDPOINT_BULK_DATA, |
| 871 | .isoc_in = ENDPOINT_ISOC_DATA | ||
| 799 | }; | 872 | }; |
| 800 | 873 | ||
| 801 | static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | 874 | static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) |
