diff options
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 113 |
1 files changed, 98 insertions, 15 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 829f446064ea..90e6644dc886 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -54,6 +54,7 @@ struct usbtest_info { | |||
54 | unsigned autoconf:1; | 54 | unsigned autoconf:1; |
55 | unsigned ctrl_out:1; | 55 | unsigned ctrl_out:1; |
56 | unsigned iso:1; /* try iso in/out */ | 56 | unsigned iso:1; /* try iso in/out */ |
57 | unsigned intr:1; /* try interrupt in/out */ | ||
57 | int alt; | 58 | int alt; |
58 | }; | 59 | }; |
59 | 60 | ||
@@ -70,7 +71,10 @@ struct usbtest_dev { | |||
70 | int out_pipe; | 71 | int out_pipe; |
71 | int in_iso_pipe; | 72 | int in_iso_pipe; |
72 | int out_iso_pipe; | 73 | int out_iso_pipe; |
74 | int in_int_pipe; | ||
75 | int out_int_pipe; | ||
73 | struct usb_endpoint_descriptor *iso_in, *iso_out; | 76 | struct usb_endpoint_descriptor *iso_in, *iso_out; |
77 | struct usb_endpoint_descriptor *int_in, *int_out; | ||
74 | struct mutex lock; | 78 | struct mutex lock; |
75 | 79 | ||
76 | #define TBUF_SIZE 256 | 80 | #define TBUF_SIZE 256 |
@@ -101,6 +105,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | |||
101 | struct usb_host_interface *alt; | 105 | struct usb_host_interface *alt; |
102 | struct usb_host_endpoint *in, *out; | 106 | struct usb_host_endpoint *in, *out; |
103 | struct usb_host_endpoint *iso_in, *iso_out; | 107 | struct usb_host_endpoint *iso_in, *iso_out; |
108 | struct usb_host_endpoint *int_in, *int_out; | ||
104 | struct usb_device *udev; | 109 | struct usb_device *udev; |
105 | 110 | ||
106 | for (tmp = 0; tmp < intf->num_altsetting; tmp++) { | 111 | for (tmp = 0; tmp < intf->num_altsetting; tmp++) { |
@@ -108,6 +113,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | |||
108 | 113 | ||
109 | in = out = NULL; | 114 | in = out = NULL; |
110 | iso_in = iso_out = NULL; | 115 | iso_in = iso_out = NULL; |
116 | int_in = int_out = NULL; | ||
111 | alt = intf->altsetting + tmp; | 117 | alt = intf->altsetting + tmp; |
112 | 118 | ||
113 | if (override_alt >= 0 && | 119 | if (override_alt >= 0 && |
@@ -124,6 +130,9 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | |||
124 | switch (usb_endpoint_type(&e->desc)) { | 130 | switch (usb_endpoint_type(&e->desc)) { |
125 | case USB_ENDPOINT_XFER_BULK: | 131 | case USB_ENDPOINT_XFER_BULK: |
126 | break; | 132 | break; |
133 | case USB_ENDPOINT_XFER_INT: | ||
134 | if (dev->info->intr) | ||
135 | goto try_intr; | ||
127 | case USB_ENDPOINT_XFER_ISOC: | 136 | case USB_ENDPOINT_XFER_ISOC: |
128 | if (dev->info->iso) | 137 | if (dev->info->iso) |
129 | goto try_iso; | 138 | goto try_iso; |
@@ -139,6 +148,15 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | |||
139 | out = e; | 148 | out = e; |
140 | } | 149 | } |
141 | continue; | 150 | continue; |
151 | try_intr: | ||
152 | if (usb_endpoint_dir_in(&e->desc)) { | ||
153 | if (!int_in) | ||
154 | int_in = e; | ||
155 | } else { | ||
156 | if (!int_out) | ||
157 | int_out = e; | ||
158 | } | ||
159 | continue; | ||
142 | try_iso: | 160 | try_iso: |
143 | if (usb_endpoint_dir_in(&e->desc)) { | 161 | if (usb_endpoint_dir_in(&e->desc)) { |
144 | if (!iso_in) | 162 | if (!iso_in) |
@@ -148,7 +166,7 @@ try_iso: | |||
148 | iso_out = e; | 166 | iso_out = e; |
149 | } | 167 | } |
150 | } | 168 | } |
151 | if ((in && out) || iso_in || iso_out) | 169 | if ((in && out) || iso_in || iso_out || int_in || int_out) |
152 | goto found; | 170 | goto found; |
153 | } | 171 | } |
154 | return -EINVAL; | 172 | return -EINVAL; |
@@ -183,6 +201,20 @@ found: | |||
183 | iso_out->desc.bEndpointAddress | 201 | iso_out->desc.bEndpointAddress |
184 | & USB_ENDPOINT_NUMBER_MASK); | 202 | & USB_ENDPOINT_NUMBER_MASK); |
185 | } | 203 | } |
204 | |||
205 | if (int_in) { | ||
206 | dev->int_in = &int_in->desc; | ||
207 | dev->in_int_pipe = usb_rcvintpipe(udev, | ||
208 | int_in->desc.bEndpointAddress | ||
209 | & USB_ENDPOINT_NUMBER_MASK); | ||
210 | } | ||
211 | |||
212 | if (int_out) { | ||
213 | dev->int_out = &int_out->desc; | ||
214 | dev->out_int_pipe = usb_sndintpipe(udev, | ||
215 | int_out->desc.bEndpointAddress | ||
216 | & USB_ENDPOINT_NUMBER_MASK); | ||
217 | } | ||
186 | return 0; | 218 | return 0; |
187 | } | 219 | } |
188 | 220 | ||
@@ -205,14 +237,22 @@ static struct urb *usbtest_alloc_urb( | |||
205 | int pipe, | 237 | int pipe, |
206 | unsigned long bytes, | 238 | unsigned long bytes, |
207 | unsigned transfer_flags, | 239 | unsigned transfer_flags, |
208 | unsigned offset) | 240 | unsigned offset, |
241 | u8 bInterval) | ||
209 | { | 242 | { |
210 | struct urb *urb; | 243 | struct urb *urb; |
211 | 244 | ||
212 | urb = usb_alloc_urb(0, GFP_KERNEL); | 245 | urb = usb_alloc_urb(0, GFP_KERNEL); |
213 | if (!urb) | 246 | if (!urb) |
214 | return urb; | 247 | return urb; |
215 | usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL); | 248 | |
249 | if (bInterval) | ||
250 | usb_fill_int_urb(urb, udev, pipe, NULL, bytes, simple_callback, | ||
251 | NULL, bInterval); | ||
252 | else | ||
253 | usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, | ||
254 | NULL); | ||
255 | |||
216 | urb->interval = (udev->speed == USB_SPEED_HIGH) | 256 | urb->interval = (udev->speed == USB_SPEED_HIGH) |
217 | ? (INTERRUPT_RATE << 3) | 257 | ? (INTERRUPT_RATE << 3) |
218 | : INTERRUPT_RATE; | 258 | : INTERRUPT_RATE; |
@@ -251,9 +291,11 @@ static struct urb *usbtest_alloc_urb( | |||
251 | static struct urb *simple_alloc_urb( | 291 | static struct urb *simple_alloc_urb( |
252 | struct usb_device *udev, | 292 | struct usb_device *udev, |
253 | int pipe, | 293 | int pipe, |
254 | unsigned long bytes) | 294 | unsigned long bytes, |
295 | u8 bInterval) | ||
255 | { | 296 | { |
256 | return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0); | 297 | return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0, |
298 | bInterval); | ||
257 | } | 299 | } |
258 | 300 | ||
259 | static unsigned pattern; | 301 | static unsigned pattern; |
@@ -1255,7 +1297,7 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) | |||
1255 | goto cleanup; | 1297 | goto cleanup; |
1256 | } | 1298 | } |
1257 | req.wLength = cpu_to_le16(len); | 1299 | req.wLength = cpu_to_le16(len); |
1258 | urb[i] = u = simple_alloc_urb(udev, pipe, len); | 1300 | urb[i] = u = simple_alloc_urb(udev, pipe, len, 0); |
1259 | if (!u) | 1301 | if (!u) |
1260 | goto cleanup; | 1302 | goto cleanup; |
1261 | 1303 | ||
@@ -1328,7 +1370,7 @@ static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async) | |||
1328 | int retval = 0; | 1370 | int retval = 0; |
1329 | 1371 | ||
1330 | init_completion(&completion); | 1372 | init_completion(&completion); |
1331 | urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size); | 1373 | urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size, 0); |
1332 | if (!urb) | 1374 | if (!urb) |
1333 | return -ENOMEM; | 1375 | return -ENOMEM; |
1334 | urb->context = &completion; | 1376 | urb->context = &completion; |
@@ -1616,9 +1658,9 @@ static int halt_simple(struct usbtest_dev *dev) | |||
1616 | struct usb_device *udev = testdev_to_usbdev(dev); | 1658 | struct usb_device *udev = testdev_to_usbdev(dev); |
1617 | 1659 | ||
1618 | if (udev->speed == USB_SPEED_SUPER) | 1660 | if (udev->speed == USB_SPEED_SUPER) |
1619 | urb = simple_alloc_urb(udev, 0, 1024); | 1661 | urb = simple_alloc_urb(udev, 0, 1024, 0); |
1620 | else | 1662 | else |
1621 | urb = simple_alloc_urb(udev, 0, 512); | 1663 | urb = simple_alloc_urb(udev, 0, 512, 0); |
1622 | if (urb == NULL) | 1664 | if (urb == NULL) |
1623 | return -ENOMEM; | 1665 | return -ENOMEM; |
1624 | 1666 | ||
@@ -1962,7 +2004,7 @@ static int test_unaligned_bulk( | |||
1962 | { | 2004 | { |
1963 | int retval; | 2005 | int retval; |
1964 | struct urb *urb = usbtest_alloc_urb( | 2006 | struct urb *urb = usbtest_alloc_urb( |
1965 | testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1); | 2007 | testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1, 0); |
1966 | 2008 | ||
1967 | if (!urb) | 2009 | if (!urb) |
1968 | return -ENOMEM; | 2010 | return -ENOMEM; |
@@ -2068,7 +2110,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2068 | dev_info(&intf->dev, | 2110 | dev_info(&intf->dev, |
2069 | "TEST 1: write %d bytes %u times\n", | 2111 | "TEST 1: write %d bytes %u times\n", |
2070 | param->length, param->iterations); | 2112 | param->length, param->iterations); |
2071 | urb = simple_alloc_urb(udev, dev->out_pipe, param->length); | 2113 | urb = simple_alloc_urb(udev, dev->out_pipe, param->length, 0); |
2072 | if (!urb) { | 2114 | if (!urb) { |
2073 | retval = -ENOMEM; | 2115 | retval = -ENOMEM; |
2074 | break; | 2116 | break; |
@@ -2083,7 +2125,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2083 | dev_info(&intf->dev, | 2125 | dev_info(&intf->dev, |
2084 | "TEST 2: read %d bytes %u times\n", | 2126 | "TEST 2: read %d bytes %u times\n", |
2085 | param->length, param->iterations); | 2127 | param->length, param->iterations); |
2086 | urb = simple_alloc_urb(udev, dev->in_pipe, param->length); | 2128 | urb = simple_alloc_urb(udev, dev->in_pipe, param->length, 0); |
2087 | if (!urb) { | 2129 | if (!urb) { |
2088 | retval = -ENOMEM; | 2130 | retval = -ENOMEM; |
2089 | break; | 2131 | break; |
@@ -2098,7 +2140,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2098 | dev_info(&intf->dev, | 2140 | dev_info(&intf->dev, |
2099 | "TEST 3: write/%d 0..%d bytes %u times\n", | 2141 | "TEST 3: write/%d 0..%d bytes %u times\n", |
2100 | param->vary, param->length, param->iterations); | 2142 | param->vary, param->length, param->iterations); |
2101 | urb = simple_alloc_urb(udev, dev->out_pipe, param->length); | 2143 | urb = simple_alloc_urb(udev, dev->out_pipe, param->length, 0); |
2102 | if (!urb) { | 2144 | if (!urb) { |
2103 | retval = -ENOMEM; | 2145 | retval = -ENOMEM; |
2104 | break; | 2146 | break; |
@@ -2114,7 +2156,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2114 | dev_info(&intf->dev, | 2156 | dev_info(&intf->dev, |
2115 | "TEST 4: read/%d 0..%d bytes %u times\n", | 2157 | "TEST 4: read/%d 0..%d bytes %u times\n", |
2116 | param->vary, param->length, param->iterations); | 2158 | param->vary, param->length, param->iterations); |
2117 | urb = simple_alloc_urb(udev, dev->in_pipe, param->length); | 2159 | urb = simple_alloc_urb(udev, dev->in_pipe, param->length, 0); |
2118 | if (!urb) { | 2160 | if (!urb) { |
2119 | retval = -ENOMEM; | 2161 | retval = -ENOMEM; |
2120 | break; | 2162 | break; |
@@ -2411,6 +2453,39 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2411 | } | 2453 | } |
2412 | break; | 2454 | break; |
2413 | 2455 | ||
2456 | /* Simple non-queued interrupt I/O tests */ | ||
2457 | case 25: | ||
2458 | if (dev->out_int_pipe == 0) | ||
2459 | break; | ||
2460 | dev_info(&intf->dev, | ||
2461 | "TEST 25: write %d bytes %u times\n", | ||
2462 | param->length, param->iterations); | ||
2463 | urb = simple_alloc_urb(udev, dev->out_int_pipe, param->length, | ||
2464 | dev->int_out->bInterval); | ||
2465 | if (!urb) { | ||
2466 | retval = -ENOMEM; | ||
2467 | break; | ||
2468 | } | ||
2469 | /* FIRMWARE: interrupt sink (maybe accepts short writes) */ | ||
2470 | retval = simple_io(dev, urb, param->iterations, 0, 0, "test25"); | ||
2471 | simple_free_urb(urb); | ||
2472 | break; | ||
2473 | case 26: | ||
2474 | if (dev->in_int_pipe == 0) | ||
2475 | break; | ||
2476 | dev_info(&intf->dev, | ||
2477 | "TEST 26: read %d bytes %u times\n", | ||
2478 | param->length, param->iterations); | ||
2479 | urb = simple_alloc_urb(udev, dev->in_int_pipe, param->length, | ||
2480 | dev->int_in->bInterval); | ||
2481 | if (!urb) { | ||
2482 | retval = -ENOMEM; | ||
2483 | break; | ||
2484 | } | ||
2485 | /* FIRMWARE: interrupt source (maybe generates short writes) */ | ||
2486 | retval = simple_io(dev, urb, param->iterations, 0, 0, "test26"); | ||
2487 | simple_free_urb(urb); | ||
2488 | break; | ||
2414 | } | 2489 | } |
2415 | do_gettimeofday(¶m->duration); | 2490 | do_gettimeofday(¶m->duration); |
2416 | param->duration.tv_sec -= start.tv_sec; | 2491 | param->duration.tv_sec -= start.tv_sec; |
@@ -2447,6 +2522,7 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2447 | struct usbtest_info *info; | 2522 | struct usbtest_info *info; |
2448 | char *rtest, *wtest; | 2523 | char *rtest, *wtest; |
2449 | char *irtest, *iwtest; | 2524 | char *irtest, *iwtest; |
2525 | char *intrtest, *intwtest; | ||
2450 | 2526 | ||
2451 | udev = interface_to_usbdev(intf); | 2527 | udev = interface_to_usbdev(intf); |
2452 | 2528 | ||
@@ -2487,6 +2563,7 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2487 | */ | 2563 | */ |
2488 | rtest = wtest = ""; | 2564 | rtest = wtest = ""; |
2489 | irtest = iwtest = ""; | 2565 | irtest = iwtest = ""; |
2566 | intrtest = intwtest = ""; | ||
2490 | if (force_interrupt || udev->speed == USB_SPEED_LOW) { | 2567 | if (force_interrupt || udev->speed == USB_SPEED_LOW) { |
2491 | if (info->ep_in) { | 2568 | if (info->ep_in) { |
2492 | dev->in_pipe = usb_rcvintpipe(udev, info->ep_in); | 2569 | dev->in_pipe = usb_rcvintpipe(udev, info->ep_in); |
@@ -2525,15 +2602,20 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2525 | irtest = " iso-in"; | 2602 | irtest = " iso-in"; |
2526 | if (dev->out_iso_pipe) | 2603 | if (dev->out_iso_pipe) |
2527 | iwtest = " iso-out"; | 2604 | iwtest = " iso-out"; |
2605 | if (dev->in_int_pipe) | ||
2606 | intrtest = " int-in"; | ||
2607 | if (dev->out_int_pipe) | ||
2608 | intwtest = " int-out"; | ||
2528 | } | 2609 | } |
2529 | 2610 | ||
2530 | usb_set_intfdata(intf, dev); | 2611 | usb_set_intfdata(intf, dev); |
2531 | dev_info(&intf->dev, "%s\n", info->name); | 2612 | dev_info(&intf->dev, "%s\n", info->name); |
2532 | dev_info(&intf->dev, "%s {control%s%s%s%s%s} tests%s\n", | 2613 | dev_info(&intf->dev, "%s {control%s%s%s%s%s%s%s} tests%s\n", |
2533 | usb_speed_string(udev->speed), | 2614 | usb_speed_string(udev->speed), |
2534 | info->ctrl_out ? " in/out" : "", | 2615 | info->ctrl_out ? " in/out" : "", |
2535 | rtest, wtest, | 2616 | rtest, wtest, |
2536 | irtest, iwtest, | 2617 | irtest, iwtest, |
2618 | intrtest, intwtest, | ||
2537 | info->alt >= 0 ? " (+alt)" : ""); | 2619 | info->alt >= 0 ? " (+alt)" : ""); |
2538 | return 0; | 2620 | return 0; |
2539 | } | 2621 | } |
@@ -2607,6 +2689,7 @@ static struct usbtest_info gz_info = { | |||
2607 | .autoconf = 1, | 2689 | .autoconf = 1, |
2608 | .ctrl_out = 1, | 2690 | .ctrl_out = 1, |
2609 | .iso = 1, | 2691 | .iso = 1, |
2692 | .intr = 1, | ||
2610 | .alt = 0, | 2693 | .alt = 0, |
2611 | }; | 2694 | }; |
2612 | 2695 | ||