]>
Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0+ |
1da177e4 LT |
2 | /*****************************************************************************/ |
3 | ||
4 | /* | |
5 | * devio.c -- User space communication with USB devices. | |
6 | * | |
7 | * Copyright (C) 1999-2000 Thomas Sailer ([email protected]) | |
8 | * | |
1da177e4 LT |
9 | * This file implements the usbfs/x/y files, where |
10 | * x is the bus number and y the device number. | |
11 | * | |
12 | * It allows user space programs/"drivers" to communicate directly | |
13 | * with USB devices without intervening kernel driver. | |
14 | * | |
15 | * Revision history | |
16 | * 22.12.1999 0.1 Initial release (split from proc_usb.c) | |
17 | * 04.01.2000 0.2 Turned into its own filesystem | |
46113830 HW |
18 | * 30.09.2005 0.3 Fix user-triggerable oops in async URB delivery |
19 | * (CAN-2005-3055) | |
1da177e4 LT |
20 | */ |
21 | ||
22 | /*****************************************************************************/ | |
23 | ||
24 | #include <linux/fs.h> | |
25 | #include <linux/mm.h> | |
3f07c014 | 26 | #include <linux/sched/signal.h> |
1da177e4 | 27 | #include <linux/slab.h> |
1da177e4 LT |
28 | #include <linux/signal.h> |
29 | #include <linux/poll.h> | |
30 | #include <linux/module.h> | |
b11b2e1b | 31 | #include <linux/string.h> |
1da177e4 LT |
32 | #include <linux/usb.h> |
33 | #include <linux/usbdevice_fs.h> | |
27729aad | 34 | #include <linux/usb/hcd.h> /* for usbcore internals */ |
fbf82fd2 | 35 | #include <linux/cdev.h> |
a7b986b3 | 36 | #include <linux/notifier.h> |
7a01955f | 37 | #include <linux/security.h> |
d178bc3a | 38 | #include <linux/user_namespace.h> |
3d97ff63 | 39 | #include <linux/scatterlist.h> |
e6889b31 | 40 | #include <linux/uaccess.h> |
f7d34b44 | 41 | #include <linux/dma-mapping.h> |
1da177e4 LT |
42 | #include <asm/byteorder.h> |
43 | #include <linux/moduleparam.h> | |
44 | ||
1da177e4 LT |
45 | #include "usb.h" |
46 | ||
4ed33505 AS |
47 | #ifdef CONFIG_PM |
48 | #define MAYBE_CAP_SUSPEND USBDEVFS_CAP_SUSPEND | |
49 | #else | |
50 | #define MAYBE_CAP_SUSPEND 0 | |
51 | #endif | |
52 | ||
fbf82fd2 | 53 | #define USB_MAXBUS 64 |
fa86ad0b | 54 | #define USB_DEVICE_MAX (USB_MAXBUS * 128) |
3d97ff63 | 55 | #define USB_SG_SIZE 16384 /* split-size for large txs */ |
fbf82fd2 | 56 | |
7794f486 AS |
57 | /* Mutual exclusion for ps->list in resume vs. release and remove */ |
58 | static DEFINE_MUTEX(usbfs_mutex); | |
59 | ||
9b6f0c4b | 60 | struct usb_dev_state { |
cd9f0375 AS |
61 | struct list_head list; /* state list */ |
62 | struct usb_device *dev; | |
63 | struct file *file; | |
64 | spinlock_t lock; /* protects the async urb lists */ | |
65 | struct list_head async_pending; | |
66 | struct list_head async_completed; | |
f7d34b44 | 67 | struct list_head memory_list; |
cd9f0375 | 68 | wait_queue_head_t wait; /* wake up if a request completed */ |
7794f486 | 69 | wait_queue_head_t wait_for_resume; /* wake up upon runtime resume */ |
cd9f0375 AS |
70 | unsigned int discsignr; |
71 | struct pid *disc_pid; | |
d178bc3a | 72 | const struct cred *cred; |
70f1b0d3 | 73 | sigval_t disccontext; |
cd9f0375 | 74 | unsigned long ifclaimed; |
01c6460f | 75 | u32 disabled_bulk_eps; |
d883f52e | 76 | unsigned long interface_allowed_mask; |
7794f486 AS |
77 | int not_yet_resumed; |
78 | bool suspend_allowed; | |
79 | bool privileges_dropped; | |
cd9f0375 AS |
80 | }; |
81 | ||
f7d34b44 SG |
82 | struct usb_memory { |
83 | struct list_head memlist; | |
84 | int vma_use_count; | |
85 | int urb_use_count; | |
86 | u32 size; | |
87 | void *mem; | |
88 | dma_addr_t dma_handle; | |
89 | unsigned long vm_start; | |
90 | struct usb_dev_state *ps; | |
91 | }; | |
92 | ||
1da177e4 LT |
93 | struct async { |
94 | struct list_head asynclist; | |
9b6f0c4b | 95 | struct usb_dev_state *ps; |
2425c08b | 96 | struct pid *pid; |
d178bc3a | 97 | const struct cred *cred; |
1da177e4 LT |
98 | unsigned int signr; |
99 | unsigned int ifnum; | |
100 | void __user *userbuffer; | |
101 | void __user *userurb; | |
70f1b0d3 | 102 | sigval_t userurb_sigval; |
1da177e4 | 103 | struct urb *urb; |
f7d34b44 | 104 | struct usb_memory *usbm; |
add1aaea | 105 | unsigned int mem_usage; |
e015268d | 106 | int status; |
01c6460f AS |
107 | u8 bulk_addr; |
108 | u8 bulk_status; | |
1da177e4 LT |
109 | }; |
110 | ||
90ab5ee9 | 111 | static bool usbfs_snoop; |
04e482ff GKH |
112 | module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR); |
113 | MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); | |
1da177e4 | 114 | |
0290cc9f AS |
115 | static unsigned usbfs_snoop_max = 65536; |
116 | module_param(usbfs_snoop_max, uint, S_IRUGO | S_IWUSR); | |
117 | MODULE_PARM_DESC(usbfs_snoop_max, | |
118 | "maximum number of bytes to print while snooping"); | |
119 | ||
1da177e4 LT |
120 | #define snoop(dev, format, arg...) \ |
121 | do { \ | |
122 | if (usbfs_snoop) \ | |
f355e830 | 123 | dev_info(dev, format, ## arg); \ |
1da177e4 LT |
124 | } while (0) |
125 | ||
4c6e8971 AS |
126 | enum snoop_when { |
127 | SUBMIT, COMPLETE | |
128 | }; | |
fad21bdf | 129 | |
4c6e8971 | 130 | #define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) |
1da177e4 | 131 | |
add1aaea | 132 | /* Limit on the total amount of memory we can allocate for transfers */ |
1129d270 | 133 | static u32 usbfs_memory_mb = 16; |
3f5eb8d5 AS |
134 | module_param(usbfs_memory_mb, uint, 0644); |
135 | MODULE_PARM_DESC(usbfs_memory_mb, | |
136 | "maximum MB allowed for usbfs buffers (0 = no limit)"); | |
137 | ||
57999d11 DC |
138 | /* Hard limit, necessary to avoid arithmetic overflow */ |
139 | #define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000) | |
140 | ||
1129d270 | 141 | static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */ |
add1aaea AS |
142 | |
143 | /* Check whether it's okay to allocate more memory for a transfer */ | |
1129d270 | 144 | static int usbfs_increase_memory_usage(u64 amount) |
add1aaea | 145 | { |
1129d270 | 146 | u64 lim; |
3f5eb8d5 | 147 | |
6aa7de05 | 148 | lim = READ_ONCE(usbfs_memory_mb); |
1129d270 | 149 | lim <<= 20; |
3f5eb8d5 | 150 | |
1129d270 MB |
151 | atomic64_add(amount, &usbfs_memory_usage); |
152 | ||
153 | if (lim > 0 && atomic64_read(&usbfs_memory_usage) > lim) { | |
154 | atomic64_sub(amount, &usbfs_memory_usage); | |
155 | return -ENOMEM; | |
156 | } | |
157 | ||
158 | return 0; | |
add1aaea AS |
159 | } |
160 | ||
161 | /* Memory for a transfer is being deallocated */ | |
1129d270 | 162 | static void usbfs_decrease_memory_usage(u64 amount) |
add1aaea | 163 | { |
1129d270 | 164 | atomic64_sub(amount, &usbfs_memory_usage); |
add1aaea | 165 | } |
4c6e8971 | 166 | |
9b6f0c4b | 167 | static int connected(struct usb_dev_state *ps) |
1da177e4 | 168 | { |
349710c3 AS |
169 | return (!list_empty(&ps->list) && |
170 | ps->dev->state != USB_STATE_NOTATTACHED); | |
1da177e4 LT |
171 | } |
172 | ||
f7d34b44 SG |
173 | static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count) |
174 | { | |
175 | struct usb_dev_state *ps = usbm->ps; | |
176 | unsigned long flags; | |
177 | ||
178 | spin_lock_irqsave(&ps->lock, flags); | |
179 | --*count; | |
180 | if (usbm->urb_use_count == 0 && usbm->vma_use_count == 0) { | |
181 | list_del(&usbm->memlist); | |
182 | spin_unlock_irqrestore(&ps->lock, flags); | |
183 | ||
184 | usb_free_coherent(ps->dev, usbm->size, usbm->mem, | |
185 | usbm->dma_handle); | |
186 | usbfs_decrease_memory_usage( | |
187 | usbm->size + sizeof(struct usb_memory)); | |
188 | kfree(usbm); | |
189 | } else { | |
190 | spin_unlock_irqrestore(&ps->lock, flags); | |
191 | } | |
192 | } | |
193 | ||
194 | static void usbdev_vm_open(struct vm_area_struct *vma) | |
195 | { | |
196 | struct usb_memory *usbm = vma->vm_private_data; | |
197 | unsigned long flags; | |
198 | ||
199 | spin_lock_irqsave(&usbm->ps->lock, flags); | |
200 | ++usbm->vma_use_count; | |
201 | spin_unlock_irqrestore(&usbm->ps->lock, flags); | |
202 | } | |
203 | ||
204 | static void usbdev_vm_close(struct vm_area_struct *vma) | |
205 | { | |
206 | struct usb_memory *usbm = vma->vm_private_data; | |
207 | ||
208 | dec_usb_memory_use_count(usbm, &usbm->vma_use_count); | |
209 | } | |
210 | ||
b64d47ae | 211 | static const struct vm_operations_struct usbdev_vm_ops = { |
f7d34b44 SG |
212 | .open = usbdev_vm_open, |
213 | .close = usbdev_vm_close | |
214 | }; | |
215 | ||
216 | static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) | |
217 | { | |
218 | struct usb_memory *usbm = NULL; | |
219 | struct usb_dev_state *ps = file->private_data; | |
2bef9aed | 220 | struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus); |
f7d34b44 SG |
221 | size_t size = vma->vm_end - vma->vm_start; |
222 | void *mem; | |
223 | unsigned long flags; | |
224 | dma_addr_t dma_handle; | |
225 | int ret; | |
226 | ||
227 | ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory)); | |
228 | if (ret) | |
229 | goto error; | |
230 | ||
231 | usbm = kzalloc(sizeof(struct usb_memory), GFP_KERNEL); | |
232 | if (!usbm) { | |
233 | ret = -ENOMEM; | |
234 | goto error_decrease_mem; | |
235 | } | |
236 | ||
70f7ca9a JS |
237 | mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN, |
238 | &dma_handle); | |
f7d34b44 SG |
239 | if (!mem) { |
240 | ret = -ENOMEM; | |
241 | goto error_free_usbm; | |
242 | } | |
243 | ||
244 | memset(mem, 0, size); | |
245 | ||
246 | usbm->mem = mem; | |
247 | usbm->dma_handle = dma_handle; | |
248 | usbm->size = size; | |
249 | usbm->ps = ps; | |
250 | usbm->vm_start = vma->vm_start; | |
251 | usbm->vma_use_count = 1; | |
252 | INIT_LIST_HEAD(&usbm->memlist); | |
253 | ||
2bef9aed | 254 | if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) { |
f7d34b44 SG |
255 | dec_usb_memory_use_count(usbm, &usbm->vma_use_count); |
256 | return -EAGAIN; | |
257 | } | |
258 | ||
259 | vma->vm_flags |= VM_IO; | |
260 | vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); | |
261 | vma->vm_ops = &usbdev_vm_ops; | |
262 | vma->vm_private_data = usbm; | |
263 | ||
264 | spin_lock_irqsave(&ps->lock, flags); | |
265 | list_add_tail(&usbm->memlist, &ps->memory_list); | |
266 | spin_unlock_irqrestore(&ps->lock, flags); | |
267 | ||
268 | return 0; | |
269 | ||
270 | error_free_usbm: | |
271 | kfree(usbm); | |
272 | error_decrease_mem: | |
273 | usbfs_decrease_memory_usage(size + sizeof(struct usb_memory)); | |
274 | error: | |
275 | return ret; | |
276 | } | |
277 | ||
04e482ff GKH |
278 | static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, |
279 | loff_t *ppos) | |
1da177e4 | 280 | { |
9b6f0c4b | 281 | struct usb_dev_state *ps = file->private_data; |
1da177e4 LT |
282 | struct usb_device *dev = ps->dev; |
283 | ssize_t ret = 0; | |
284 | unsigned len; | |
285 | loff_t pos; | |
286 | int i; | |
287 | ||
288 | pos = *ppos; | |
289 | usb_lock_device(dev); | |
349710c3 | 290 | if (!connected(ps)) { |
1da177e4 LT |
291 | ret = -ENODEV; |
292 | goto err; | |
293 | } else if (pos < 0) { | |
294 | ret = -EINVAL; | |
295 | goto err; | |
296 | } | |
297 | ||
298 | if (pos < sizeof(struct usb_device_descriptor)) { | |
04e482ff GKH |
299 | /* 18 bytes - fits on the stack */ |
300 | struct usb_device_descriptor temp_desc; | |
8781ba0a ON |
301 | |
302 | memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); | |
9fcd5c32 AM |
303 | le16_to_cpus(&temp_desc.bcdUSB); |
304 | le16_to_cpus(&temp_desc.idVendor); | |
305 | le16_to_cpus(&temp_desc.idProduct); | |
306 | le16_to_cpus(&temp_desc.bcdDevice); | |
1da177e4 LT |
307 | |
308 | len = sizeof(struct usb_device_descriptor) - pos; | |
309 | if (len > nbytes) | |
310 | len = nbytes; | |
8781ba0a | 311 | if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) { |
1da177e4 LT |
312 | ret = -EFAULT; |
313 | goto err; | |
314 | } | |
1da177e4 LT |
315 | |
316 | *ppos += len; | |
317 | buf += len; | |
318 | nbytes -= len; | |
319 | ret += len; | |
320 | } | |
321 | ||
322 | pos = sizeof(struct usb_device_descriptor); | |
323 | for (i = 0; nbytes && i < dev->descriptor.bNumConfigurations; i++) { | |
324 | struct usb_config_descriptor *config = | |
325 | (struct usb_config_descriptor *)dev->rawdescriptors[i]; | |
326 | unsigned int length = le16_to_cpu(config->wTotalLength); | |
327 | ||
328 | if (*ppos < pos + length) { | |
329 | ||
330 | /* The descriptor may claim to be longer than it | |
331 | * really is. Here is the actual allocated length. */ | |
332 | unsigned alloclen = | |
333 | le16_to_cpu(dev->config[i].desc.wTotalLength); | |
334 | ||
335 | len = length - (*ppos - pos); | |
336 | if (len > nbytes) | |
337 | len = nbytes; | |
338 | ||
339 | /* Simply don't write (skip over) unallocated parts */ | |
340 | if (alloclen > (*ppos - pos)) { | |
341 | alloclen -= (*ppos - pos); | |
342 | if (copy_to_user(buf, | |
343 | dev->rawdescriptors[i] + (*ppos - pos), | |
344 | min(len, alloclen))) { | |
345 | ret = -EFAULT; | |
346 | goto err; | |
347 | } | |
348 | } | |
349 | ||
350 | *ppos += len; | |
351 | buf += len; | |
352 | nbytes -= len; | |
353 | ret += len; | |
354 | } | |
355 | ||
356 | pos += length; | |
357 | } | |
358 | ||
359 | err: | |
360 | usb_unlock_device(dev); | |
361 | return ret; | |
362 | } | |
363 | ||
364 | /* | |
365 | * async list handling | |
366 | */ | |
367 | ||
368 | static struct async *alloc_async(unsigned int numisoframes) | |
369 | { | |
dd95b814 | 370 | struct async *as; |
0a1ef3b5 | 371 | |
dd95b814 | 372 | as = kzalloc(sizeof(struct async), GFP_KERNEL); |
04e482ff GKH |
373 | if (!as) |
374 | return NULL; | |
1da177e4 LT |
375 | as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL); |
376 | if (!as->urb) { | |
377 | kfree(as); | |
378 | return NULL; | |
379 | } | |
04e482ff | 380 | return as; |
1da177e4 LT |
381 | } |
382 | ||
383 | static void free_async(struct async *as) | |
384 | { | |
3d97ff63 HG |
385 | int i; |
386 | ||
2425c08b | 387 | put_pid(as->pid); |
1b41c832 SS |
388 | if (as->cred) |
389 | put_cred(as->cred); | |
3d97ff63 HG |
390 | for (i = 0; i < as->urb->num_sgs; i++) { |
391 | if (sg_page(&as->urb->sg[i])) | |
392 | kfree(sg_virt(&as->urb->sg[i])); | |
393 | } | |
f7d34b44 | 394 | |
3d97ff63 | 395 | kfree(as->urb->sg); |
f7d34b44 SG |
396 | if (as->usbm == NULL) |
397 | kfree(as->urb->transfer_buffer); | |
398 | else | |
399 | dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count); | |
400 | ||
6fd19f4b | 401 | kfree(as->urb->setup_packet); |
1da177e4 | 402 | usb_free_urb(as->urb); |
add1aaea | 403 | usbfs_decrease_memory_usage(as->mem_usage); |
6fd19f4b | 404 | kfree(as); |
1da177e4 LT |
405 | } |
406 | ||
d34d9721 | 407 | static void async_newpending(struct async *as) |
1da177e4 | 408 | { |
9b6f0c4b | 409 | struct usb_dev_state *ps = as->ps; |
04e482ff GKH |
410 | unsigned long flags; |
411 | ||
412 | spin_lock_irqsave(&ps->lock, flags); | |
413 | list_add_tail(&as->asynclist, &ps->async_pending); | |
414 | spin_unlock_irqrestore(&ps->lock, flags); | |
1da177e4 LT |
415 | } |
416 | ||
d34d9721 | 417 | static void async_removepending(struct async *as) |
1da177e4 | 418 | { |
9b6f0c4b | 419 | struct usb_dev_state *ps = as->ps; |
04e482ff GKH |
420 | unsigned long flags; |
421 | ||
422 | spin_lock_irqsave(&ps->lock, flags); | |
423 | list_del_init(&as->asynclist); | |
424 | spin_unlock_irqrestore(&ps->lock, flags); | |
1da177e4 LT |
425 | } |
426 | ||
9b6f0c4b | 427 | static struct async *async_getcompleted(struct usb_dev_state *ps) |
1da177e4 | 428 | { |
04e482ff GKH |
429 | unsigned long flags; |
430 | struct async *as = NULL; | |
431 | ||
432 | spin_lock_irqsave(&ps->lock, flags); | |
433 | if (!list_empty(&ps->async_completed)) { | |
434 | as = list_entry(ps->async_completed.next, struct async, | |
435 | asynclist); | |
436 | list_del_init(&as->asynclist); | |
437 | } | |
438 | spin_unlock_irqrestore(&ps->lock, flags); | |
439 | return as; | |
1da177e4 LT |
440 | } |
441 | ||
9b6f0c4b | 442 | static struct async *async_getpending(struct usb_dev_state *ps, |
04e482ff | 443 | void __user *userurb) |
1da177e4 | 444 | { |
04e482ff | 445 | struct async *as; |
1da177e4 | 446 | |
1da177e4 LT |
447 | list_for_each_entry(as, &ps->async_pending, asynclist) |
448 | if (as->userurb == userurb) { | |
449 | list_del_init(&as->asynclist); | |
1da177e4 LT |
450 | return as; |
451 | } | |
4e09dcf2 | 452 | |
04e482ff | 453 | return NULL; |
1da177e4 LT |
454 | } |
455 | ||
4c6e8971 AS |
456 | static void snoop_urb(struct usb_device *udev, |
457 | void __user *userurb, int pipe, unsigned length, | |
0880aef4 CF |
458 | int timeout_or_status, enum snoop_when when, |
459 | unsigned char *data, unsigned data_len) | |
e639dd3f | 460 | { |
4c6e8971 AS |
461 | static const char *types[] = {"isoc", "int", "ctrl", "bulk"}; |
462 | static const char *dirs[] = {"out", "in"}; | |
463 | int ep; | |
464 | const char *t, *d; | |
e639dd3f GKH |
465 | |
466 | if (!usbfs_snoop) | |
467 | return; | |
468 | ||
4c6e8971 AS |
469 | ep = usb_pipeendpoint(pipe); |
470 | t = types[usb_pipetype(pipe)]; | |
471 | d = dirs[!!usb_pipein(pipe)]; | |
472 | ||
473 | if (userurb) { /* Async */ | |
474 | if (when == SUBMIT) | |
2f964780 | 475 | dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " |
4c6e8971 AS |
476 | "length %u\n", |
477 | userurb, ep, t, d, length); | |
478 | else | |
2f964780 | 479 | dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " |
4c6e8971 AS |
480 | "actual_length %u status %d\n", |
481 | userurb, ep, t, d, length, | |
482 | timeout_or_status); | |
483 | } else { | |
484 | if (when == SUBMIT) | |
485 | dev_info(&udev->dev, "ep%d %s-%s, length %u, " | |
486 | "timeout %d\n", | |
487 | ep, t, d, length, timeout_or_status); | |
488 | else | |
489 | dev_info(&udev->dev, "ep%d %s-%s, actual_length %u, " | |
490 | "status %d\n", | |
491 | ep, t, d, length, timeout_or_status); | |
492 | } | |
0880aef4 | 493 | |
0290cc9f | 494 | data_len = min(data_len, usbfs_snoop_max); |
0880aef4 CF |
495 | if (data && data_len > 0) { |
496 | print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, | |
497 | data, data_len, 1); | |
498 | } | |
e639dd3f GKH |
499 | } |
500 | ||
3d97ff63 HG |
501 | static void snoop_urb_data(struct urb *urb, unsigned len) |
502 | { | |
503 | int i, size; | |
504 | ||
0290cc9f AS |
505 | len = min(len, usbfs_snoop_max); |
506 | if (!usbfs_snoop || len == 0) | |
3d97ff63 HG |
507 | return; |
508 | ||
509 | if (urb->num_sgs == 0) { | |
510 | print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, | |
511 | urb->transfer_buffer, len, 1); | |
512 | return; | |
513 | } | |
514 | ||
515 | for (i = 0; i < urb->num_sgs && len; i++) { | |
516 | size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; | |
517 | print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1, | |
518 | sg_virt(&urb->sg[i]), size, 1); | |
519 | len -= size; | |
520 | } | |
521 | } | |
522 | ||
523 | static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb) | |
524 | { | |
525 | unsigned i, len, size; | |
526 | ||
527 | if (urb->number_of_packets > 0) /* Isochronous */ | |
528 | len = urb->transfer_buffer_length; | |
529 | else /* Non-Isoc */ | |
530 | len = urb->actual_length; | |
531 | ||
532 | if (urb->num_sgs == 0) { | |
533 | if (copy_to_user(userbuffer, urb->transfer_buffer, len)) | |
534 | return -EFAULT; | |
535 | return 0; | |
536 | } | |
537 | ||
538 | for (i = 0; i < urb->num_sgs && len; i++) { | |
539 | size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len; | |
540 | if (copy_to_user(userbuffer, sg_virt(&urb->sg[i]), size)) | |
541 | return -EFAULT; | |
542 | userbuffer += size; | |
543 | len -= size; | |
544 | } | |
545 | ||
546 | return 0; | |
547 | } | |
548 | ||
01c6460f AS |
549 | #define AS_CONTINUATION 1 |
550 | #define AS_UNLINK 2 | |
551 | ||
9b6f0c4b | 552 | static void cancel_bulk_urbs(struct usb_dev_state *ps, unsigned bulk_addr) |
01c6460f AS |
553 | __releases(ps->lock) |
554 | __acquires(ps->lock) | |
555 | { | |
4e09dcf2 | 556 | struct urb *urb; |
01c6460f AS |
557 | struct async *as; |
558 | ||
559 | /* Mark all the pending URBs that match bulk_addr, up to but not | |
560 | * including the first one without AS_CONTINUATION. If such an | |
561 | * URB is encountered then a new transfer has already started so | |
562 | * the endpoint doesn't need to be disabled; otherwise it does. | |
563 | */ | |
564 | list_for_each_entry(as, &ps->async_pending, asynclist) { | |
565 | if (as->bulk_addr == bulk_addr) { | |
566 | if (as->bulk_status != AS_CONTINUATION) | |
567 | goto rescan; | |
568 | as->bulk_status = AS_UNLINK; | |
569 | as->bulk_addr = 0; | |
570 | } | |
571 | } | |
572 | ps->disabled_bulk_eps |= (1 << bulk_addr); | |
573 | ||
574 | /* Now carefully unlink all the marked pending URBs */ | |
575 | rescan: | |
fdd64df7 | 576 | list_for_each_entry_reverse(as, &ps->async_pending, asynclist) { |
01c6460f AS |
577 | if (as->bulk_status == AS_UNLINK) { |
578 | as->bulk_status = 0; /* Only once */ | |
4e09dcf2 HL |
579 | urb = as->urb; |
580 | usb_get_urb(urb); | |
01c6460f | 581 | spin_unlock(&ps->lock); /* Allow completions */ |
4e09dcf2 HL |
582 | usb_unlink_urb(urb); |
583 | usb_put_urb(urb); | |
01c6460f AS |
584 | spin_lock(&ps->lock); |
585 | goto rescan; | |
586 | } | |
587 | } | |
588 | } | |
589 | ||
7d12e780 | 590 | static void async_completed(struct urb *urb) |
1da177e4 | 591 | { |
04e482ff | 592 | struct async *as = urb->context; |
9b6f0c4b | 593 | struct usb_dev_state *ps = as->ps; |
516a1a07 | 594 | struct pid *pid = NULL; |
d178bc3a | 595 | const struct cred *cred = NULL; |
3f38dace | 596 | unsigned long flags; |
70f1b0d3 EB |
597 | sigval_t addr; |
598 | int signr, errno; | |
1da177e4 | 599 | |
3f38dace | 600 | spin_lock_irqsave(&ps->lock, flags); |
04e482ff | 601 | list_move_tail(&as->asynclist, &ps->async_completed); |
e015268d | 602 | as->status = urb->status; |
516a1a07 ON |
603 | signr = as->signr; |
604 | if (signr) { | |
70f1b0d3 EB |
605 | errno = as->status; |
606 | addr = as->userurb_sigval; | |
aec01c58 | 607 | pid = get_pid(as->pid); |
d178bc3a | 608 | cred = get_cred(as->cred); |
1da177e4 | 609 | } |
e639dd3f | 610 | snoop(&urb->dev->dev, "urb complete\n"); |
4c6e8971 | 611 | snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, |
3d97ff63 | 612 | as->status, COMPLETE, NULL, 0); |
79595a73 | 613 | if (usb_urb_dir_in(urb)) |
3d97ff63 HG |
614 | snoop_urb_data(urb, urb->actual_length); |
615 | ||
01c6460f AS |
616 | if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && |
617 | as->status != -ENOENT) | |
618 | cancel_bulk_urbs(ps, as->bulk_addr); | |
ed62ca2f DA |
619 | |
620 | wake_up(&ps->wait); | |
3f38dace | 621 | spin_unlock_irqrestore(&ps->lock, flags); |
516a1a07 | 622 | |
aec01c58 | 623 | if (signr) { |
70f1b0d3 | 624 | kill_pid_usb_asyncio(signr, errno, addr, pid, cred); |
aec01c58 | 625 | put_pid(pid); |
d178bc3a | 626 | put_cred(cred); |
aec01c58 | 627 | } |
1da177e4 LT |
628 | } |
629 | ||
9b6f0c4b | 630 | static void destroy_async(struct usb_dev_state *ps, struct list_head *list) |
1da177e4 | 631 | { |
4e09dcf2 | 632 | struct urb *urb; |
1da177e4 LT |
633 | struct async *as; |
634 | unsigned long flags; | |
635 | ||
636 | spin_lock_irqsave(&ps->lock, flags); | |
637 | while (!list_empty(list)) { | |
fdd64df7 | 638 | as = list_last_entry(list, struct async, asynclist); |
1da177e4 | 639 | list_del_init(&as->asynclist); |
4e09dcf2 HL |
640 | urb = as->urb; |
641 | usb_get_urb(urb); | |
1da177e4 LT |
642 | |
643 | /* drop the spinlock so the completion handler can run */ | |
644 | spin_unlock_irqrestore(&ps->lock, flags); | |
4e09dcf2 HL |
645 | usb_kill_urb(urb); |
646 | usb_put_urb(urb); | |
1da177e4 LT |
647 | spin_lock_irqsave(&ps->lock, flags); |
648 | } | |
649 | spin_unlock_irqrestore(&ps->lock, flags); | |
1da177e4 LT |
650 | } |
651 | ||
9b6f0c4b | 652 | static void destroy_async_on_interface(struct usb_dev_state *ps, |
04e482ff | 653 | unsigned int ifnum) |
1da177e4 LT |
654 | { |
655 | struct list_head *p, *q, hitlist; | |
656 | unsigned long flags; | |
657 | ||
658 | INIT_LIST_HEAD(&hitlist); | |
659 | spin_lock_irqsave(&ps->lock, flags); | |
660 | list_for_each_safe(p, q, &ps->async_pending) | |
661 | if (ifnum == list_entry(p, struct async, asynclist)->ifnum) | |
662 | list_move_tail(p, &hitlist); | |
663 | spin_unlock_irqrestore(&ps->lock, flags); | |
664 | destroy_async(ps, &hitlist); | |
665 | } | |
666 | ||
9b6f0c4b | 667 | static void destroy_all_async(struct usb_dev_state *ps) |
1da177e4 | 668 | { |
04e482ff | 669 | destroy_async(ps, &ps->async_pending); |
1da177e4 LT |
670 | } |
671 | ||
672 | /* | |
673 | * interface claims are made only at the request of user level code, | |
674 | * which can also release them (explicitly or by closing files). | |
675 | * they're also undone when devices disconnect. | |
676 | */ | |
677 | ||
04e482ff GKH |
678 | static int driver_probe(struct usb_interface *intf, |
679 | const struct usb_device_id *id) | |
1da177e4 LT |
680 | { |
681 | return -ENODEV; | |
682 | } | |
683 | ||
684 | static void driver_disconnect(struct usb_interface *intf) | |
685 | { | |
9b6f0c4b | 686 | struct usb_dev_state *ps = usb_get_intfdata(intf); |
1da177e4 LT |
687 | unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber; |
688 | ||
689 | if (!ps) | |
690 | return; | |
691 | ||
692 | /* NOTE: this relies on usbcore having canceled and completed | |
693 | * all pending I/O requests; 2.6 does that. | |
694 | */ | |
695 | ||
696 | if (likely(ifnum < 8*sizeof(ps->ifclaimed))) | |
697 | clear_bit(ifnum, &ps->ifclaimed); | |
698 | else | |
3b6004f3 GKH |
699 | dev_warn(&intf->dev, "interface number %u out of range\n", |
700 | ifnum); | |
1da177e4 | 701 | |
04e482ff | 702 | usb_set_intfdata(intf, NULL); |
1da177e4 LT |
703 | |
704 | /* force async requests to complete */ | |
705 | destroy_async_on_interface(ps, ifnum); | |
706 | } | |
707 | ||
7794f486 | 708 | /* We don't care about suspend/resume of claimed interfaces */ |
2e2eb83f AS |
709 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) |
710 | { | |
711 | return 0; | |
712 | } | |
713 | ||
714 | static int driver_resume(struct usb_interface *intf) | |
715 | { | |
716 | return 0; | |
717 | } | |
718 | ||
7794f486 AS |
719 | /* The following routines apply to the entire device, not interfaces */ |
720 | void usbfs_notify_suspend(struct usb_device *udev) | |
721 | { | |
722 | /* We don't need to handle this */ | |
723 | } | |
724 | ||
725 | void usbfs_notify_resume(struct usb_device *udev) | |
726 | { | |
727 | struct usb_dev_state *ps; | |
728 | ||
729 | /* Protect against simultaneous remove or release */ | |
730 | mutex_lock(&usbfs_mutex); | |
731 | list_for_each_entry(ps, &udev->filelist, list) { | |
732 | WRITE_ONCE(ps->not_yet_resumed, 0); | |
733 | wake_up_all(&ps->wait_for_resume); | |
734 | } | |
735 | mutex_unlock(&usbfs_mutex); | |
736 | } | |
737 | ||
1da177e4 | 738 | struct usb_driver usbfs_driver = { |
1da177e4 LT |
739 | .name = "usbfs", |
740 | .probe = driver_probe, | |
741 | .disconnect = driver_disconnect, | |
2e2eb83f AS |
742 | .suspend = driver_suspend, |
743 | .resume = driver_resume, | |
7794f486 | 744 | .supports_autosuspend = 1, |
1da177e4 LT |
745 | }; |
746 | ||
9b6f0c4b | 747 | static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) |
1da177e4 LT |
748 | { |
749 | struct usb_device *dev = ps->dev; | |
750 | struct usb_interface *intf; | |
751 | int err; | |
752 | ||
753 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | |
754 | return -EINVAL; | |
755 | /* already claimed */ | |
756 | if (test_bit(ifnum, &ps->ifclaimed)) | |
757 | return 0; | |
758 | ||
d883f52e RG |
759 | if (ps->privileges_dropped && |
760 | !test_bit(ifnum, &ps->interface_allowed_mask)) | |
761 | return -EACCES; | |
762 | ||
1da177e4 LT |
763 | intf = usb_ifnum_to_if(dev, ifnum); |
764 | if (!intf) | |
765 | err = -ENOENT; | |
abb0b3d9 IR |
766 | else { |
767 | unsigned int old_suppress; | |
768 | ||
769 | /* suppress uevents while claiming interface */ | |
770 | old_suppress = dev_get_uevent_suppress(&intf->dev); | |
771 | dev_set_uevent_suppress(&intf->dev, 1); | |
1da177e4 | 772 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); |
abb0b3d9 IR |
773 | dev_set_uevent_suppress(&intf->dev, old_suppress); |
774 | } | |
1da177e4 LT |
775 | if (err == 0) |
776 | set_bit(ifnum, &ps->ifclaimed); | |
777 | return err; | |
778 | } | |
779 | ||
9b6f0c4b | 780 | static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum) |
1da177e4 LT |
781 | { |
782 | struct usb_device *dev; | |
783 | struct usb_interface *intf; | |
784 | int err; | |
785 | ||
786 | err = -EINVAL; | |
787 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | |
788 | return err; | |
789 | dev = ps->dev; | |
1da177e4 LT |
790 | intf = usb_ifnum_to_if(dev, ifnum); |
791 | if (!intf) | |
792 | err = -ENOENT; | |
793 | else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { | |
abb0b3d9 IR |
794 | unsigned int old_suppress; |
795 | ||
796 | /* suppress uevents while releasing interface */ | |
797 | old_suppress = dev_get_uevent_suppress(&intf->dev); | |
798 | dev_set_uevent_suppress(&intf->dev, 1); | |
1da177e4 | 799 | usb_driver_release_interface(&usbfs_driver, intf); |
abb0b3d9 | 800 | dev_set_uevent_suppress(&intf->dev, old_suppress); |
1da177e4 LT |
801 | err = 0; |
802 | } | |
1da177e4 LT |
803 | return err; |
804 | } | |
805 | ||
9b6f0c4b | 806 | static int checkintf(struct usb_dev_state *ps, unsigned int ifnum) |
1da177e4 LT |
807 | { |
808 | if (ps->dev->state != USB_STATE_CONFIGURED) | |
809 | return -EHOSTUNREACH; | |
810 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | |
811 | return -EINVAL; | |
812 | if (test_bit(ifnum, &ps->ifclaimed)) | |
813 | return 0; | |
814 | /* if not yet claimed, claim it for the driver */ | |
04e482ff GKH |
815 | dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim " |
816 | "interface %u before use\n", task_pid_nr(current), | |
817 | current->comm, ifnum); | |
1da177e4 LT |
818 | return claimintf(ps, ifnum); |
819 | } | |
820 | ||
821 | static int findintfep(struct usb_device *dev, unsigned int ep) | |
822 | { | |
823 | unsigned int i, j, e; | |
04e482ff | 824 | struct usb_interface *intf; |
1da177e4 LT |
825 | struct usb_host_interface *alts; |
826 | struct usb_endpoint_descriptor *endpt; | |
827 | ||
828 | if (ep & ~(USB_DIR_IN|0xf)) | |
829 | return -EINVAL; | |
830 | if (!dev->actconfig) | |
831 | return -ESRCH; | |
832 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { | |
833 | intf = dev->actconfig->interface[i]; | |
834 | for (j = 0; j < intf->num_altsetting; j++) { | |
04e482ff | 835 | alts = &intf->altsetting[j]; |
1da177e4 LT |
836 | for (e = 0; e < alts->desc.bNumEndpoints; e++) { |
837 | endpt = &alts->endpoint[e].desc; | |
838 | if (endpt->bEndpointAddress == ep) | |
839 | return alts->desc.bInterfaceNumber; | |
840 | } | |
841 | } | |
842 | } | |
04e482ff | 843 | return -ENOENT; |
1da177e4 LT |
844 | } |
845 | ||
9b6f0c4b | 846 | static int check_ctrlrecip(struct usb_dev_state *ps, unsigned int requesttype, |
393cbb51 | 847 | unsigned int request, unsigned int index) |
1da177e4 LT |
848 | { |
849 | int ret = 0; | |
393cbb51 | 850 | struct usb_host_interface *alt_setting; |
1da177e4 | 851 | |
6da9c990 DV |
852 | if (ps->dev->state != USB_STATE_UNAUTHENTICATED |
853 | && ps->dev->state != USB_STATE_ADDRESS | |
24f8b116 | 854 | && ps->dev->state != USB_STATE_CONFIGURED) |
1da177e4 LT |
855 | return -EHOSTUNREACH; |
856 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) | |
857 | return 0; | |
858 | ||
393cbb51 MD |
859 | /* |
860 | * check for the special corner case 'get_device_id' in the printer | |
5dc50c35 HG |
861 | * class specification, which we always want to allow as it is used |
862 | * to query things like ink level, etc. | |
393cbb51 MD |
863 | */ |
864 | if (requesttype == 0xa1 && request == 0) { | |
865 | alt_setting = usb_find_alt_setting(ps->dev->actconfig, | |
866 | index >> 8, index & 0xff); | |
867 | if (alt_setting | |
868 | && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER) | |
5dc50c35 | 869 | return 0; |
393cbb51 MD |
870 | } |
871 | ||
1da177e4 LT |
872 | index &= 0xff; |
873 | switch (requesttype & USB_RECIP_MASK) { | |
874 | case USB_RECIP_ENDPOINT: | |
1361bf4b HG |
875 | if ((index & ~USB_DIR_IN) == 0) |
876 | return 0; | |
04e482ff | 877 | ret = findintfep(ps->dev, index); |
831abf76 KG |
878 | if (ret < 0) { |
879 | /* | |
880 | * Some not fully compliant Win apps seem to get | |
881 | * index wrong and have the endpoint number here | |
882 | * rather than the endpoint address (with the | |
883 | * correct direction). Win does let this through, | |
884 | * so we'll not reject it here but leave it to | |
885 | * the device to not break KVM. But we warn. | |
886 | */ | |
887 | ret = findintfep(ps->dev, index ^ 0x80); | |
888 | if (ret >= 0) | |
889 | dev_info(&ps->dev->dev, | |
890 | "%s: process %i (%s) requesting ep %02x but needs %02x\n", | |
891 | __func__, task_pid_nr(current), | |
892 | current->comm, index, index ^ 0x80); | |
893 | } | |
04e482ff | 894 | if (ret >= 0) |
1da177e4 LT |
895 | ret = checkintf(ps, ret); |
896 | break; | |
897 | ||
898 | case USB_RECIP_INTERFACE: | |
899 | ret = checkintf(ps, index); | |
900 | break; | |
901 | } | |
902 | return ret; | |
903 | } | |
904 | ||
2fec32b0 HG |
905 | static struct usb_host_endpoint *ep_to_host_endpoint(struct usb_device *dev, |
906 | unsigned char ep) | |
907 | { | |
908 | if (ep & USB_ENDPOINT_DIR_MASK) | |
909 | return dev->ep_in[ep & USB_ENDPOINT_NUMBER_MASK]; | |
910 | else | |
911 | return dev->ep_out[ep & USB_ENDPOINT_NUMBER_MASK]; | |
912 | } | |
913 | ||
3e75c6de | 914 | static int parse_usbdevfs_streams(struct usb_dev_state *ps, |
bcf7f6e3 HG |
915 | struct usbdevfs_streams __user *streams, |
916 | unsigned int *num_streams_ret, | |
917 | unsigned int *num_eps_ret, | |
918 | struct usb_host_endpoint ***eps_ret, | |
919 | struct usb_interface **intf_ret) | |
920 | { | |
921 | unsigned int i, num_streams, num_eps; | |
922 | struct usb_host_endpoint **eps; | |
923 | struct usb_interface *intf = NULL; | |
924 | unsigned char ep; | |
925 | int ifnum, ret; | |
926 | ||
927 | if (get_user(num_streams, &streams->num_streams) || | |
928 | get_user(num_eps, &streams->num_eps)) | |
929 | return -EFAULT; | |
930 | ||
931 | if (num_eps < 1 || num_eps > USB_MAXENDPOINTS) | |
932 | return -EINVAL; | |
933 | ||
934 | /* The XHCI controller allows max 2 ^ 16 streams */ | |
935 | if (num_streams_ret && (num_streams < 2 || num_streams > 65536)) | |
936 | return -EINVAL; | |
937 | ||
6da2ec56 | 938 | eps = kmalloc_array(num_eps, sizeof(*eps), GFP_KERNEL); |
bcf7f6e3 HG |
939 | if (!eps) |
940 | return -ENOMEM; | |
941 | ||
942 | for (i = 0; i < num_eps; i++) { | |
943 | if (get_user(ep, &streams->eps[i])) { | |
944 | ret = -EFAULT; | |
945 | goto error; | |
946 | } | |
947 | eps[i] = ep_to_host_endpoint(ps->dev, ep); | |
948 | if (!eps[i]) { | |
949 | ret = -EINVAL; | |
950 | goto error; | |
951 | } | |
952 | ||
953 | /* usb_alloc/free_streams operate on an usb_interface */ | |
954 | ifnum = findintfep(ps->dev, ep); | |
955 | if (ifnum < 0) { | |
956 | ret = ifnum; | |
957 | goto error; | |
958 | } | |
959 | ||
960 | if (i == 0) { | |
961 | ret = checkintf(ps, ifnum); | |
962 | if (ret < 0) | |
963 | goto error; | |
964 | intf = usb_ifnum_to_if(ps->dev, ifnum); | |
965 | } else { | |
966 | /* Verify all eps belong to the same interface */ | |
967 | if (ifnum != intf->altsetting->desc.bInterfaceNumber) { | |
968 | ret = -EINVAL; | |
969 | goto error; | |
970 | } | |
971 | } | |
972 | } | |
973 | ||
974 | if (num_streams_ret) | |
975 | *num_streams_ret = num_streams; | |
976 | *num_eps_ret = num_eps; | |
977 | *eps_ret = eps; | |
978 | *intf_ret = intf; | |
979 | ||
980 | return 0; | |
981 | ||
982 | error: | |
983 | kfree(eps); | |
984 | return ret; | |
985 | } | |
986 | ||
61ad04a8 | 987 | static struct usb_device *usbdev_lookup_by_devt(dev_t devt) |
9f8b17e6 KS |
988 | { |
989 | struct device *dev; | |
990 | ||
4495dfdd | 991 | dev = bus_find_device_by_devt(&usb_bus_type, devt); |
9f8b17e6 KS |
992 | if (!dev) |
993 | return NULL; | |
69ab55d7 | 994 | return to_usb_device(dev); |
9f8b17e6 | 995 | } |
4592bf5a | 996 | |
1da177e4 LT |
997 | /* |
998 | * file operations | |
999 | */ | |
1000 | static int usbdev_open(struct inode *inode, struct file *file) | |
1001 | { | |
fbf82fd2 | 1002 | struct usb_device *dev = NULL; |
9b6f0c4b | 1003 | struct usb_dev_state *ps; |
1da177e4 LT |
1004 | int ret; |
1005 | ||
1da177e4 | 1006 | ret = -ENOMEM; |
d883f52e | 1007 | ps = kzalloc(sizeof(struct usb_dev_state), GFP_KERNEL); |
04e482ff | 1008 | if (!ps) |
62e299e6 | 1009 | goto out_free_ps; |
1da177e4 | 1010 | |
01105a24 | 1011 | ret = -ENODEV; |
61ad04a8 | 1012 | |
9f8b17e6 | 1013 | /* usbdev device-node */ |
fbf82fd2 | 1014 | if (imajor(inode) == USB_DEVICE_MAJOR) |
61ad04a8 | 1015 | dev = usbdev_lookup_by_devt(inode->i_rdev); |
62e299e6 AS |
1016 | if (!dev) |
1017 | goto out_free_ps; | |
1018 | ||
1019 | usb_lock_device(dev); | |
1020 | if (dev->state == USB_STATE_NOTATTACHED) | |
1021 | goto out_unlock_device; | |
1022 | ||
94fcda1f | 1023 | ret = usb_autoresume_device(dev); |
01d883d4 | 1024 | if (ret) |
62e299e6 | 1025 | goto out_unlock_device; |
01d883d4 | 1026 | |
1da177e4 LT |
1027 | ps->dev = dev; |
1028 | ps->file = file; | |
d883f52e | 1029 | ps->interface_allowed_mask = 0xFFFFFFFF; /* 32 bits */ |
1da177e4 | 1030 | spin_lock_init(&ps->lock); |
316547fd | 1031 | INIT_LIST_HEAD(&ps->list); |
1da177e4 LT |
1032 | INIT_LIST_HEAD(&ps->async_pending); |
1033 | INIT_LIST_HEAD(&ps->async_completed); | |
f7d34b44 | 1034 | INIT_LIST_HEAD(&ps->memory_list); |
1da177e4 | 1035 | init_waitqueue_head(&ps->wait); |
7794f486 | 1036 | init_waitqueue_head(&ps->wait_for_resume); |
2425c08b | 1037 | ps->disc_pid = get_pid(task_pid(current)); |
d178bc3a | 1038 | ps->cred = get_current_cred(); |
527660a8 | 1039 | smp_wmb(); |
7794f486 AS |
1040 | |
1041 | /* Can't race with resume; the device is already active */ | |
1da177e4 LT |
1042 | list_add_tail(&ps->list, &dev->filelist); |
1043 | file->private_data = ps; | |
62e299e6 | 1044 | usb_unlock_device(dev); |
2da41d5f AS |
1045 | snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current), |
1046 | current->comm); | |
62e299e6 AS |
1047 | return ret; |
1048 | ||
1049 | out_unlock_device: | |
1050 | usb_unlock_device(dev); | |
1051 | usb_put_dev(dev); | |
1052 | out_free_ps: | |
1053 | kfree(ps); | |
4a2a8a2c | 1054 | return ret; |
1da177e4 LT |
1055 | } |
1056 | ||
1057 | static int usbdev_release(struct inode *inode, struct file *file) | |
1058 | { | |
9b6f0c4b | 1059 | struct usb_dev_state *ps = file->private_data; |
1da177e4 LT |
1060 | struct usb_device *dev = ps->dev; |
1061 | unsigned int ifnum; | |
6ff10464 | 1062 | struct async *as; |
1da177e4 LT |
1063 | |
1064 | usb_lock_device(dev); | |
7cbe5dca | 1065 | usb_hub_release_all_ports(dev, ps); |
4a2a8a2c | 1066 | |
7794f486 AS |
1067 | /* Protect against simultaneous resume */ |
1068 | mutex_lock(&usbfs_mutex); | |
1da177e4 | 1069 | list_del_init(&ps->list); |
7794f486 | 1070 | mutex_unlock(&usbfs_mutex); |
4a2a8a2c | 1071 | |
1da177e4 LT |
1072 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
1073 | ifnum++) { | |
1074 | if (test_bit(ifnum, &ps->ifclaimed)) | |
1075 | releaseintf(ps, ifnum); | |
1076 | } | |
1077 | destroy_all_async(ps); | |
7794f486 AS |
1078 | if (!ps->suspend_allowed) |
1079 | usb_autosuspend_device(dev); | |
1da177e4 LT |
1080 | usb_unlock_device(dev); |
1081 | usb_put_dev(dev); | |
2425c08b | 1082 | put_pid(ps->disc_pid); |
d178bc3a | 1083 | put_cred(ps->cred); |
6ff10464 AS |
1084 | |
1085 | as = async_getcompleted(ps); | |
1086 | while (as) { | |
1087 | free_async(as); | |
1088 | as = async_getcompleted(ps); | |
1089 | } | |
f7d34b44 | 1090 | |
1da177e4 | 1091 | kfree(ps); |
4a2a8a2c | 1092 | return 0; |
1da177e4 LT |
1093 | } |
1094 | ||
9b6f0c4b | 1095 | static int proc_control(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1096 | { |
1097 | struct usb_device *dev = ps->dev; | |
1098 | struct usbdevfs_ctrltransfer ctrl; | |
1099 | unsigned int tmo; | |
1100 | unsigned char *tbuf; | |
ff66e3ce | 1101 | unsigned wLength; |
4c6e8971 | 1102 | int i, pipe, ret; |
1da177e4 LT |
1103 | |
1104 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | |
1105 | return -EFAULT; | |
393cbb51 MD |
1106 | ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest, |
1107 | ctrl.wIndex); | |
04e482ff | 1108 | if (ret) |
1da177e4 | 1109 | return ret; |
ff66e3ce AM |
1110 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ |
1111 | if (wLength > PAGE_SIZE) | |
1da177e4 | 1112 | return -EINVAL; |
add1aaea AS |
1113 | ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) + |
1114 | sizeof(struct usb_ctrlrequest)); | |
1115 | if (ret) | |
1116 | return ret; | |
04e482ff | 1117 | tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); |
add1aaea AS |
1118 | if (!tbuf) { |
1119 | ret = -ENOMEM; | |
1120 | goto done; | |
1121 | } | |
1da177e4 | 1122 | tmo = ctrl.timeout; |
0880aef4 CF |
1123 | snoop(&dev->dev, "control urb: bRequestType=%02x " |
1124 | "bRequest=%02x wValue=%04x " | |
1125 | "wIndex=%04x wLength=%04x\n", | |
c8f2efc8 XR |
1126 | ctrl.bRequestType, ctrl.bRequest, ctrl.wValue, |
1127 | ctrl.wIndex, ctrl.wLength); | |
1da177e4 | 1128 | if (ctrl.bRequestType & 0x80) { |
96d4f267 | 1129 | if (ctrl.wLength && !access_ok(ctrl.data, |
04e482ff | 1130 | ctrl.wLength)) { |
52fb743d AS |
1131 | ret = -EINVAL; |
1132 | goto done; | |
1da177e4 | 1133 | } |
4c6e8971 | 1134 | pipe = usb_rcvctrlpipe(dev, 0); |
0880aef4 | 1135 | snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); |
1da177e4 LT |
1136 | |
1137 | usb_unlock_device(dev); | |
4c6e8971 | 1138 | i = usb_control_msg(dev, pipe, ctrl.bRequest, |
04e482ff GKH |
1139 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, |
1140 | tbuf, ctrl.wLength, tmo); | |
1da177e4 | 1141 | usb_lock_device(dev); |
0880aef4 | 1142 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, |
9d02b426 | 1143 | tbuf, max(i, 0)); |
1da177e4 | 1144 | if ((i > 0) && ctrl.wLength) { |
fe0410c7 | 1145 | if (copy_to_user(ctrl.data, tbuf, i)) { |
52fb743d AS |
1146 | ret = -EFAULT; |
1147 | goto done; | |
1da177e4 LT |
1148 | } |
1149 | } | |
1150 | } else { | |
1151 | if (ctrl.wLength) { | |
1152 | if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { | |
52fb743d AS |
1153 | ret = -EFAULT; |
1154 | goto done; | |
1da177e4 LT |
1155 | } |
1156 | } | |
4c6e8971 | 1157 | pipe = usb_sndctrlpipe(dev, 0); |
0880aef4 CF |
1158 | snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, |
1159 | tbuf, ctrl.wLength); | |
4c6e8971 | 1160 | |
1da177e4 | 1161 | usb_unlock_device(dev); |
04e482ff GKH |
1162 | i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, |
1163 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, | |
1164 | tbuf, ctrl.wLength, tmo); | |
1da177e4 | 1165 | usb_lock_device(dev); |
0880aef4 | 1166 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); |
1da177e4 | 1167 | } |
04e482ff | 1168 | if (i < 0 && i != -EPIPE) { |
1da177e4 LT |
1169 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " |
1170 | "failed cmd %s rqt %u rq %u len %u ret %d\n", | |
1171 | current->comm, ctrl.bRequestType, ctrl.bRequest, | |
1172 | ctrl.wLength, i); | |
1173 | } | |
52fb743d AS |
1174 | ret = i; |
1175 | done: | |
1176 | free_page((unsigned long) tbuf); | |
add1aaea AS |
1177 | usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) + |
1178 | sizeof(struct usb_ctrlrequest)); | |
52fb743d | 1179 | return ret; |
1da177e4 LT |
1180 | } |
1181 | ||
9b6f0c4b | 1182 | static int proc_bulk(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1183 | { |
1184 | struct usb_device *dev = ps->dev; | |
1185 | struct usbdevfs_bulktransfer bulk; | |
1186 | unsigned int tmo, len1, pipe; | |
1187 | int len2; | |
1188 | unsigned char *tbuf; | |
4c6e8971 | 1189 | int i, ret; |
1da177e4 LT |
1190 | |
1191 | if (copy_from_user(&bulk, arg, sizeof(bulk))) | |
1192 | return -EFAULT; | |
04e482ff GKH |
1193 | ret = findintfep(ps->dev, bulk.ep); |
1194 | if (ret < 0) | |
1da177e4 | 1195 | return ret; |
04e482ff GKH |
1196 | ret = checkintf(ps, ret); |
1197 | if (ret) | |
1da177e4 LT |
1198 | return ret; |
1199 | if (bulk.ep & USB_DIR_IN) | |
1200 | pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); | |
1201 | else | |
1202 | pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); | |
1203 | if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) | |
1204 | return -EINVAL; | |
1205 | len1 = bulk.len; | |
1129d270 | 1206 | if (len1 >= (INT_MAX - sizeof(struct urb))) |
1da177e4 | 1207 | return -EINVAL; |
add1aaea AS |
1208 | ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); |
1209 | if (ret) | |
1210 | return ret; | |
135551ea KB |
1211 | tbuf = kmalloc(len1, GFP_KERNEL); |
1212 | if (!tbuf) { | |
add1aaea AS |
1213 | ret = -ENOMEM; |
1214 | goto done; | |
1215 | } | |
1da177e4 LT |
1216 | tmo = bulk.timeout; |
1217 | if (bulk.ep & 0x80) { | |
96d4f267 | 1218 | if (len1 && !access_ok(bulk.data, len1)) { |
52fb743d AS |
1219 | ret = -EINVAL; |
1220 | goto done; | |
1da177e4 | 1221 | } |
0880aef4 | 1222 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); |
4c6e8971 | 1223 | |
1da177e4 LT |
1224 | usb_unlock_device(dev); |
1225 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); | |
1226 | usb_lock_device(dev); | |
0880aef4 | 1227 | snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2); |
4c6e8971 | 1228 | |
1da177e4 LT |
1229 | if (!i && len2) { |
1230 | if (copy_to_user(bulk.data, tbuf, len2)) { | |
52fb743d AS |
1231 | ret = -EFAULT; |
1232 | goto done; | |
1da177e4 LT |
1233 | } |
1234 | } | |
1235 | } else { | |
1236 | if (len1) { | |
1237 | if (copy_from_user(tbuf, bulk.data, len1)) { | |
52fb743d AS |
1238 | ret = -EFAULT; |
1239 | goto done; | |
1da177e4 LT |
1240 | } |
1241 | } | |
0880aef4 | 1242 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); |
4c6e8971 | 1243 | |
1da177e4 LT |
1244 | usb_unlock_device(dev); |
1245 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); | |
1246 | usb_lock_device(dev); | |
0880aef4 | 1247 | snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0); |
1da177e4 | 1248 | } |
52fb743d AS |
1249 | ret = (i < 0 ? i : len2); |
1250 | done: | |
1da177e4 | 1251 | kfree(tbuf); |
add1aaea | 1252 | usbfs_decrease_memory_usage(len1 + sizeof(struct urb)); |
52fb743d | 1253 | return ret; |
1da177e4 LT |
1254 | } |
1255 | ||
f080a51b AS |
1256 | static void check_reset_of_active_ep(struct usb_device *udev, |
1257 | unsigned int epnum, char *ioctl_name) | |
1258 | { | |
1259 | struct usb_host_endpoint **eps; | |
1260 | struct usb_host_endpoint *ep; | |
1261 | ||
1262 | eps = (epnum & USB_DIR_IN) ? udev->ep_in : udev->ep_out; | |
1263 | ep = eps[epnum & 0x0f]; | |
1264 | if (ep && !list_empty(&ep->urb_list)) | |
1265 | dev_warn(&udev->dev, "Process %d (%s) called USBDEVFS_%s for active endpoint 0x%02x\n", | |
1266 | task_pid_nr(current), current->comm, | |
1267 | ioctl_name, epnum); | |
1268 | } | |
1269 | ||
9b6f0c4b | 1270 | static int proc_resetep(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1271 | { |
1272 | unsigned int ep; | |
1273 | int ret; | |
1274 | ||
1275 | if (get_user(ep, (unsigned int __user *)arg)) | |
1276 | return -EFAULT; | |
04e482ff GKH |
1277 | ret = findintfep(ps->dev, ep); |
1278 | if (ret < 0) | |
1da177e4 | 1279 | return ret; |
04e482ff GKH |
1280 | ret = checkintf(ps, ret); |
1281 | if (ret) | |
1da177e4 | 1282 | return ret; |
f080a51b | 1283 | check_reset_of_active_ep(ps->dev, ep, "RESETEP"); |
3444b26a | 1284 | usb_reset_endpoint(ps->dev, ep); |
1da177e4 LT |
1285 | return 0; |
1286 | } | |
1287 | ||
9b6f0c4b | 1288 | static int proc_clearhalt(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1289 | { |
1290 | unsigned int ep; | |
1291 | int pipe; | |
1292 | int ret; | |
1293 | ||
1294 | if (get_user(ep, (unsigned int __user *)arg)) | |
1295 | return -EFAULT; | |
04e482ff GKH |
1296 | ret = findintfep(ps->dev, ep); |
1297 | if (ret < 0) | |
1da177e4 | 1298 | return ret; |
04e482ff GKH |
1299 | ret = checkintf(ps, ret); |
1300 | if (ret) | |
1da177e4 | 1301 | return ret; |
f080a51b | 1302 | check_reset_of_active_ep(ps->dev, ep, "CLEAR_HALT"); |
1da177e4 | 1303 | if (ep & USB_DIR_IN) |
04e482ff GKH |
1304 | pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f); |
1305 | else | |
1306 | pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f); | |
1da177e4 LT |
1307 | |
1308 | return usb_clear_halt(ps->dev, pipe); | |
1309 | } | |
1da177e4 | 1310 | |
9b6f0c4b | 1311 | static int proc_getdriver(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1312 | { |
1313 | struct usbdevfs_getdriver gd; | |
1314 | struct usb_interface *intf; | |
1315 | int ret; | |
1316 | ||
1317 | if (copy_from_user(&gd, arg, sizeof(gd))) | |
1318 | return -EFAULT; | |
1da177e4 LT |
1319 | intf = usb_ifnum_to_if(ps->dev, gd.interface); |
1320 | if (!intf || !intf->dev.driver) | |
1321 | ret = -ENODATA; | |
1322 | else { | |
b11b2e1b | 1323 | strlcpy(gd.driver, intf->dev.driver->name, |
1da177e4 LT |
1324 | sizeof(gd.driver)); |
1325 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); | |
1326 | } | |
1da177e4 LT |
1327 | return ret; |
1328 | } | |
1329 | ||
9b6f0c4b | 1330 | static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) |
1da177e4 | 1331 | { |
681fef83 KL |
1332 | struct usbdevfs_connectinfo ci; |
1333 | ||
1334 | memset(&ci, 0, sizeof(ci)); | |
1335 | ci.devnum = ps->dev->devnum; | |
1336 | ci.slow = ps->dev->speed == USB_SPEED_LOW; | |
1da177e4 | 1337 | |
1da177e4 LT |
1338 | if (copy_to_user(arg, &ci, sizeof(ci))) |
1339 | return -EFAULT; | |
1340 | return 0; | |
1341 | } | |
1342 | ||
6d101f24 DT |
1343 | static int proc_conninfo_ex(struct usb_dev_state *ps, |
1344 | void __user *arg, size_t size) | |
1345 | { | |
1346 | struct usbdevfs_conninfo_ex ci; | |
1347 | struct usb_device *udev = ps->dev; | |
1348 | ||
1349 | if (size < sizeof(ci.size)) | |
1350 | return -EINVAL; | |
1351 | ||
1352 | memset(&ci, 0, sizeof(ci)); | |
1353 | ci.size = sizeof(ci); | |
1354 | ci.busnum = udev->bus->busnum; | |
1355 | ci.devnum = udev->devnum; | |
1356 | ci.speed = udev->speed; | |
1357 | ||
1358 | while (udev && udev->portnum != 0) { | |
1359 | if (++ci.num_ports <= ARRAY_SIZE(ci.ports)) | |
1360 | ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports] = | |
1361 | udev->portnum; | |
1362 | udev = udev->parent; | |
1363 | } | |
1364 | ||
1365 | if (ci.num_ports < ARRAY_SIZE(ci.ports)) | |
1366 | memmove(&ci.ports[0], | |
1367 | &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports], | |
1368 | ci.num_ports); | |
1369 | ||
1370 | if (copy_to_user(arg, &ci, min(sizeof(ci), size))) | |
1371 | return -EFAULT; | |
1372 | ||
1373 | return 0; | |
1374 | } | |
1375 | ||
9b6f0c4b | 1376 | static int proc_resetdevice(struct usb_dev_state *ps) |
1da177e4 | 1377 | { |
d883f52e RG |
1378 | struct usb_host_config *actconfig = ps->dev->actconfig; |
1379 | struct usb_interface *interface; | |
1380 | int i, number; | |
1381 | ||
1382 | /* Don't allow a device reset if the process has dropped the | |
1383 | * privilege to do such things and any of the interfaces are | |
1384 | * currently claimed. | |
1385 | */ | |
1386 | if (ps->privileges_dropped && actconfig) { | |
1387 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { | |
1388 | interface = actconfig->interface[i]; | |
1389 | number = interface->cur_altsetting->desc.bInterfaceNumber; | |
1390 | if (usb_interface_claimed(interface) && | |
1391 | !test_bit(number, &ps->ifclaimed)) { | |
1392 | dev_warn(&ps->dev->dev, | |
1393 | "usbfs: interface %d claimed by %s while '%s' resets device\n", | |
1394 | number, interface->dev.driver->name, current->comm); | |
1395 | return -EACCES; | |
1396 | } | |
1397 | } | |
1398 | } | |
1399 | ||
742120c6 | 1400 | return usb_reset_device(ps->dev); |
1da177e4 LT |
1401 | } |
1402 | ||
9b6f0c4b | 1403 | static int proc_setintf(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1404 | { |
1405 | struct usbdevfs_setinterface setintf; | |
1406 | int ret; | |
1407 | ||
1408 | if (copy_from_user(&setintf, arg, sizeof(setintf))) | |
1409 | return -EFAULT; | |
135551ea KB |
1410 | ret = checkintf(ps, setintf.interface); |
1411 | if (ret) | |
1da177e4 | 1412 | return ret; |
5ec9c177 HG |
1413 | |
1414 | destroy_async_on_interface(ps, setintf.interface); | |
1415 | ||
1da177e4 LT |
1416 | return usb_set_interface(ps->dev, setintf.interface, |
1417 | setintf.altsetting); | |
1418 | } | |
1419 | ||
9b6f0c4b | 1420 | static int proc_setconfig(struct usb_dev_state *ps, void __user *arg) |
1da177e4 | 1421 | { |
3f141e2a | 1422 | int u; |
1da177e4 | 1423 | int status = 0; |
04e482ff | 1424 | struct usb_host_config *actconfig; |
1da177e4 | 1425 | |
3f141e2a | 1426 | if (get_user(u, (int __user *)arg)) |
1da177e4 LT |
1427 | return -EFAULT; |
1428 | ||
04e482ff GKH |
1429 | actconfig = ps->dev->actconfig; |
1430 | ||
1431 | /* Don't touch the device if any interfaces are claimed. | |
1432 | * It could interfere with other drivers' operations, and if | |
1da177e4 LT |
1433 | * an interface is claimed by usbfs it could easily deadlock. |
1434 | */ | |
04e482ff GKH |
1435 | if (actconfig) { |
1436 | int i; | |
1437 | ||
1438 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { | |
1439 | if (usb_interface_claimed(actconfig->interface[i])) { | |
1440 | dev_warn(&ps->dev->dev, | |
72ebddb5 | 1441 | "usbfs: interface %d claimed by %s " |
1da177e4 LT |
1442 | "while '%s' sets config #%d\n", |
1443 | actconfig->interface[i] | |
1444 | ->cur_altsetting | |
1445 | ->desc.bInterfaceNumber, | |
72ebddb5 DB |
1446 | actconfig->interface[i] |
1447 | ->dev.driver->name, | |
1da177e4 | 1448 | current->comm, u); |
04e482ff | 1449 | status = -EBUSY; |
1da177e4 | 1450 | break; |
1da177e4 | 1451 | } |
04e482ff GKH |
1452 | } |
1453 | } | |
1da177e4 LT |
1454 | |
1455 | /* SET_CONFIGURATION is often abused as a "cheap" driver reset, | |
1456 | * so avoid usb_set_configuration()'s kick to sysfs | |
1457 | */ | |
1458 | if (status == 0) { | |
1459 | if (actconfig && actconfig->desc.bConfigurationValue == u) | |
1460 | status = usb_reset_configuration(ps->dev); | |
1461 | else | |
1462 | status = usb_set_configuration(ps->dev, u); | |
1463 | } | |
1464 | ||
1465 | return status; | |
1466 | } | |
1467 | ||
f7d34b44 SG |
1468 | static struct usb_memory * |
1469 | find_memory_area(struct usb_dev_state *ps, const struct usbdevfs_urb *uurb) | |
1470 | { | |
1471 | struct usb_memory *usbm = NULL, *iter; | |
1472 | unsigned long flags; | |
1473 | unsigned long uurb_start = (unsigned long)uurb->buffer; | |
1474 | ||
1475 | spin_lock_irqsave(&ps->lock, flags); | |
1476 | list_for_each_entry(iter, &ps->memory_list, memlist) { | |
1477 | if (uurb_start >= iter->vm_start && | |
1478 | uurb_start < iter->vm_start + iter->size) { | |
1479 | if (uurb->buffer_length > iter->vm_start + iter->size - | |
1480 | uurb_start) { | |
1481 | usbm = ERR_PTR(-EINVAL); | |
1482 | } else { | |
1483 | usbm = iter; | |
1484 | usbm->urb_use_count++; | |
1485 | } | |
1486 | break; | |
1487 | } | |
1488 | } | |
1489 | spin_unlock_irqrestore(&ps->lock, flags); | |
1490 | return usbm; | |
1491 | } | |
1492 | ||
9b6f0c4b | 1493 | static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb, |
04e482ff | 1494 | struct usbdevfs_iso_packet_desc __user *iso_frame_desc, |
70f1b0d3 | 1495 | void __user *arg, sigval_t userurb_sigval) |
1da177e4 LT |
1496 | { |
1497 | struct usbdevfs_iso_packet_desc *isopkt = NULL; | |
1498 | struct usb_host_endpoint *ep; | |
52fb743d | 1499 | struct async *as = NULL; |
1da177e4 LT |
1500 | struct usb_ctrlrequest *dr = NULL; |
1501 | unsigned int u, totlen, isofrmlen; | |
7a68d9fb | 1502 | int i, ret, num_sgs = 0, ifnum = -1; |
b2d03eb5 | 1503 | int number_of_packets = 0; |
948cd8c1 | 1504 | unsigned int stream_id = 0; |
3d97ff63 | 1505 | void *buf; |
7a68d9fb ON |
1506 | bool is_in; |
1507 | bool allow_short = false; | |
1508 | bool allow_zero = false; | |
446f666d | 1509 | unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK | |
01c6460f | 1510 | USBDEVFS_URB_BULK_CONTINUATION | |
14722ef4 AS |
1511 | USBDEVFS_URB_NO_FSBR | |
1512 | USBDEVFS_URB_ZERO_PACKET | | |
446f666d ON |
1513 | USBDEVFS_URB_NO_INTERRUPT; |
1514 | /* USBDEVFS_URB_ISO_ASAP is a special case */ | |
1515 | if (uurb->type == USBDEVFS_URB_TYPE_ISO) | |
1516 | mask |= USBDEVFS_URB_ISO_ASAP; | |
1517 | ||
1518 | if (uurb->flags & ~mask) | |
1519 | return -EINVAL; | |
1520 | ||
57999d11 DC |
1521 | if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX) |
1522 | return -EINVAL; | |
9180135b | 1523 | if (uurb->buffer_length > 0 && !uurb->buffer) |
1da177e4 | 1524 | return -EINVAL; |
04e482ff GKH |
1525 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && |
1526 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { | |
1527 | ifnum = findintfep(ps->dev, uurb->endpoint); | |
1528 | if (ifnum < 0) | |
1da177e4 | 1529 | return ifnum; |
04e482ff GKH |
1530 | ret = checkintf(ps, ifnum); |
1531 | if (ret) | |
1da177e4 LT |
1532 | return ret; |
1533 | } | |
2fec32b0 | 1534 | ep = ep_to_host_endpoint(ps->dev, uurb->endpoint); |
1da177e4 LT |
1535 | if (!ep) |
1536 | return -ENOENT; | |
2fec32b0 | 1537 | is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0; |
add1aaea AS |
1538 | |
1539 | u = 0; | |
f355e830 | 1540 | switch (uurb->type) { |
1da177e4 | 1541 | case USBDEVFS_URB_TYPE_CONTROL: |
93cf9b90 | 1542 | if (!usb_endpoint_xfer_control(&ep->desc)) |
1da177e4 | 1543 | return -EINVAL; |
add1aaea AS |
1544 | /* min 8 byte setup packet */ |
1545 | if (uurb->buffer_length < 8) | |
1da177e4 | 1546 | return -EINVAL; |
04e482ff GKH |
1547 | dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); |
1548 | if (!dr) | |
1da177e4 LT |
1549 | return -ENOMEM; |
1550 | if (copy_from_user(dr, uurb->buffer, 8)) { | |
52fb743d AS |
1551 | ret = -EFAULT; |
1552 | goto error; | |
1da177e4 | 1553 | } |
257adc0f | 1554 | if (uurb->buffer_length < (le16_to_cpu(dr->wLength) + 8)) { |
52fb743d AS |
1555 | ret = -EINVAL; |
1556 | goto error; | |
1da177e4 | 1557 | } |
393cbb51 | 1558 | ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, |
257adc0f | 1559 | le16_to_cpu(dr->wIndex)); |
52fb743d AS |
1560 | if (ret) |
1561 | goto error; | |
257adc0f | 1562 | uurb->buffer_length = le16_to_cpu(dr->wLength); |
1da177e4 | 1563 | uurb->buffer += 8; |
93cf9b90 | 1564 | if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { |
71464db9 | 1565 | is_in = true; |
93cf9b90 AS |
1566 | uurb->endpoint |= USB_DIR_IN; |
1567 | } else { | |
71464db9 | 1568 | is_in = false; |
93cf9b90 AS |
1569 | uurb->endpoint &= ~USB_DIR_IN; |
1570 | } | |
665c365a AS |
1571 | if (is_in) |
1572 | allow_short = true; | |
0880aef4 CF |
1573 | snoop(&ps->dev->dev, "control urb: bRequestType=%02x " |
1574 | "bRequest=%02x wValue=%04x " | |
1575 | "wIndex=%04x wLength=%04x\n", | |
1576 | dr->bRequestType, dr->bRequest, | |
257adc0f AS |
1577 | __le16_to_cpu(dr->wValue), |
1578 | __le16_to_cpu(dr->wIndex), | |
1579 | __le16_to_cpu(dr->wLength)); | |
add1aaea | 1580 | u = sizeof(struct usb_ctrlrequest); |
1da177e4 LT |
1581 | break; |
1582 | ||
1583 | case USBDEVFS_URB_TYPE_BULK: | |
7a68d9fb ON |
1584 | if (!is_in) |
1585 | allow_zero = true; | |
1586 | else | |
1587 | allow_short = true; | |
93cf9b90 | 1588 | switch (usb_endpoint_type(&ep->desc)) { |
1da177e4 LT |
1589 | case USB_ENDPOINT_XFER_CONTROL: |
1590 | case USB_ENDPOINT_XFER_ISOC: | |
1591 | return -EINVAL; | |
f661c6f8 AS |
1592 | case USB_ENDPOINT_XFER_INT: |
1593 | /* allow single-shot interrupt transfers */ | |
1594 | uurb->type = USBDEVFS_URB_TYPE_INTERRUPT; | |
1595 | goto interrupt_urb; | |
1da177e4 | 1596 | } |
3d97ff63 HG |
1597 | num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE); |
1598 | if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize) | |
1599 | num_sgs = 0; | |
948cd8c1 HG |
1600 | if (ep->streams) |
1601 | stream_id = uurb->stream_id; | |
1da177e4 LT |
1602 | break; |
1603 | ||
f661c6f8 AS |
1604 | case USBDEVFS_URB_TYPE_INTERRUPT: |
1605 | if (!usb_endpoint_xfer_int(&ep->desc)) | |
1606 | return -EINVAL; | |
1607 | interrupt_urb: | |
7a68d9fb ON |
1608 | if (!is_in) |
1609 | allow_zero = true; | |
1610 | else | |
1611 | allow_short = true; | |
f661c6f8 AS |
1612 | break; |
1613 | ||
1da177e4 LT |
1614 | case USBDEVFS_URB_TYPE_ISO: |
1615 | /* arbitrary limit */ | |
04e482ff GKH |
1616 | if (uurb->number_of_packets < 1 || |
1617 | uurb->number_of_packets > 128) | |
1da177e4 | 1618 | return -EINVAL; |
93cf9b90 | 1619 | if (!usb_endpoint_xfer_isoc(&ep->desc)) |
1da177e4 | 1620 | return -EINVAL; |
b2d03eb5 | 1621 | number_of_packets = uurb->number_of_packets; |
04e482ff | 1622 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * |
b2d03eb5 | 1623 | number_of_packets; |
73a02d32 RP |
1624 | isopkt = memdup_user(iso_frame_desc, isofrmlen); |
1625 | if (IS_ERR(isopkt)) { | |
1626 | ret = PTR_ERR(isopkt); | |
1627 | isopkt = NULL; | |
52fb743d | 1628 | goto error; |
1da177e4 | 1629 | } |
b2d03eb5 | 1630 | for (totlen = u = 0; u < number_of_packets; u++) { |
e2e2f0ea | 1631 | /* |
8a1dbc8d CY |
1632 | * arbitrary limit need for USB 3.1 Gen2 |
1633 | * sizemax: 96 DPs at SSP, 96 * 1024 = 98304 | |
e2e2f0ea | 1634 | */ |
8a1dbc8d | 1635 | if (isopkt[u].length > 98304) { |
52fb743d AS |
1636 | ret = -EINVAL; |
1637 | goto error; | |
1da177e4 LT |
1638 | } |
1639 | totlen += isopkt[u].length; | |
1640 | } | |
add1aaea | 1641 | u *= sizeof(struct usb_iso_packet_descriptor); |
845d584f | 1642 | uurb->buffer_length = totlen; |
1da177e4 LT |
1643 | break; |
1644 | ||
1da177e4 LT |
1645 | default: |
1646 | return -EINVAL; | |
1647 | } | |
add1aaea | 1648 | |
9180135b | 1649 | if (uurb->buffer_length > 0 && |
96d4f267 | 1650 | !access_ok(uurb->buffer, uurb->buffer_length)) { |
52fb743d AS |
1651 | ret = -EFAULT; |
1652 | goto error; | |
1da177e4 | 1653 | } |
b2d03eb5 | 1654 | as = alloc_async(number_of_packets); |
9180135b | 1655 | if (!as) { |
52fb743d AS |
1656 | ret = -ENOMEM; |
1657 | goto error; | |
1da177e4 | 1658 | } |
3d97ff63 | 1659 | |
f7d34b44 SG |
1660 | as->usbm = find_memory_area(ps, uurb); |
1661 | if (IS_ERR(as->usbm)) { | |
1662 | ret = PTR_ERR(as->usbm); | |
1663 | as->usbm = NULL; | |
1664 | goto error; | |
1665 | } | |
1666 | ||
1667 | /* do not use SG buffers when memory mapped segments | |
1668 | * are in use | |
1669 | */ | |
1670 | if (as->usbm) | |
1671 | num_sgs = 0; | |
1672 | ||
b08a6259 GL |
1673 | u += sizeof(struct async) + sizeof(struct urb) + |
1674 | (as->usbm ? 0 : uurb->buffer_length) + | |
3d97ff63 | 1675 | num_sgs * sizeof(struct scatterlist); |
add1aaea AS |
1676 | ret = usbfs_increase_memory_usage(u); |
1677 | if (ret) | |
1678 | goto error; | |
1679 | as->mem_usage = u; | |
1680 | ||
3d97ff63 | 1681 | if (num_sgs) { |
6da2ec56 KC |
1682 | as->urb->sg = kmalloc_array(num_sgs, |
1683 | sizeof(struct scatterlist), | |
1684 | GFP_KERNEL); | |
3d97ff63 HG |
1685 | if (!as->urb->sg) { |
1686 | ret = -ENOMEM; | |
1687 | goto error; | |
1688 | } | |
1689 | as->urb->num_sgs = num_sgs; | |
1690 | sg_init_table(as->urb->sg, as->urb->num_sgs); | |
1691 | ||
1692 | totlen = uurb->buffer_length; | |
1693 | for (i = 0; i < as->urb->num_sgs; i++) { | |
1694 | u = (totlen > USB_SG_SIZE) ? USB_SG_SIZE : totlen; | |
1695 | buf = kmalloc(u, GFP_KERNEL); | |
1696 | if (!buf) { | |
1697 | ret = -ENOMEM; | |
1698 | goto error; | |
1699 | } | |
1700 | sg_set_buf(&as->urb->sg[i], buf, u); | |
1701 | ||
1702 | if (!is_in) { | |
1703 | if (copy_from_user(buf, uurb->buffer, u)) { | |
1704 | ret = -EFAULT; | |
1705 | goto error; | |
1706 | } | |
01463900 | 1707 | uurb->buffer += u; |
3d97ff63 HG |
1708 | } |
1709 | totlen -= u; | |
1710 | } | |
1711 | } else if (uurb->buffer_length > 0) { | |
f7d34b44 SG |
1712 | if (as->usbm) { |
1713 | unsigned long uurb_start = (unsigned long)uurb->buffer; | |
3d97ff63 | 1714 | |
f7d34b44 SG |
1715 | as->urb->transfer_buffer = as->usbm->mem + |
1716 | (uurb_start - as->usbm->vm_start); | |
1717 | } else { | |
1718 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, | |
1719 | GFP_KERNEL); | |
1720 | if (!as->urb->transfer_buffer) { | |
1721 | ret = -ENOMEM; | |
3d97ff63 HG |
1722 | goto error; |
1723 | } | |
f7d34b44 SG |
1724 | if (!is_in) { |
1725 | if (copy_from_user(as->urb->transfer_buffer, | |
1726 | uurb->buffer, | |
1727 | uurb->buffer_length)) { | |
1728 | ret = -EFAULT; | |
1729 | goto error; | |
1730 | } | |
1731 | } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) { | |
1732 | /* | |
1733 | * Isochronous input data may end up being | |
1734 | * discontiguous if some of the packets are | |
1735 | * short. Clear the buffer so that the gaps | |
1736 | * don't leak kernel data to userspace. | |
1737 | */ | |
1738 | memset(as->urb->transfer_buffer, 0, | |
1739 | uurb->buffer_length); | |
1740 | } | |
3d97ff63 | 1741 | } |
9180135b | 1742 | } |
04e482ff GKH |
1743 | as->urb->dev = ps->dev; |
1744 | as->urb->pipe = (uurb->type << 30) | | |
93cf9b90 AS |
1745 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | |
1746 | (uurb->endpoint & USB_DIR_IN); | |
14722ef4 AS |
1747 | |
1748 | /* This tedious sequence is necessary because the URB_* flags | |
1749 | * are internal to the kernel and subject to change, whereas | |
1750 | * the USBDEVFS_URB_* flags are a user API and must not be changed. | |
1751 | */ | |
1752 | u = (is_in ? URB_DIR_IN : URB_DIR_OUT); | |
1753 | if (uurb->flags & USBDEVFS_URB_ISO_ASAP) | |
1754 | u |= URB_ISO_ASAP; | |
7a68d9fb | 1755 | if (allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) |
14722ef4 | 1756 | u |= URB_SHORT_NOT_OK; |
7a68d9fb | 1757 | if (allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET) |
14722ef4 AS |
1758 | u |= URB_ZERO_PACKET; |
1759 | if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT) | |
1760 | u |= URB_NO_INTERRUPT; | |
1761 | as->urb->transfer_flags = u; | |
1762 | ||
81e0403b ON |
1763 | if (!allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) |
1764 | dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_SHORT_NOT_OK.\n"); | |
1765 | if (!allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET) | |
1766 | dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_ZERO_PACKET.\n"); | |
1767 | ||
1da177e4 | 1768 | as->urb->transfer_buffer_length = uurb->buffer_length; |
04e482ff | 1769 | as->urb->setup_packet = (unsigned char *)dr; |
52fb743d | 1770 | dr = NULL; |
1da177e4 | 1771 | as->urb->start_frame = uurb->start_frame; |
b2d03eb5 | 1772 | as->urb->number_of_packets = number_of_packets; |
948cd8c1 | 1773 | as->urb->stream_id = stream_id; |
53e5f36f AS |
1774 | |
1775 | if (ep->desc.bInterval) { | |
1776 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || | |
1777 | ps->dev->speed == USB_SPEED_HIGH || | |
1778 | ps->dev->speed >= USB_SPEED_SUPER) | |
1779 | as->urb->interval = 1 << | |
1780 | min(15, ep->desc.bInterval - 1); | |
1781 | else | |
1782 | as->urb->interval = ep->desc.bInterval; | |
1783 | } | |
1784 | ||
04e482ff GKH |
1785 | as->urb->context = as; |
1786 | as->urb->complete = async_completed; | |
b2d03eb5 | 1787 | for (totlen = u = 0; u < number_of_packets; u++) { |
1da177e4 LT |
1788 | as->urb->iso_frame_desc[u].offset = totlen; |
1789 | as->urb->iso_frame_desc[u].length = isopkt[u].length; | |
1790 | totlen += isopkt[u].length; | |
1791 | } | |
6fd19f4b | 1792 | kfree(isopkt); |
52fb743d | 1793 | isopkt = NULL; |
1da177e4 | 1794 | as->ps = ps; |
04e482ff | 1795 | as->userurb = arg; |
70f1b0d3 | 1796 | as->userurb_sigval = userurb_sigval; |
f7d34b44 SG |
1797 | if (as->usbm) { |
1798 | unsigned long uurb_start = (unsigned long)uurb->buffer; | |
1799 | ||
1800 | as->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
1801 | as->urb->transfer_dma = as->usbm->dma_handle + | |
1802 | (uurb_start - as->usbm->vm_start); | |
1803 | } else if (is_in && uurb->buffer_length > 0) | |
1da177e4 | 1804 | as->userbuffer = uurb->buffer; |
1da177e4 LT |
1805 | as->signr = uurb->signr; |
1806 | as->ifnum = ifnum; | |
2425c08b | 1807 | as->pid = get_pid(task_pid(current)); |
d178bc3a | 1808 | as->cred = get_current_cred(); |
4c6e8971 | 1809 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, |
0880aef4 | 1810 | as->urb->transfer_buffer_length, 0, SUBMIT, |
3d97ff63 HG |
1811 | NULL, 0); |
1812 | if (!is_in) | |
1813 | snoop_urb_data(as->urb, as->urb->transfer_buffer_length); | |
1814 | ||
04e482ff | 1815 | async_newpending(as); |
01c6460f AS |
1816 | |
1817 | if (usb_endpoint_xfer_bulk(&ep->desc)) { | |
1818 | spin_lock_irq(&ps->lock); | |
1819 | ||
1820 | /* Not exactly the endpoint address; the direction bit is | |
1821 | * shifted to the 0x10 position so that the value will be | |
1822 | * between 0 and 31. | |
1823 | */ | |
1824 | as->bulk_addr = usb_endpoint_num(&ep->desc) | | |
1825 | ((ep->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) | |
1826 | >> 3); | |
1827 | ||
1828 | /* If this bulk URB is the start of a new transfer, re-enable | |
1829 | * the endpoint. Otherwise mark it as a continuation URB. | |
1830 | */ | |
1831 | if (uurb->flags & USBDEVFS_URB_BULK_CONTINUATION) | |
1832 | as->bulk_status = AS_CONTINUATION; | |
1833 | else | |
1834 | ps->disabled_bulk_eps &= ~(1 << as->bulk_addr); | |
1835 | ||
1836 | /* Don't accept continuation URBs if the endpoint is | |
1837 | * disabled because of an earlier error. | |
1838 | */ | |
1839 | if (ps->disabled_bulk_eps & (1 << as->bulk_addr)) | |
1840 | ret = -EREMOTEIO; | |
1841 | else | |
1842 | ret = usb_submit_urb(as->urb, GFP_ATOMIC); | |
1843 | spin_unlock_irq(&ps->lock); | |
1844 | } else { | |
1845 | ret = usb_submit_urb(as->urb, GFP_KERNEL); | |
1846 | } | |
1847 | ||
1848 | if (ret) { | |
04e482ff GKH |
1849 | dev_printk(KERN_DEBUG, &ps->dev->dev, |
1850 | "usbfs: usb_submit_urb returned %d\n", ret); | |
4c6e8971 | 1851 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, |
0880aef4 | 1852 | 0, ret, COMPLETE, NULL, 0); |
04e482ff | 1853 | async_removepending(as); |
52fb743d | 1854 | goto error; |
04e482ff GKH |
1855 | } |
1856 | return 0; | |
52fb743d AS |
1857 | |
1858 | error: | |
1859 | kfree(isopkt); | |
1860 | kfree(dr); | |
1861 | if (as) | |
1862 | free_async(as); | |
1863 | return ret; | |
1da177e4 LT |
1864 | } |
1865 | ||
9b6f0c4b | 1866 | static int proc_submiturb(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1867 | { |
1868 | struct usbdevfs_urb uurb; | |
70f1b0d3 | 1869 | sigval_t userurb_sigval; |
1da177e4 LT |
1870 | |
1871 | if (copy_from_user(&uurb, arg, sizeof(uurb))) | |
1872 | return -EFAULT; | |
1873 | ||
70f1b0d3 EB |
1874 | memset(&userurb_sigval, 0, sizeof(userurb_sigval)); |
1875 | userurb_sigval.sival_ptr = arg; | |
1876 | ||
04e482ff GKH |
1877 | return proc_do_submiturb(ps, &uurb, |
1878 | (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), | |
70f1b0d3 | 1879 | arg, userurb_sigval); |
1da177e4 LT |
1880 | } |
1881 | ||
9b6f0c4b | 1882 | static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg) |
1da177e4 | 1883 | { |
4e09dcf2 | 1884 | struct urb *urb; |
1da177e4 | 1885 | struct async *as; |
4e09dcf2 | 1886 | unsigned long flags; |
1da177e4 | 1887 | |
4e09dcf2 | 1888 | spin_lock_irqsave(&ps->lock, flags); |
1da177e4 | 1889 | as = async_getpending(ps, arg); |
4e09dcf2 HL |
1890 | if (!as) { |
1891 | spin_unlock_irqrestore(&ps->lock, flags); | |
1da177e4 | 1892 | return -EINVAL; |
4e09dcf2 HL |
1893 | } |
1894 | ||
1895 | urb = as->urb; | |
1896 | usb_get_urb(urb); | |
1897 | spin_unlock_irqrestore(&ps->lock, flags); | |
1898 | ||
1899 | usb_kill_urb(urb); | |
1900 | usb_put_urb(urb); | |
1901 | ||
1da177e4 LT |
1902 | return 0; |
1903 | } | |
1904 | ||
2ef47001 AS |
1905 | static void compute_isochronous_actual_length(struct urb *urb) |
1906 | { | |
1907 | unsigned int i; | |
1908 | ||
1909 | if (urb->number_of_packets > 0) { | |
1910 | urb->actual_length = 0; | |
1911 | for (i = 0; i < urb->number_of_packets; i++) | |
1912 | urb->actual_length += | |
1913 | urb->iso_frame_desc[i].actual_length; | |
1914 | } | |
1915 | } | |
1916 | ||
1da177e4 LT |
1917 | static int processcompl(struct async *as, void __user * __user *arg) |
1918 | { | |
1919 | struct urb *urb = as->urb; | |
1920 | struct usbdevfs_urb __user *userurb = as->userurb; | |
1921 | void __user *addr = as->userurb; | |
1922 | unsigned int i; | |
1923 | ||
2ef47001 | 1924 | compute_isochronous_actual_length(urb); |
7152b592 | 1925 | if (as->userbuffer && urb->actual_length) { |
3d97ff63 | 1926 | if (copy_urb_data_to_user(as->userbuffer, urb)) |
d794a021 | 1927 | goto err_out; |
7152b592 | 1928 | } |
e015268d | 1929 | if (put_user(as->status, &userurb->status)) |
d794a021 | 1930 | goto err_out; |
1da177e4 | 1931 | if (put_user(urb->actual_length, &userurb->actual_length)) |
d794a021 | 1932 | goto err_out; |
1da177e4 | 1933 | if (put_user(urb->error_count, &userurb->error_count)) |
d794a021 | 1934 | goto err_out; |
1da177e4 | 1935 | |
93cf9b90 | 1936 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
668a9541 CL |
1937 | for (i = 0; i < urb->number_of_packets; i++) { |
1938 | if (put_user(urb->iso_frame_desc[i].actual_length, | |
1939 | &userurb->iso_frame_desc[i].actual_length)) | |
d794a021 | 1940 | goto err_out; |
668a9541 CL |
1941 | if (put_user(urb->iso_frame_desc[i].status, |
1942 | &userurb->iso_frame_desc[i].status)) | |
d794a021 | 1943 | goto err_out; |
668a9541 | 1944 | } |
1da177e4 LT |
1945 | } |
1946 | ||
1da177e4 LT |
1947 | if (put_user(addr, (void __user * __user *)arg)) |
1948 | return -EFAULT; | |
1949 | return 0; | |
d794a021 ON |
1950 | |
1951 | err_out: | |
d794a021 | 1952 | return -EFAULT; |
1da177e4 LT |
1953 | } |
1954 | ||
9b6f0c4b | 1955 | static struct async *reap_as(struct usb_dev_state *ps) |
1da177e4 | 1956 | { |
04e482ff | 1957 | DECLARE_WAITQUEUE(wait, current); |
1da177e4 LT |
1958 | struct async *as = NULL; |
1959 | struct usb_device *dev = ps->dev; | |
1960 | ||
1961 | add_wait_queue(&ps->wait, &wait); | |
1962 | for (;;) { | |
1963 | __set_current_state(TASK_INTERRUPTIBLE); | |
04e482ff | 1964 | as = async_getcompleted(ps); |
3f2cee73 | 1965 | if (as || !connected(ps)) |
1da177e4 LT |
1966 | break; |
1967 | if (signal_pending(current)) | |
1968 | break; | |
1969 | usb_unlock_device(dev); | |
1970 | schedule(); | |
1971 | usb_lock_device(dev); | |
1972 | } | |
1973 | remove_wait_queue(&ps->wait, &wait); | |
1974 | set_current_state(TASK_RUNNING); | |
1975 | return as; | |
1976 | } | |
1977 | ||
9b6f0c4b | 1978 | static int proc_reapurb(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
1979 | { |
1980 | struct async *as = reap_as(ps); | |
a016a816 | 1981 | |
ddeee0b2 | 1982 | if (as) { |
a016a816 AS |
1983 | int retval; |
1984 | ||
2f964780 | 1985 | snoop(&ps->dev->dev, "reap %pK\n", as->userurb); |
a016a816 | 1986 | retval = processcompl(as, (void __user * __user *)arg); |
ddeee0b2 LT |
1987 | free_async(as); |
1988 | return retval; | |
1989 | } | |
1da177e4 LT |
1990 | if (signal_pending(current)) |
1991 | return -EINTR; | |
3f2cee73 | 1992 | return -ENODEV; |
1da177e4 LT |
1993 | } |
1994 | ||
9b6f0c4b | 1995 | static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) |
1da177e4 | 1996 | { |
ddeee0b2 | 1997 | int retval; |
1da177e4 LT |
1998 | struct async *as; |
1999 | ||
ddeee0b2 | 2000 | as = async_getcompleted(ps); |
ddeee0b2 | 2001 | if (as) { |
2f964780 | 2002 | snoop(&ps->dev->dev, "reap %pK\n", as->userurb); |
ddeee0b2 LT |
2003 | retval = processcompl(as, (void __user * __user *)arg); |
2004 | free_async(as); | |
3f2cee73 AS |
2005 | } else { |
2006 | retval = (connected(ps) ? -EAGAIN : -ENODEV); | |
ddeee0b2 LT |
2007 | } |
2008 | return retval; | |
1da177e4 LT |
2009 | } |
2010 | ||
2011 | #ifdef CONFIG_COMPAT | |
9b6f0c4b | 2012 | static int proc_control_compat(struct usb_dev_state *ps, |
637e8a60 AB |
2013 | struct usbdevfs_ctrltransfer32 __user *p32) |
2014 | { | |
5b32c385 MB |
2015 | struct usbdevfs_ctrltransfer __user *p; |
2016 | __u32 udata; | |
2017 | p = compat_alloc_user_space(sizeof(*p)); | |
2018 | if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || | |
2019 | get_user(udata, &p32->data) || | |
637e8a60 AB |
2020 | put_user(compat_ptr(udata), &p->data)) |
2021 | return -EFAULT; | |
5b32c385 | 2022 | return proc_control(ps, p); |
637e8a60 AB |
2023 | } |
2024 | ||
9b6f0c4b | 2025 | static int proc_bulk_compat(struct usb_dev_state *ps, |
637e8a60 AB |
2026 | struct usbdevfs_bulktransfer32 __user *p32) |
2027 | { | |
06793f2d MB |
2028 | struct usbdevfs_bulktransfer __user *p; |
2029 | compat_uint_t n; | |
2030 | compat_caddr_t addr; | |
637e8a60 | 2031 | |
06793f2d | 2032 | p = compat_alloc_user_space(sizeof(*p)); |
637e8a60 | 2033 | |
06793f2d MB |
2034 | if (get_user(n, &p32->ep) || put_user(n, &p->ep) || |
2035 | get_user(n, &p32->len) || put_user(n, &p->len) || | |
2036 | get_user(n, &p32->timeout) || put_user(n, &p->timeout) || | |
2037 | get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) | |
2038 | return -EFAULT; | |
637e8a60 | 2039 | |
06793f2d | 2040 | return proc_bulk(ps, p); |
637e8a60 | 2041 | } |
9b6f0c4b | 2042 | static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg) |
637e8a60 AB |
2043 | { |
2044 | struct usbdevfs_disconnectsignal32 ds; | |
2045 | ||
2046 | if (copy_from_user(&ds, arg, sizeof(ds))) | |
2047 | return -EFAULT; | |
2048 | ps->discsignr = ds.signr; | |
70f1b0d3 | 2049 | ps->disccontext.sival_int = ds.context; |
637e8a60 AB |
2050 | return 0; |
2051 | } | |
1da177e4 LT |
2052 | |
2053 | static int get_urb32(struct usbdevfs_urb *kurb, | |
2054 | struct usbdevfs_urb32 __user *uurb) | |
2055 | { | |
cc1a7c4b AV |
2056 | struct usbdevfs_urb32 urb32; |
2057 | if (copy_from_user(&urb32, uurb, sizeof(*uurb))) | |
1da177e4 | 2058 | return -EFAULT; |
cc1a7c4b AV |
2059 | kurb->type = urb32.type; |
2060 | kurb->endpoint = urb32.endpoint; | |
2061 | kurb->status = urb32.status; | |
2062 | kurb->flags = urb32.flags; | |
2063 | kurb->buffer = compat_ptr(urb32.buffer); | |
2064 | kurb->buffer_length = urb32.buffer_length; | |
2065 | kurb->actual_length = urb32.actual_length; | |
2066 | kurb->start_frame = urb32.start_frame; | |
2067 | kurb->number_of_packets = urb32.number_of_packets; | |
2068 | kurb->error_count = urb32.error_count; | |
2069 | kurb->signr = urb32.signr; | |
2070 | kurb->usercontext = compat_ptr(urb32.usercontext); | |
1da177e4 LT |
2071 | return 0; |
2072 | } | |
2073 | ||
9b6f0c4b | 2074 | static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
2075 | { |
2076 | struct usbdevfs_urb uurb; | |
70f1b0d3 | 2077 | sigval_t userurb_sigval; |
1da177e4 | 2078 | |
04e482ff | 2079 | if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg)) |
1da177e4 LT |
2080 | return -EFAULT; |
2081 | ||
70f1b0d3 EB |
2082 | memset(&userurb_sigval, 0, sizeof(userurb_sigval)); |
2083 | userurb_sigval.sival_int = ptr_to_compat(arg); | |
2084 | ||
04e482ff GKH |
2085 | return proc_do_submiturb(ps, &uurb, |
2086 | ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, | |
70f1b0d3 | 2087 | arg, userurb_sigval); |
1da177e4 LT |
2088 | } |
2089 | ||
2090 | static int processcompl_compat(struct async *as, void __user * __user *arg) | |
2091 | { | |
2092 | struct urb *urb = as->urb; | |
2093 | struct usbdevfs_urb32 __user *userurb = as->userurb; | |
2094 | void __user *addr = as->userurb; | |
2095 | unsigned int i; | |
2096 | ||
2ef47001 | 2097 | compute_isochronous_actual_length(urb); |
2102e06a | 2098 | if (as->userbuffer && urb->actual_length) { |
3d97ff63 | 2099 | if (copy_urb_data_to_user(as->userbuffer, urb)) |
1da177e4 | 2100 | return -EFAULT; |
2102e06a | 2101 | } |
e015268d | 2102 | if (put_user(as->status, &userurb->status)) |
1da177e4 LT |
2103 | return -EFAULT; |
2104 | if (put_user(urb->actual_length, &userurb->actual_length)) | |
2105 | return -EFAULT; | |
2106 | if (put_user(urb->error_count, &userurb->error_count)) | |
2107 | return -EFAULT; | |
2108 | ||
93cf9b90 | 2109 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
668a9541 CL |
2110 | for (i = 0; i < urb->number_of_packets; i++) { |
2111 | if (put_user(urb->iso_frame_desc[i].actual_length, | |
2112 | &userurb->iso_frame_desc[i].actual_length)) | |
2113 | return -EFAULT; | |
2114 | if (put_user(urb->iso_frame_desc[i].status, | |
2115 | &userurb->iso_frame_desc[i].status)) | |
2116 | return -EFAULT; | |
2117 | } | |
1da177e4 LT |
2118 | } |
2119 | ||
c714de5d | 2120 | if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) |
1da177e4 LT |
2121 | return -EFAULT; |
2122 | return 0; | |
2123 | } | |
2124 | ||
9b6f0c4b | 2125 | static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
2126 | { |
2127 | struct async *as = reap_as(ps); | |
a016a816 | 2128 | |
ddeee0b2 | 2129 | if (as) { |
a016a816 AS |
2130 | int retval; |
2131 | ||
2f964780 | 2132 | snoop(&ps->dev->dev, "reap %pK\n", as->userurb); |
a016a816 | 2133 | retval = processcompl_compat(as, (void __user * __user *)arg); |
ddeee0b2 LT |
2134 | free_async(as); |
2135 | return retval; | |
2136 | } | |
1da177e4 LT |
2137 | if (signal_pending(current)) |
2138 | return -EINTR; | |
3f2cee73 | 2139 | return -ENODEV; |
1da177e4 LT |
2140 | } |
2141 | ||
9b6f0c4b | 2142 | static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg) |
1da177e4 | 2143 | { |
ddeee0b2 | 2144 | int retval; |
1da177e4 LT |
2145 | struct async *as; |
2146 | ||
ddeee0b2 LT |
2147 | as = async_getcompleted(ps); |
2148 | if (as) { | |
2f964780 | 2149 | snoop(&ps->dev->dev, "reap %pK\n", as->userurb); |
ddeee0b2 LT |
2150 | retval = processcompl_compat(as, (void __user * __user *)arg); |
2151 | free_async(as); | |
3f2cee73 AS |
2152 | } else { |
2153 | retval = (connected(ps) ? -EAGAIN : -ENODEV); | |
ddeee0b2 LT |
2154 | } |
2155 | return retval; | |
1da177e4 LT |
2156 | } |
2157 | ||
637e8a60 | 2158 | |
1da177e4 LT |
2159 | #endif |
2160 | ||
9b6f0c4b | 2161 | static int proc_disconnectsignal(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
2162 | { |
2163 | struct usbdevfs_disconnectsignal ds; | |
2164 | ||
2165 | if (copy_from_user(&ds, arg, sizeof(ds))) | |
2166 | return -EFAULT; | |
1da177e4 | 2167 | ps->discsignr = ds.signr; |
70f1b0d3 | 2168 | ps->disccontext.sival_ptr = ds.context; |
1da177e4 LT |
2169 | return 0; |
2170 | } | |
2171 | ||
9b6f0c4b | 2172 | static int proc_claiminterface(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
2173 | { |
2174 | unsigned int ifnum; | |
2175 | ||
2176 | if (get_user(ifnum, (unsigned int __user *)arg)) | |
2177 | return -EFAULT; | |
2178 | return claimintf(ps, ifnum); | |
2179 | } | |
2180 | ||
9b6f0c4b | 2181 | static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg) |
1da177e4 LT |
2182 | { |
2183 | unsigned int ifnum; | |
2184 | int ret; | |
2185 | ||
2186 | if (get_user(ifnum, (unsigned int __user *)arg)) | |
2187 | return -EFAULT; | |
135551ea KB |
2188 | ret = releaseintf(ps, ifnum); |
2189 | if (ret < 0) | |
1da177e4 | 2190 | return ret; |
64f10edf | 2191 | destroy_async_on_interface(ps, ifnum); |
1da177e4 LT |
2192 | return 0; |
2193 | } | |
2194 | ||
9b6f0c4b | 2195 | static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) |
1da177e4 | 2196 | { |
1da177e4 LT |
2197 | int size; |
2198 | void *buf = NULL; | |
2199 | int retval = 0; | |
2200 | struct usb_interface *intf = NULL; | |
2201 | struct usb_driver *driver = NULL; | |
1da177e4 | 2202 | |
d883f52e RG |
2203 | if (ps->privileges_dropped) |
2204 | return -EACCES; | |
2205 | ||
086ebf92 WH |
2206 | if (!connected(ps)) |
2207 | return -ENODEV; | |
2208 | ||
c36fc889 | 2209 | /* alloc buffer */ |
135551ea KB |
2210 | size = _IOC_SIZE(ctl->ioctl_code); |
2211 | if (size > 0) { | |
4baf0df7 Tİ |
2212 | buf = kmalloc(size, GFP_KERNEL); |
2213 | if (buf == NULL) | |
1da177e4 | 2214 | return -ENOMEM; |
c36fc889 | 2215 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { |
04e482ff | 2216 | if (copy_from_user(buf, ctl->data, size)) { |
6fd19f4b | 2217 | kfree(buf); |
1da177e4 LT |
2218 | return -EFAULT; |
2219 | } | |
2220 | } else { | |
04e482ff | 2221 | memset(buf, 0, size); |
1da177e4 LT |
2222 | } |
2223 | } | |
2224 | ||
1da177e4 LT |
2225 | if (ps->dev->state != USB_STATE_CONFIGURED) |
2226 | retval = -EHOSTUNREACH; | |
04e482ff GKH |
2227 | else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) |
2228 | retval = -EINVAL; | |
c36fc889 | 2229 | else switch (ctl->ioctl_code) { |
1da177e4 LT |
2230 | |
2231 | /* disconnect kernel driver from interface */ | |
2232 | case USBDEVFS_DISCONNECT: | |
1da177e4 LT |
2233 | if (intf->dev.driver) { |
2234 | driver = to_usb_driver(intf->dev.driver); | |
04e482ff | 2235 | dev_dbg(&intf->dev, "disconnect by usbfs\n"); |
1da177e4 LT |
2236 | usb_driver_release_interface(driver, intf); |
2237 | } else | |
2238 | retval = -ENODATA; | |
1da177e4 LT |
2239 | break; |
2240 | ||
2241 | /* let kernel drivers try to (re)bind to the interface */ | |
2242 | case USBDEVFS_CONNECT: | |
885e9747 AS |
2243 | if (!intf->dev.driver) |
2244 | retval = device_attach(&intf->dev); | |
2245 | else | |
2246 | retval = -EBUSY; | |
1da177e4 LT |
2247 | break; |
2248 | ||
2249 | /* talk directly to the interface's driver */ | |
2250 | default: | |
1da177e4 LT |
2251 | if (intf->dev.driver) |
2252 | driver = to_usb_driver(intf->dev.driver); | |
c532b29a | 2253 | if (driver == NULL || driver->unlocked_ioctl == NULL) { |
1da177e4 LT |
2254 | retval = -ENOTTY; |
2255 | } else { | |
c532b29a | 2256 | retval = driver->unlocked_ioctl(intf, ctl->ioctl_code, buf); |
1da177e4 LT |
2257 | if (retval == -ENOIOCTLCMD) |
2258 | retval = -ENOTTY; | |
2259 | } | |
1da177e4 LT |
2260 | } |
2261 | ||
2262 | /* cleanup and return */ | |
2263 | if (retval >= 0 | |
04e482ff | 2264 | && (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0 |
1da177e4 | 2265 | && size > 0 |
04e482ff | 2266 | && copy_to_user(ctl->data, buf, size) != 0) |
1da177e4 | 2267 | retval = -EFAULT; |
6fd19f4b JJ |
2268 | |
2269 | kfree(buf); | |
1da177e4 LT |
2270 | return retval; |
2271 | } | |
2272 | ||
9b6f0c4b | 2273 | static int proc_ioctl_default(struct usb_dev_state *ps, void __user *arg) |
c36fc889 PZ |
2274 | { |
2275 | struct usbdevfs_ioctl ctrl; | |
2276 | ||
04e482ff | 2277 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
c36fc889 PZ |
2278 | return -EFAULT; |
2279 | return proc_ioctl(ps, &ctrl); | |
2280 | } | |
2281 | ||
2282 | #ifdef CONFIG_COMPAT | |
9b6f0c4b | 2283 | static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg) |
c36fc889 | 2284 | { |
cc1a7c4b | 2285 | struct usbdevfs_ioctl32 ioc32; |
c36fc889 | 2286 | struct usbdevfs_ioctl ctrl; |
c36fc889 | 2287 | |
cc1a7c4b | 2288 | if (copy_from_user(&ioc32, compat_ptr(arg), sizeof(ioc32))) |
c36fc889 | 2289 | return -EFAULT; |
cc1a7c4b AV |
2290 | ctrl.ifno = ioc32.ifno; |
2291 | ctrl.ioctl_code = ioc32.ioctl_code; | |
2292 | ctrl.data = compat_ptr(ioc32.data); | |
c36fc889 PZ |
2293 | return proc_ioctl(ps, &ctrl); |
2294 | } | |
2295 | #endif | |
2296 | ||
9b6f0c4b | 2297 | static int proc_claim_port(struct usb_dev_state *ps, void __user *arg) |
7cbe5dca AS |
2298 | { |
2299 | unsigned portnum; | |
2300 | int rc; | |
2301 | ||
2302 | if (get_user(portnum, (unsigned __user *) arg)) | |
2303 | return -EFAULT; | |
2304 | rc = usb_hub_claim_port(ps->dev, portnum, ps); | |
2305 | if (rc == 0) | |
2306 | snoop(&ps->dev->dev, "port %d claimed by process %d: %s\n", | |
2307 | portnum, task_pid_nr(current), current->comm); | |
2308 | return rc; | |
2309 | } | |
2310 | ||
9b6f0c4b | 2311 | static int proc_release_port(struct usb_dev_state *ps, void __user *arg) |
7cbe5dca AS |
2312 | { |
2313 | unsigned portnum; | |
2314 | ||
2315 | if (get_user(portnum, (unsigned __user *) arg)) | |
2316 | return -EFAULT; | |
2317 | return usb_hub_release_port(ps->dev, portnum, ps); | |
2318 | } | |
2319 | ||
9b6f0c4b | 2320 | static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) |
19181bc5 HG |
2321 | { |
2322 | __u32 caps; | |
2323 | ||
3f2cee73 | 2324 | caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | |
d883f52e | 2325 | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | |
4ed33505 AS |
2326 | USBDEVFS_CAP_DROP_PRIVILEGES | |
2327 | USBDEVFS_CAP_CONNINFO_EX | MAYBE_CAP_SUSPEND; | |
19181bc5 HG |
2328 | if (!ps->dev->bus->no_stop_on_short) |
2329 | caps |= USBDEVFS_CAP_BULK_CONTINUATION; | |
3d97ff63 HG |
2330 | if (ps->dev->bus->sg_tablesize) |
2331 | caps |= USBDEVFS_CAP_BULK_SCATTER_GATHER; | |
19181bc5 HG |
2332 | |
2333 | if (put_user(caps, (__u32 __user *)arg)) | |
2334 | return -EFAULT; | |
2335 | ||
2336 | return 0; | |
2337 | } | |
2338 | ||
9b6f0c4b | 2339 | static int proc_disconnect_claim(struct usb_dev_state *ps, void __user *arg) |
0837e7e5 HG |
2340 | { |
2341 | struct usbdevfs_disconnect_claim dc; | |
2342 | struct usb_interface *intf; | |
2343 | ||
2344 | if (copy_from_user(&dc, arg, sizeof(dc))) | |
2345 | return -EFAULT; | |
2346 | ||
2347 | intf = usb_ifnum_to_if(ps->dev, dc.interface); | |
2348 | if (!intf) | |
2349 | return -EINVAL; | |
2350 | ||
2351 | if (intf->dev.driver) { | |
2352 | struct usb_driver *driver = to_usb_driver(intf->dev.driver); | |
2353 | ||
d883f52e RG |
2354 | if (ps->privileges_dropped) |
2355 | return -EACCES; | |
2356 | ||
0837e7e5 HG |
2357 | if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER) && |
2358 | strncmp(dc.driver, intf->dev.driver->name, | |
2359 | sizeof(dc.driver)) != 0) | |
2360 | return -EBUSY; | |
2361 | ||
2362 | if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER) && | |
2363 | strncmp(dc.driver, intf->dev.driver->name, | |
2364 | sizeof(dc.driver)) == 0) | |
2365 | return -EBUSY; | |
2366 | ||
2367 | dev_dbg(&intf->dev, "disconnect by usbfs\n"); | |
2368 | usb_driver_release_interface(driver, intf); | |
2369 | } | |
2370 | ||
2371 | return claimintf(ps, dc.interface); | |
2372 | } | |
2373 | ||
3e75c6de | 2374 | static int proc_alloc_streams(struct usb_dev_state *ps, void __user *arg) |
bcf7f6e3 HG |
2375 | { |
2376 | unsigned num_streams, num_eps; | |
2377 | struct usb_host_endpoint **eps; | |
2378 | struct usb_interface *intf; | |
2379 | int r; | |
2380 | ||
2381 | r = parse_usbdevfs_streams(ps, arg, &num_streams, &num_eps, | |
2382 | &eps, &intf); | |
2383 | if (r) | |
2384 | return r; | |
2385 | ||
2386 | destroy_async_on_interface(ps, | |
2387 | intf->altsetting[0].desc.bInterfaceNumber); | |
2388 | ||
2389 | r = usb_alloc_streams(intf, eps, num_eps, num_streams, GFP_KERNEL); | |
2390 | kfree(eps); | |
2391 | return r; | |
2392 | } | |
2393 | ||
3e75c6de | 2394 | static int proc_free_streams(struct usb_dev_state *ps, void __user *arg) |
bcf7f6e3 HG |
2395 | { |
2396 | unsigned num_eps; | |
2397 | struct usb_host_endpoint **eps; | |
2398 | struct usb_interface *intf; | |
2399 | int r; | |
2400 | ||
2401 | r = parse_usbdevfs_streams(ps, arg, NULL, &num_eps, &eps, &intf); | |
2402 | if (r) | |
2403 | return r; | |
2404 | ||
2405 | destroy_async_on_interface(ps, | |
2406 | intf->altsetting[0].desc.bInterfaceNumber); | |
2407 | ||
2408 | r = usb_free_streams(intf, eps, num_eps, GFP_KERNEL); | |
2409 | kfree(eps); | |
2410 | return r; | |
2411 | } | |
2412 | ||
d883f52e RG |
2413 | static int proc_drop_privileges(struct usb_dev_state *ps, void __user *arg) |
2414 | { | |
2415 | u32 data; | |
2416 | ||
2417 | if (copy_from_user(&data, arg, sizeof(data))) | |
2418 | return -EFAULT; | |
2419 | ||
0f5e1558 | 2420 | /* This is a one way operation. Once privileges are |
d883f52e RG |
2421 | * dropped, you cannot regain them. You may however reissue |
2422 | * this ioctl to shrink the allowed interfaces mask. | |
2423 | */ | |
2424 | ps->interface_allowed_mask &= data; | |
2425 | ps->privileges_dropped = true; | |
2426 | ||
2427 | return 0; | |
2428 | } | |
2429 | ||
7794f486 AS |
2430 | static int proc_forbid_suspend(struct usb_dev_state *ps) |
2431 | { | |
2432 | int ret = 0; | |
2433 | ||
2434 | if (ps->suspend_allowed) { | |
2435 | ret = usb_autoresume_device(ps->dev); | |
2436 | if (ret == 0) | |
2437 | ps->suspend_allowed = false; | |
2438 | else if (ret != -ENODEV) | |
2439 | ret = -EIO; | |
2440 | } | |
2441 | return ret; | |
2442 | } | |
2443 | ||
2444 | static int proc_allow_suspend(struct usb_dev_state *ps) | |
2445 | { | |
2446 | if (!connected(ps)) | |
2447 | return -ENODEV; | |
2448 | ||
2449 | WRITE_ONCE(ps->not_yet_resumed, 1); | |
2450 | if (!ps->suspend_allowed) { | |
2451 | usb_autosuspend_device(ps->dev); | |
2452 | ps->suspend_allowed = true; | |
2453 | } | |
2454 | return 0; | |
2455 | } | |
2456 | ||
2457 | static int proc_wait_for_resume(struct usb_dev_state *ps) | |
2458 | { | |
2459 | int ret; | |
2460 | ||
2461 | usb_unlock_device(ps->dev); | |
2462 | ret = wait_event_interruptible(ps->wait_for_resume, | |
2463 | READ_ONCE(ps->not_yet_resumed) == 0); | |
2464 | usb_lock_device(ps->dev); | |
2465 | ||
2466 | if (ret != 0) | |
2467 | return -EINTR; | |
2468 | return proc_forbid_suspend(ps); | |
2469 | } | |
2470 | ||
1da177e4 LT |
2471 | /* |
2472 | * NOTE: All requests here that have interface numbers as parameters | |
2473 | * are assuming that somehow the configuration has been prevented from | |
2474 | * changing. But there's no mechanism to ensure that... | |
2475 | */ | |
637e8a60 AB |
2476 | static long usbdev_do_ioctl(struct file *file, unsigned int cmd, |
2477 | void __user *p) | |
1da177e4 | 2478 | { |
9b6f0c4b | 2479 | struct usb_dev_state *ps = file->private_data; |
496ad9aa | 2480 | struct inode *inode = file_inode(file); |
1da177e4 | 2481 | struct usb_device *dev = ps->dev; |
1da177e4 LT |
2482 | int ret = -ENOTTY; |
2483 | ||
2484 | if (!(file->f_mode & FMODE_WRITE)) | |
2485 | return -EPERM; | |
01412a21 | 2486 | |
1da177e4 | 2487 | usb_lock_device(dev); |
3f2cee73 AS |
2488 | |
2489 | /* Reap operations are allowed even after disconnection */ | |
2490 | switch (cmd) { | |
2491 | case USBDEVFS_REAPURB: | |
2492 | snoop(&dev->dev, "%s: REAPURB\n", __func__); | |
2493 | ret = proc_reapurb(ps, p); | |
2494 | goto done; | |
2495 | ||
2496 | case USBDEVFS_REAPURBNDELAY: | |
2497 | snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); | |
2498 | ret = proc_reapurbnonblock(ps, p); | |
2499 | goto done; | |
2500 | ||
2501 | #ifdef CONFIG_COMPAT | |
2502 | case USBDEVFS_REAPURB32: | |
2503 | snoop(&dev->dev, "%s: REAPURB32\n", __func__); | |
2504 | ret = proc_reapurb_compat(ps, p); | |
2505 | goto done; | |
2506 | ||
2507 | case USBDEVFS_REAPURBNDELAY32: | |
2508 | snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); | |
2509 | ret = proc_reapurbnonblock_compat(ps, p); | |
2510 | goto done; | |
2511 | #endif | |
2512 | } | |
2513 | ||
349710c3 | 2514 | if (!connected(ps)) { |
1da177e4 LT |
2515 | usb_unlock_device(dev); |
2516 | return -ENODEV; | |
2517 | } | |
2518 | ||
2519 | switch (cmd) { | |
2520 | case USBDEVFS_CONTROL: | |
441b62c1 | 2521 | snoop(&dev->dev, "%s: CONTROL\n", __func__); |
1da177e4 LT |
2522 | ret = proc_control(ps, p); |
2523 | if (ret >= 0) | |
078cd827 | 2524 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2525 | break; |
2526 | ||
2527 | case USBDEVFS_BULK: | |
441b62c1 | 2528 | snoop(&dev->dev, "%s: BULK\n", __func__); |
1da177e4 LT |
2529 | ret = proc_bulk(ps, p); |
2530 | if (ret >= 0) | |
078cd827 | 2531 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2532 | break; |
2533 | ||
2534 | case USBDEVFS_RESETEP: | |
441b62c1 | 2535 | snoop(&dev->dev, "%s: RESETEP\n", __func__); |
1da177e4 LT |
2536 | ret = proc_resetep(ps, p); |
2537 | if (ret >= 0) | |
078cd827 | 2538 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2539 | break; |
2540 | ||
2541 | case USBDEVFS_RESET: | |
441b62c1 | 2542 | snoop(&dev->dev, "%s: RESET\n", __func__); |
1da177e4 LT |
2543 | ret = proc_resetdevice(ps); |
2544 | break; | |
2545 | ||
2546 | case USBDEVFS_CLEAR_HALT: | |
441b62c1 | 2547 | snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__); |
1da177e4 LT |
2548 | ret = proc_clearhalt(ps, p); |
2549 | if (ret >= 0) | |
078cd827 | 2550 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2551 | break; |
2552 | ||
2553 | case USBDEVFS_GETDRIVER: | |
441b62c1 | 2554 | snoop(&dev->dev, "%s: GETDRIVER\n", __func__); |
1da177e4 LT |
2555 | ret = proc_getdriver(ps, p); |
2556 | break; | |
2557 | ||
2558 | case USBDEVFS_CONNECTINFO: | |
441b62c1 | 2559 | snoop(&dev->dev, "%s: CONNECTINFO\n", __func__); |
1da177e4 LT |
2560 | ret = proc_connectinfo(ps, p); |
2561 | break; | |
2562 | ||
2563 | case USBDEVFS_SETINTERFACE: | |
441b62c1 | 2564 | snoop(&dev->dev, "%s: SETINTERFACE\n", __func__); |
1da177e4 LT |
2565 | ret = proc_setintf(ps, p); |
2566 | break; | |
2567 | ||
2568 | case USBDEVFS_SETCONFIGURATION: | |
441b62c1 | 2569 | snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__); |
1da177e4 LT |
2570 | ret = proc_setconfig(ps, p); |
2571 | break; | |
2572 | ||
2573 | case USBDEVFS_SUBMITURB: | |
441b62c1 | 2574 | snoop(&dev->dev, "%s: SUBMITURB\n", __func__); |
1da177e4 LT |
2575 | ret = proc_submiturb(ps, p); |
2576 | if (ret >= 0) | |
078cd827 | 2577 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2578 | break; |
2579 | ||
2580 | #ifdef CONFIG_COMPAT | |
637e8a60 AB |
2581 | case USBDEVFS_CONTROL32: |
2582 | snoop(&dev->dev, "%s: CONTROL32\n", __func__); | |
2583 | ret = proc_control_compat(ps, p); | |
2584 | if (ret >= 0) | |
078cd827 | 2585 | inode->i_mtime = current_time(inode); |
637e8a60 AB |
2586 | break; |
2587 | ||
2588 | case USBDEVFS_BULK32: | |
2589 | snoop(&dev->dev, "%s: BULK32\n", __func__); | |
2590 | ret = proc_bulk_compat(ps, p); | |
2591 | if (ret >= 0) | |
078cd827 | 2592 | inode->i_mtime = current_time(inode); |
637e8a60 AB |
2593 | break; |
2594 | ||
2595 | case USBDEVFS_DISCSIGNAL32: | |
2596 | snoop(&dev->dev, "%s: DISCSIGNAL32\n", __func__); | |
2597 | ret = proc_disconnectsignal_compat(ps, p); | |
2598 | break; | |
1da177e4 LT |
2599 | |
2600 | case USBDEVFS_SUBMITURB32: | |
441b62c1 | 2601 | snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); |
1da177e4 LT |
2602 | ret = proc_submiturb_compat(ps, p); |
2603 | if (ret >= 0) | |
078cd827 | 2604 | inode->i_mtime = current_time(inode); |
1da177e4 LT |
2605 | break; |
2606 | ||
c36fc889 | 2607 | case USBDEVFS_IOCTL32: |
637e8a60 | 2608 | snoop(&dev->dev, "%s: IOCTL32\n", __func__); |
c714de5d | 2609 | ret = proc_ioctl_compat(ps, ptr_to_compat(p)); |
c36fc889 | 2610 | break; |
1da177e4 LT |
2611 | #endif |
2612 | ||
2613 | case USBDEVFS_DISCARDURB: | |
2f964780 | 2614 | snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p); |
1da177e4 LT |
2615 | ret = proc_unlinkurb(ps, p); |
2616 | break; | |
2617 | ||
1da177e4 | 2618 | case USBDEVFS_DISCSIGNAL: |
441b62c1 | 2619 | snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__); |
1da177e4 LT |
2620 | ret = proc_disconnectsignal(ps, p); |
2621 | break; | |
2622 | ||
2623 | case USBDEVFS_CLAIMINTERFACE: | |
441b62c1 | 2624 | snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__); |
1da177e4 LT |
2625 | ret = proc_claiminterface(ps, p); |
2626 | break; | |
2627 | ||
2628 | case USBDEVFS_RELEASEINTERFACE: | |
441b62c1 | 2629 | snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__); |
1da177e4 LT |
2630 | ret = proc_releaseinterface(ps, p); |
2631 | break; | |
2632 | ||
2633 | case USBDEVFS_IOCTL: | |
441b62c1 | 2634 | snoop(&dev->dev, "%s: IOCTL\n", __func__); |
c36fc889 | 2635 | ret = proc_ioctl_default(ps, p); |
1da177e4 | 2636 | break; |
7cbe5dca AS |
2637 | |
2638 | case USBDEVFS_CLAIM_PORT: | |
2639 | snoop(&dev->dev, "%s: CLAIM_PORT\n", __func__); | |
2640 | ret = proc_claim_port(ps, p); | |
2641 | break; | |
2642 | ||
2643 | case USBDEVFS_RELEASE_PORT: | |
2644 | snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__); | |
2645 | ret = proc_release_port(ps, p); | |
2646 | break; | |
19181bc5 HG |
2647 | case USBDEVFS_GET_CAPABILITIES: |
2648 | ret = proc_get_capabilities(ps, p); | |
2649 | break; | |
0837e7e5 HG |
2650 | case USBDEVFS_DISCONNECT_CLAIM: |
2651 | ret = proc_disconnect_claim(ps, p); | |
2652 | break; | |
bcf7f6e3 HG |
2653 | case USBDEVFS_ALLOC_STREAMS: |
2654 | ret = proc_alloc_streams(ps, p); | |
2655 | break; | |
2656 | case USBDEVFS_FREE_STREAMS: | |
2657 | ret = proc_free_streams(ps, p); | |
2658 | break; | |
d883f52e RG |
2659 | case USBDEVFS_DROP_PRIVILEGES: |
2660 | ret = proc_drop_privileges(ps, p); | |
2661 | break; | |
c01b244a AS |
2662 | case USBDEVFS_GET_SPEED: |
2663 | ret = ps->dev->speed; | |
2664 | break; | |
7794f486 AS |
2665 | case USBDEVFS_FORBID_SUSPEND: |
2666 | ret = proc_forbid_suspend(ps); | |
2667 | break; | |
2668 | case USBDEVFS_ALLOW_SUSPEND: | |
2669 | ret = proc_allow_suspend(ps); | |
2670 | break; | |
2671 | case USBDEVFS_WAIT_FOR_RESUME: | |
2672 | ret = proc_wait_for_resume(ps); | |
2673 | break; | |
1da177e4 | 2674 | } |
3f2cee73 | 2675 | |
6d101f24 DT |
2676 | /* Handle variable-length commands */ |
2677 | switch (cmd & ~IOCSIZE_MASK) { | |
2678 | case USBDEVFS_CONNINFO_EX(0): | |
2679 | ret = proc_conninfo_ex(ps, p, _IOC_SIZE(cmd)); | |
2680 | break; | |
2681 | } | |
2682 | ||
3f2cee73 | 2683 | done: |
1da177e4 LT |
2684 | usb_unlock_device(dev); |
2685 | if (ret >= 0) | |
078cd827 | 2686 | inode->i_atime = current_time(inode); |
1da177e4 LT |
2687 | return ret; |
2688 | } | |
2689 | ||
637e8a60 AB |
2690 | static long usbdev_ioctl(struct file *file, unsigned int cmd, |
2691 | unsigned long arg) | |
2692 | { | |
2693 | int ret; | |
2694 | ||
637e8a60 | 2695 | ret = usbdev_do_ioctl(file, cmd, (void __user *)arg); |
637e8a60 AB |
2696 | |
2697 | return ret; | |
2698 | } | |
2699 | ||
1da177e4 | 2700 | /* No kernel lock - fine */ |
afc9a42b | 2701 | static __poll_t usbdev_poll(struct file *file, |
04e482ff | 2702 | struct poll_table_struct *wait) |
1da177e4 | 2703 | { |
9b6f0c4b | 2704 | struct usb_dev_state *ps = file->private_data; |
afc9a42b | 2705 | __poll_t mask = 0; |
1da177e4 LT |
2706 | |
2707 | poll_wait(file, &ps->wait, wait); | |
2708 | if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) | |
a9a08845 | 2709 | mask |= EPOLLOUT | EPOLLWRNORM; |
349710c3 | 2710 | if (!connected(ps)) |
a9a08845 | 2711 | mask |= EPOLLHUP; |
5cce4382 | 2712 | if (list_empty(&ps->list)) |
a9a08845 | 2713 | mask |= EPOLLERR; |
1da177e4 LT |
2714 | return mask; |
2715 | } | |
2716 | ||
9f8b17e6 | 2717 | const struct file_operations usbdev_file_operations = { |
637e8a60 | 2718 | .owner = THIS_MODULE, |
b25472f9 | 2719 | .llseek = no_seek_end_llseek, |
637e8a60 AB |
2720 | .read = usbdev_read, |
2721 | .poll = usbdev_poll, | |
2722 | .unlocked_ioctl = usbdev_ioctl, | |
407e9ef7 | 2723 | .compat_ioctl = compat_ptr_ioctl, |
f7d34b44 | 2724 | .mmap = usbdev_mmap, |
637e8a60 AB |
2725 | .open = usbdev_open, |
2726 | .release = usbdev_release, | |
1da177e4 | 2727 | }; |
fbf82fd2 | 2728 | |
501950d8 | 2729 | static void usbdev_remove(struct usb_device *udev) |
cd9f0375 | 2730 | { |
9b6f0c4b | 2731 | struct usb_dev_state *ps; |
cd9f0375 | 2732 | |
7794f486 AS |
2733 | /* Protect against simultaneous resume */ |
2734 | mutex_lock(&usbfs_mutex); | |
cd9f0375 | 2735 | while (!list_empty(&udev->filelist)) { |
9b6f0c4b | 2736 | ps = list_entry(udev->filelist.next, struct usb_dev_state, list); |
cd9f0375 AS |
2737 | destroy_all_async(ps); |
2738 | wake_up_all(&ps->wait); | |
7794f486 AS |
2739 | WRITE_ONCE(ps->not_yet_resumed, 0); |
2740 | wake_up_all(&ps->wait_for_resume); | |
cd9f0375 | 2741 | list_del_init(&ps->list); |
70f1b0d3 EB |
2742 | if (ps->discsignr) |
2743 | kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext, | |
2744 | ps->disc_pid, ps->cred); | |
cd9f0375 | 2745 | } |
7794f486 | 2746 | mutex_unlock(&usbfs_mutex); |
cd9f0375 AS |
2747 | } |
2748 | ||
501950d8 | 2749 | static int usbdev_notify(struct notifier_block *self, |
9f8b17e6 | 2750 | unsigned long action, void *dev) |
a7b986b3 GKH |
2751 | { |
2752 | switch (action) { | |
2753 | case USB_DEVICE_ADD: | |
a7b986b3 GKH |
2754 | break; |
2755 | case USB_DEVICE_REMOVE: | |
501950d8 | 2756 | usbdev_remove(dev); |
a7b986b3 GKH |
2757 | break; |
2758 | } | |
2759 | return NOTIFY_OK; | |
2760 | } | |
2761 | ||
2762 | static struct notifier_block usbdev_nb = { | |
00fe52de | 2763 | .notifier_call = usbdev_notify, |
a7b986b3 GKH |
2764 | }; |
2765 | ||
7e7654a9 | 2766 | static struct cdev usb_device_cdev; |
fbf82fd2 | 2767 | |
9f8b17e6 | 2768 | int __init usb_devio_init(void) |
fbf82fd2 KS |
2769 | { |
2770 | int retval; | |
2771 | ||
fad21bdf | 2772 | retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX, |
04e482ff | 2773 | "usb_device"); |
fbf82fd2 | 2774 | if (retval) { |
69a85942 | 2775 | printk(KERN_ERR "Unable to register minors for usb_device\n"); |
fbf82fd2 KS |
2776 | goto out; |
2777 | } | |
9f8b17e6 | 2778 | cdev_init(&usb_device_cdev, &usbdev_file_operations); |
fad21bdf | 2779 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); |
fbf82fd2 | 2780 | if (retval) { |
69a85942 GKH |
2781 | printk(KERN_ERR "Unable to get usb_device major %d\n", |
2782 | USB_DEVICE_MAJOR); | |
a7b986b3 | 2783 | goto error_cdev; |
fbf82fd2 | 2784 | } |
501950d8 | 2785 | usb_register_notify(&usbdev_nb); |
fbf82fd2 KS |
2786 | out: |
2787 | return retval; | |
a7b986b3 | 2788 | |
a7b986b3 GKH |
2789 | error_cdev: |
2790 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | |
2791 | goto out; | |
fbf82fd2 KS |
2792 | } |
2793 | ||
9f8b17e6 | 2794 | void usb_devio_cleanup(void) |
fbf82fd2 | 2795 | { |
a7b986b3 | 2796 | usb_unregister_notify(&usbdev_nb); |
fbf82fd2 | 2797 | cdev_del(&usb_device_cdev); |
fad21bdf | 2798 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
fbf82fd2 | 2799 | } |