aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/atm/xusbatm.c114
1 files changed, 77 insertions, 37 deletions
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index ad5d3ff88dd9..83848ee2c6fe 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -41,6 +41,8 @@ XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number");
41XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number"); 41XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
42XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)"); 42XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
43XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)"); 43XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
44XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
45XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
44 46
45static const char xusbatm_driver_name[] = "xusbatm"; 47static const char xusbatm_driver_name[] = "xusbatm";
46 48
@@ -48,61 +50,94 @@ static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX];
48static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; 50static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
49static struct usb_driver xusbatm_usb_driver; 51static struct usb_driver xusbatm_usb_driver;
50 52
51static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep) 53static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
52{ 54{
55 struct usb_host_interface *alt;
56 struct usb_interface *intf;
53 int i, j; 57 int i, j;
54 58
55 for (i = 0; i < intf->num_altsetting; i++) { 59 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
56 struct usb_host_interface *alt = intf->altsetting; 60 if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
57 for (j = 0; j < alt->desc.bNumEndpoints; j++) 61 for (j = 0; j < alt->desc.bNumEndpoints; j++)
58 if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep) 62 if (alt->endpoint[j].desc.bEndpointAddress == ep)
59 return 1; 63 return intf;
64 return NULL;
65}
66
67static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
68 struct usb_interface *intf, int altsetting, int claim)
69{
70 int ifnum = intf->altsetting->desc.bInterfaceNumber;
71 int ret;
72
73 if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
74 usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
75 return ret;
76 }
77 if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
78 usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
79 return ret;
60 } 80 }
61 return 0; 81 return 0;
62} 82}
63 83
84static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
85{
86 if (claimed) {
87 usb_set_intfdata(intf, NULL);
88 usb_driver_release_interface(&xusbatm_usb_driver, intf);
89 }
90}
91
64static int xusbatm_bind(struct usbatm_data *usbatm, 92static int xusbatm_bind(struct usbatm_data *usbatm,
65 struct usb_interface *intf, const struct usb_device_id *id) 93 struct usb_interface *intf, const struct usb_device_id *id)
66{ 94{
67 struct usb_device *usb_dev = interface_to_usbdev(intf); 95 struct usb_device *usb_dev = interface_to_usbdev(intf);
68 int drv_ix = id - xusbatm_usb_ids; 96 int drv_ix = id - xusbatm_usb_ids;
69 int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]); 97 int rx_alt = rx_altsetting[drv_ix];
70 int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]); 98 int tx_alt = tx_altsetting[drv_ix];
71 u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix]; 99 struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
72 int i, ret; 100 struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
101 int ret;
73 102
74 usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x" 103 usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
75 " rx: ep %02x padd %d tx: ep %02x padd %d\n", 104 " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
76 __func__, drv_ix, vendor[drv_ix], product[drv_ix], 105 __func__, drv_ix, vendor[drv_ix], product[drv_ix],
77 rx_endpoint[drv_ix], rx_padding[drv_ix], 106 rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
78 tx_endpoint[drv_ix], tx_padding[drv_ix]); 107 tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
108
109 if (!rx_intf || !tx_intf) {
110 if (!rx_intf)
111 usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
112 __func__, rx_endpoint[drv_ix], rx_alt);
113 if (!tx_intf)
114 usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
115 __func__, tx_endpoint[drv_ix], tx_alt);
116 return -ENODEV;
117 }
79 118
80 if (!rx_ep_present && !tx_ep_present) { 119 if ((rx_intf != intf) && (tx_intf != intf))
81 usb_dbg(usbatm, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
82 __func__, intf->altsetting->desc.bInterfaceNumber,
83 rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
84 return -ENODEV; 120 return -ENODEV;
121
122 if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
123 usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
124 rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
125 return -EINVAL;
85 } 126 }
86 127
87 if (rx_ep_present && tx_ep_present) 128 usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
88 return 0; 129 rx_intf->altsetting->desc.bInterfaceNumber,
130 tx_intf->altsetting->desc.bInterfaceNumber);
89 131
90 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { 132 if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf)))
91 struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; 133 return ret;
92 134
93 if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) { 135 if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
94 ret = usb_driver_claim_interface(&xusbatm_usb_driver, 136 xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
95 cur_if, usbatm); 137 return ret;
96 if (!ret)
97 usb_err(usbatm, "%s: failed to claim interface #%d (%d)\n",
98 __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
99 return ret;
100 }
101 } 138 }
102 139
103 usb_err(usbatm, "%s: no interface has endpoint %#x\n", 140 return 0;
104 __func__, searched_ep);
105 return -ENODEV;
106} 141}
107 142
108static void xusbatm_unbind(struct usbatm_data *usbatm, 143static void xusbatm_unbind(struct usbatm_data *usbatm,
@@ -114,9 +149,12 @@ static void xusbatm_unbind(struct usbatm_data *usbatm,
114 usb_dbg(usbatm, "%s entered\n", __func__); 149 usb_dbg(usbatm, "%s entered\n", __func__);
115 150
116 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { 151 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
117 struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; 152 struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
118 usb_set_intfdata(cur_if, NULL); 153
119 usb_driver_release_interface(&xusbatm_usb_driver, cur_if); 154 if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
155 usb_set_intfdata(cur_intf, NULL);
156 usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
157 }
120 } 158 }
121} 159}
122 160
@@ -161,11 +199,13 @@ static int __init xusbatm_init(void)
161 } 199 }
162 200
163 for (i = 0; i < num_vendor; i++) { 201 for (i = 0; i < num_vendor; i++) {
202 rx_endpoint[i] |= USB_DIR_IN;
203 tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
204
164 xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; 205 xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
165 xusbatm_usb_ids[i].idVendor = vendor[i]; 206 xusbatm_usb_ids[i].idVendor = vendor[i];
166 xusbatm_usb_ids[i].idProduct = product[i]; 207 xusbatm_usb_ids[i].idProduct = product[i];
167 208
168
169 xusbatm_drivers[i].driver_name = xusbatm_driver_name; 209 xusbatm_drivers[i].driver_name = xusbatm_driver_name;
170 xusbatm_drivers[i].bind = xusbatm_bind; 210 xusbatm_drivers[i].bind = xusbatm_bind;
171 xusbatm_drivers[i].unbind = xusbatm_unbind; 211 xusbatm_drivers[i].unbind = xusbatm_unbind;