aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/atm/speedtch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/atm/speedtch.c')
-rw-r--r--drivers/usb/atm/speedtch.c82
1 files changed, 66 insertions, 16 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 0e981672f149..8c1c560cf051 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -35,6 +35,8 @@
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"
@@ -66,24 +68,33 @@ 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
73static int altsetting = DEFAULT_ALTSETTING; 77static unsigned int altsetting = 0; /* zero means: use the default */
74static int dl_512_first = DEFAULT_DL_512_FIRST; 78static int dl_512_first = DEFAULT_DL_512_FIRST;
79static int enable_isoc = DEFAULT_ENABLE_ISOC;
75static int sw_buffering = DEFAULT_SW_BUFFERING; 80static int sw_buffering = DEFAULT_SW_BUFFERING;
76 81
77module_param(altsetting, int, S_IRUGO | S_IWUSR); 82module_param(altsetting, uint, S_IRUGO | S_IWUSR);
78MODULE_PARM_DESC(altsetting, 83MODULE_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
82module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); 88module_param(dl_512_first, bool, S_IRUGO | S_IWUSR);
83MODULE_PARM_DESC(dl_512_first, 89MODULE_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
93module_param(enable_isoc, bool, S_IRUGO | S_IWUSR);
94MODULE_PARM_DESC(enable_isoc,
95 "Use isochronous transfers if available (default: "
96 __MODULE_STRING(DEFAULT_ENABLE_ISOC) ")");
97
87module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); 98module_param(sw_buffering, bool, S_IRUGO | S_IWUSR);
88MODULE_PARM_DESC(sw_buffering, 99MODULE_PARM_DESC(sw_buffering,
89 "Enable software buffering (default: " 100 "Enable software buffering (default: "
@@ -91,7 +102,8 @@ MODULE_PARM_DESC(sw_buffering,
91 102
92#define INTERFACE_DATA 1 103#define INTERFACE_DATA 1
93#define ENDPOINT_INT 0x81 104#define ENDPOINT_INT 0x81
94#define ENDPOINT_DATA 0x07 105#define ENDPOINT_BULK_DATA 0x07
106#define ENDPOINT_ISOC_DATA 0x07
95#define ENDPOINT_FIRMWARE 0x05 107#define ENDPOINT_FIRMWARE 0x05
96 108
97#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) )
@@ -687,11 +699,12 @@ static int speedtch_bind(struct usbatm_data *usbatm,
687 const struct usb_device_id *id) 699 const struct usb_device_id *id)
688{ 700{
689 struct usb_device *usb_dev = interface_to_usbdev(intf); 701 struct usb_device *usb_dev = interface_to_usbdev(intf);
690 struct usb_interface *cur_intf; 702 struct usb_interface *cur_intf, *data_intf;
691 struct speedtch_instance_data *instance; 703 struct speedtch_instance_data *instance;
692 int ifnum = intf->altsetting->desc.bInterfaceNumber; 704 int ifnum = intf->altsetting->desc.bInterfaceNumber;
693 int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; 705 int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
694 int i, ret; 706 int i, ret;
707 int use_isoc;
695 708
696 usb_dbg(usbatm, "%s entered\n", __func__); 709 usb_dbg(usbatm, "%s entered\n", __func__);
697 710
@@ -702,6 +715,11 @@ static int speedtch_bind(struct usbatm_data *usbatm,
702 return -ENODEV; 715 return -ENODEV;
703 } 716 }
704 717
718 if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) {
719 usb_err(usbatm, "%s: data interface not found!\n", __func__);
720 return -ENODEV;
721 }
722
705 /* claim all interfaces */ 723 /* claim all interfaces */
706 724
707 for (i=0; i < num_interfaces; i++) { 725 for (i=0; i < num_interfaces; i++) {
@@ -728,8 +746,9 @@ static int speedtch_bind(struct usbatm_data *usbatm,
728 746
729 instance->usbatm = usbatm; 747 instance->usbatm = usbatm;
730 748
731 /* altsetting may change at any moment, so take a snapshot */ 749 /* altsetting and enable_isoc may change at any moment, so take a snapshot */
732 instance->altsetting = altsetting; 750 instance->altsetting = altsetting;
751 use_isoc = enable_isoc;
733 752
734 if (instance->altsetting) 753 if (instance->altsetting)
735 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { 754 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
@@ -737,14 +756,44 @@ static int speedtch_bind(struct usbatm_data *usbatm,
737 instance->altsetting = 0; /* fall back to default */ 756 instance->altsetting = 0; /* fall back to default */
738 } 757 }
739 758
740 if (!instance->altsetting) { 759 if (!instance->altsetting && use_isoc)
741 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ALTSETTING)) < 0) { 760 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
742 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ALTSETTING, ret); 761 usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
743 goto fail_free; 762 use_isoc = 0; /* fall back to bulk */
744 } 763 }
745 instance->altsetting = DEFAULT_ALTSETTING; 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");
746 } 784 }
747 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
748 INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); 797 INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
749 798
750 instance->status_checker.timer.function = speedtch_status_poll; 799 instance->status_checker.timer.function = speedtch_status_poll;
@@ -771,7 +820,7 @@ static int speedtch_bind(struct usbatm_data *usbatm,
771 0x12, 0xc0, 0x07, 0x00, 820 0x12, 0xc0, 0x07, 0x00,
772 instance->scratch_buffer + OFFSET_7, SIZE_7, 500); 821 instance->scratch_buffer + OFFSET_7, SIZE_7, 500);
773 822
774 usbatm->flags = (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0); 823 usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
775 824
776 usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not"); 825 usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not");
777 826
@@ -817,8 +866,9 @@ static struct usbatm_driver speedtch_usbatm_driver = {
817 .unbind = speedtch_unbind, 866 .unbind = speedtch_unbind,
818 .atm_start = speedtch_atm_start, 867 .atm_start = speedtch_atm_start,
819 .atm_stop = speedtch_atm_stop, 868 .atm_stop = speedtch_atm_stop,
820 .in = ENDPOINT_DATA, 869 .bulk_in = ENDPOINT_BULK_DATA,
821 .out = ENDPOINT_DATA 870 .bulk_out = ENDPOINT_BULK_DATA,
871 .isoc_in = ENDPOINT_ISOC_DATA
822}; 872};
823 873
824static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) 874static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)