]>
Commit | Line | Data |
---|---|---|
4d7b5c7f TH |
1 | /* |
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | |
3 | * | |
4 | * This is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
17 | * USA. | |
18 | */ | |
19 | ||
5a0e3ad6 TH |
20 | #include <linux/slab.h> |
21 | ||
4d7b5c7f TH |
22 | #include "usbip_common.h" |
23 | #include "stub.h" | |
24 | ||
25 | ||
26 | ||
27 | static int stub_probe(struct usb_interface *interface, | |
28 | const struct usb_device_id *id); | |
29 | static void stub_disconnect(struct usb_interface *interface); | |
30 | ||
31 | ||
32 | /* | |
33 | * Define device IDs here if you want to explicitly limit exportable devices. | |
34 | * In the most cases, wild card matching will be ok because driver binding can | |
35 | * be changed dynamically by a userland program. | |
36 | */ | |
37 | static struct usb_device_id stub_table[] = { | |
38 | #if 0 | |
39 | /* just an example */ | |
40 | { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ | |
41 | { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ | |
42 | { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ | |
43 | { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ | |
44 | { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ | |
45 | { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ | |
46 | { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ | |
47 | { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ | |
48 | { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ | |
49 | { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ | |
50 | { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ | |
51 | { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ | |
52 | #endif | |
53 | /* magic for wild card */ | |
54 | { .driver_info = 1 }, | |
55 | { 0, } /* Terminating entry */ | |
56 | }; | |
57 | MODULE_DEVICE_TABLE(usb, stub_table); | |
58 | ||
59 | struct usb_driver stub_driver = { | |
60 | .name = "usbip", | |
61 | .probe = stub_probe, | |
62 | .disconnect = stub_disconnect, | |
63 | .id_table = stub_table, | |
64 | }; | |
65 | ||
66 | ||
67 | /*-------------------------------------------------------------------------*/ | |
68 | ||
69 | /* Define sysfs entries for a usbip-bound device */ | |
70 | ||
71 | ||
72 | /* | |
73 | * usbip_status shows status of usbip as long as this driver is bound to the | |
74 | * target device. | |
75 | */ | |
76 | static ssize_t show_status(struct device *dev, struct device_attribute *attr, | |
77 | char *buf) | |
78 | { | |
79 | struct stub_device *sdev = dev_get_drvdata(dev); | |
80 | int status; | |
81 | ||
82 | if (!sdev) { | |
83 | dev_err(dev, "sdev is null\n"); | |
84 | return -ENODEV; | |
85 | } | |
86 | ||
87 | spin_lock(&sdev->ud.lock); | |
88 | status = sdev->ud.status; | |
89 | spin_unlock(&sdev->ud.lock); | |
90 | ||
91 | return snprintf(buf, PAGE_SIZE, "%d\n", status); | |
92 | } | |
93 | static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); | |
94 | ||
95 | /* | |
96 | * usbip_sockfd gets a socket descriptor of an established TCP connection that | |
97 | * is used to transfer usbip requests by kernel threads. -1 is a magic number | |
98 | * by which usbip connection is finished. | |
99 | */ | |
100 | static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, | |
101 | const char *buf, size_t count) | |
102 | { | |
103 | struct stub_device *sdev = dev_get_drvdata(dev); | |
104 | int sockfd = 0; | |
105 | struct socket *socket; | |
106 | ||
107 | if (!sdev) { | |
108 | dev_err(dev, "sdev is null\n"); | |
109 | return -ENODEV; | |
110 | } | |
111 | ||
112 | sscanf(buf, "%d", &sockfd); | |
113 | ||
114 | if (sockfd != -1) { | |
115 | dev_info(dev, "stub up\n"); | |
116 | ||
117 | spin_lock(&sdev->ud.lock); | |
118 | ||
119 | if (sdev->ud.status != SDEV_ST_AVAILABLE) { | |
120 | dev_err(dev, "not ready\n"); | |
121 | spin_unlock(&sdev->ud.lock); | |
122 | return -EINVAL; | |
123 | } | |
124 | ||
125 | socket = sockfd_to_socket(sockfd); | |
126 | if (!socket) { | |
127 | spin_unlock(&sdev->ud.lock); | |
128 | return -EINVAL; | |
129 | } | |
130 | ||
131 | #if 0 | |
132 | setnodelay(socket); | |
133 | setkeepalive(socket); | |
134 | setreuse(socket); | |
135 | #endif | |
136 | ||
137 | sdev->ud.tcp_socket = socket; | |
138 | ||
139 | spin_unlock(&sdev->ud.lock); | |
140 | ||
141 | usbip_start_threads(&sdev->ud); | |
142 | ||
143 | spin_lock(&sdev->ud.lock); | |
144 | sdev->ud.status = SDEV_ST_USED; | |
145 | spin_unlock(&sdev->ud.lock); | |
146 | ||
147 | } else { | |
148 | dev_info(dev, "stub down\n"); | |
149 | ||
150 | spin_lock(&sdev->ud.lock); | |
151 | if (sdev->ud.status != SDEV_ST_USED) { | |
152 | spin_unlock(&sdev->ud.lock); | |
153 | return -EINVAL; | |
154 | } | |
155 | spin_unlock(&sdev->ud.lock); | |
156 | ||
157 | usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); | |
158 | } | |
159 | ||
160 | return count; | |
161 | } | |
162 | static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); | |
163 | ||
164 | static int stub_add_files(struct device *dev) | |
165 | { | |
166 | int err = 0; | |
167 | ||
168 | err = device_create_file(dev, &dev_attr_usbip_status); | |
169 | if (err) | |
170 | goto err_status; | |
171 | ||
172 | err = device_create_file(dev, &dev_attr_usbip_sockfd); | |
173 | if (err) | |
174 | goto err_sockfd; | |
175 | ||
176 | err = device_create_file(dev, &dev_attr_usbip_debug); | |
177 | if (err) | |
178 | goto err_debug; | |
179 | ||
180 | return 0; | |
181 | ||
182 | err_debug: | |
183 | device_remove_file(dev, &dev_attr_usbip_sockfd); | |
184 | ||
185 | err_sockfd: | |
186 | device_remove_file(dev, &dev_attr_usbip_status); | |
187 | ||
188 | err_status: | |
189 | return err; | |
190 | } | |
191 | ||
192 | static void stub_remove_files(struct device *dev) | |
193 | { | |
194 | device_remove_file(dev, &dev_attr_usbip_status); | |
195 | device_remove_file(dev, &dev_attr_usbip_sockfd); | |
196 | device_remove_file(dev, &dev_attr_usbip_debug); | |
197 | } | |
198 | ||
199 | ||
200 | ||
201 | /*-------------------------------------------------------------------------*/ | |
202 | ||
203 | /* Event handler functions called by an event handler thread */ | |
204 | ||
205 | static void stub_shutdown_connection(struct usbip_device *ud) | |
206 | { | |
207 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | |
208 | ||
209 | /* | |
210 | * When removing an exported device, kernel panic sometimes occurred | |
211 | * and then EIP was sk_wait_data of stub_rx thread. Is this because | |
212 | * sk_wait_data returned though stub_rx thread was already finished by | |
213 | * step 1? | |
214 | */ | |
215 | if (ud->tcp_socket) { | |
b8868e45 | 216 | usbip_udbg("shutdown tcp_socket %p\n", ud->tcp_socket); |
4d7b5c7f TH |
217 | kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); |
218 | } | |
219 | ||
220 | /* 1. stop threads */ | |
221 | usbip_stop_threads(ud); | |
222 | ||
223 | /* 2. close the socket */ | |
224 | /* | |
225 | * tcp_socket is freed after threads are killed. | |
226 | * So usbip_xmit do not touch NULL socket. | |
227 | */ | |
228 | if (ud->tcp_socket) { | |
229 | sock_release(ud->tcp_socket); | |
230 | ud->tcp_socket = NULL; | |
231 | } | |
232 | ||
233 | /* 3. free used data */ | |
234 | stub_device_cleanup_urbs(sdev); | |
235 | ||
236 | /* 4. free stub_unlink */ | |
237 | { | |
238 | unsigned long flags; | |
239 | struct stub_unlink *unlink, *tmp; | |
240 | ||
241 | spin_lock_irqsave(&sdev->priv_lock, flags); | |
242 | ||
243 | list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { | |
244 | list_del(&unlink->list); | |
245 | kfree(unlink); | |
246 | } | |
247 | ||
248 | list_for_each_entry_safe(unlink, tmp, | |
249 | &sdev->unlink_free, list) { | |
250 | list_del(&unlink->list); | |
251 | kfree(unlink); | |
252 | } | |
253 | ||
254 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | |
255 | } | |
256 | } | |
257 | ||
258 | static void stub_device_reset(struct usbip_device *ud) | |
259 | { | |
260 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | |
261 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | |
262 | int ret; | |
263 | ||
b8868e45 | 264 | usbip_udbg("device reset"); |
4d7b5c7f TH |
265 | ret = usb_lock_device_for_reset(udev, sdev->interface); |
266 | if (ret < 0) { | |
267 | dev_err(&udev->dev, "lock for reset\n"); | |
268 | ||
269 | spin_lock(&ud->lock); | |
270 | ud->status = SDEV_ST_ERROR; | |
271 | spin_unlock(&ud->lock); | |
272 | ||
273 | return; | |
274 | } | |
275 | ||
276 | /* try to reset the device */ | |
277 | ret = usb_reset_device(udev); | |
278 | ||
279 | usb_unlock_device(udev); | |
280 | ||
281 | spin_lock(&ud->lock); | |
282 | if (ret) { | |
283 | dev_err(&udev->dev, "device reset\n"); | |
284 | ud->status = SDEV_ST_ERROR; | |
285 | ||
286 | } else { | |
287 | dev_info(&udev->dev, "device reset\n"); | |
288 | ud->status = SDEV_ST_AVAILABLE; | |
289 | ||
290 | } | |
291 | spin_unlock(&ud->lock); | |
292 | ||
293 | return; | |
294 | } | |
295 | ||
296 | static void stub_device_unusable(struct usbip_device *ud) | |
297 | { | |
298 | spin_lock(&ud->lock); | |
299 | ud->status = SDEV_ST_ERROR; | |
300 | spin_unlock(&ud->lock); | |
301 | } | |
302 | ||
303 | ||
304 | /*-------------------------------------------------------------------------*/ | |
305 | ||
306 | /** | |
307 | * stub_device_alloc - allocate a new stub_device struct | |
308 | * @interface: usb_interface of a new device | |
309 | * | |
310 | * Allocates and initializes a new stub_device struct. | |
311 | */ | |
312 | static struct stub_device *stub_device_alloc(struct usb_interface *interface) | |
313 | { | |
314 | struct stub_device *sdev; | |
315 | int busnum = interface_to_busnum(interface); | |
316 | int devnum = interface_to_devnum(interface); | |
317 | ||
318 | dev_dbg(&interface->dev, "allocating stub device"); | |
319 | ||
320 | /* yes, it's a new device */ | |
321 | sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL); | |
322 | if (!sdev) { | |
323 | dev_err(&interface->dev, "no memory for stub_device\n"); | |
324 | return NULL; | |
325 | } | |
326 | ||
327 | sdev->interface = interface; | |
328 | ||
329 | /* | |
330 | * devid is defined with devnum when this driver is first allocated. | |
331 | * devnum may change later if a device is reset. However, devid never | |
332 | * changes during a usbip connection. | |
333 | */ | |
334 | sdev->devid = (busnum << 16) | devnum; | |
335 | ||
336 | usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); | |
337 | usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); | |
338 | ||
339 | sdev->ud.side = USBIP_STUB; | |
340 | sdev->ud.status = SDEV_ST_AVAILABLE; | |
341 | /* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */ | |
342 | spin_lock_init(&sdev->ud.lock); | |
343 | sdev->ud.tcp_socket = NULL; | |
344 | ||
345 | INIT_LIST_HEAD(&sdev->priv_init); | |
346 | INIT_LIST_HEAD(&sdev->priv_tx); | |
347 | INIT_LIST_HEAD(&sdev->priv_free); | |
348 | INIT_LIST_HEAD(&sdev->unlink_free); | |
349 | INIT_LIST_HEAD(&sdev->unlink_tx); | |
350 | /* sdev->priv_lock = SPIN_LOCK_UNLOCKED; */ | |
351 | spin_lock_init(&sdev->priv_lock); | |
352 | ||
353 | init_waitqueue_head(&sdev->tx_waitq); | |
354 | ||
355 | sdev->ud.eh_ops.shutdown = stub_shutdown_connection; | |
356 | sdev->ud.eh_ops.reset = stub_device_reset; | |
357 | sdev->ud.eh_ops.unusable = stub_device_unusable; | |
358 | ||
359 | usbip_start_eh(&sdev->ud); | |
360 | ||
b8868e45 | 361 | usbip_udbg("register new interface\n"); |
4d7b5c7f TH |
362 | return sdev; |
363 | } | |
364 | ||
365 | static int stub_device_free(struct stub_device *sdev) | |
366 | { | |
367 | if (!sdev) | |
368 | return -EINVAL; | |
369 | ||
370 | kfree(sdev); | |
b8868e45 | 371 | usbip_udbg("kfree udev ok\n"); |
4d7b5c7f TH |
372 | |
373 | return 0; | |
374 | } | |
375 | ||
376 | ||
377 | /*-------------------------------------------------------------------------*/ | |
378 | ||
379 | /* | |
380 | * If a usb device has multiple active interfaces, this driver is bound to all | |
381 | * the active interfaces. However, usbip exports *a* usb device (i.e., not *an* | |
382 | * active interface). Currently, a userland program must ensure that it | |
383 | * looks at the usbip's sysfs entries of only the first active interface. | |
384 | * | |
385 | * TODO: use "struct usb_device_driver" to bind a usb device. | |
386 | * However, it seems it is not fully supported in mainline kernel yet | |
387 | * (2.6.19.2). | |
388 | */ | |
389 | static int stub_probe(struct usb_interface *interface, | |
390 | const struct usb_device_id *id) | |
391 | { | |
392 | struct usb_device *udev = interface_to_usbdev(interface); | |
393 | struct stub_device *sdev = NULL; | |
e9133972 | 394 | const char *udev_busid = dev_name(interface->dev.parent); |
4d7b5c7f TH |
395 | int err = 0; |
396 | ||
397 | dev_dbg(&interface->dev, "Enter\n"); | |
398 | ||
399 | /* check we should claim or not by busid_table */ | |
400 | if (match_busid(udev_busid)) { | |
401 | dev_info(&interface->dev, | |
402 | "this device %s is not in match_busid table. skip!\n", | |
403 | udev_busid); | |
404 | ||
405 | /* | |
406 | * Return value should be ENODEV or ENOXIO to continue trying | |
407 | * other matched drivers by the driver core. | |
408 | * See driver_probe_device() in driver/base/dd.c | |
409 | */ | |
410 | return -ENODEV; | |
411 | } | |
412 | ||
413 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { | |
b8868e45 | 414 | usbip_udbg("this device %s is a usb hub device. skip!\n", |
4d7b5c7f TH |
415 | udev_busid); |
416 | return -ENODEV; | |
417 | } | |
418 | ||
419 | if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { | |
b8868e45 | 420 | usbip_udbg("this device %s is attached on vhci_hcd. skip!\n", |
4d7b5c7f TH |
421 | udev_busid); |
422 | return -ENODEV; | |
423 | } | |
424 | ||
425 | /* ok. this is my device. */ | |
426 | sdev = stub_device_alloc(interface); | |
427 | if (!sdev) | |
428 | return -ENOMEM; | |
429 | ||
430 | dev_info(&interface->dev, "USB/IP Stub: register a new interface " | |
431 | "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum, | |
432 | interface->cur_altsetting->desc.bInterfaceNumber); | |
433 | ||
434 | /* set private data to usb_interface */ | |
435 | usb_set_intfdata(interface, sdev); | |
436 | ||
437 | err = stub_add_files(&interface->dev); | |
438 | if (err) { | |
439 | dev_err(&interface->dev, "create sysfs files for %s\n", | |
440 | udev_busid); | |
441 | return err; | |
442 | } | |
443 | ||
444 | return 0; | |
445 | } | |
446 | ||
447 | ||
448 | /* | |
449 | * called in usb_disconnect() or usb_deregister() | |
450 | * but only if actconfig(active configuration) exists | |
451 | */ | |
452 | static void stub_disconnect(struct usb_interface *interface) | |
453 | { | |
454 | struct stub_device *sdev = usb_get_intfdata(interface); | |
455 | ||
b8868e45 | 456 | usbip_udbg("Enter\n"); |
4d7b5c7f TH |
457 | |
458 | /* get stub_device */ | |
459 | if (!sdev) { | |
460 | err(" could not get device from inteface data"); | |
461 | /* BUG(); */ | |
462 | return; | |
463 | } | |
464 | ||
465 | usb_set_intfdata(interface, NULL); | |
466 | ||
467 | ||
468 | /* | |
469 | * NOTE: | |
470 | * rx/tx threads are invoked for each usb_device. | |
471 | */ | |
472 | stub_remove_files(&interface->dev); | |
473 | ||
474 | /* 1. shutdown the current connection */ | |
475 | usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); | |
476 | ||
477 | /* 2. wait for the stop of the event handler */ | |
478 | usbip_stop_eh(&sdev->ud); | |
479 | ||
480 | /* 3. free sdev */ | |
481 | stub_device_free(sdev); | |
482 | ||
483 | ||
b8868e45 | 484 | usbip_udbg("bye\n"); |
4d7b5c7f | 485 | } |