2 * Copyright (C) 2003-2008 Takahiro Hirofuchi
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.
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.
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,
20 #include <linux/slab.h>
22 #include "usbip_common.h"
25 /* Version Information */
26 #define DRIVER_VERSION "1.0"
27 #define DRIVER_AUTHOR "Takahiro Hirofuchi"
28 #define DRIVER_DESC "Stub Driver for USB/IP"
30 /* stub_priv is allocated from stub_priv_cache */
31 struct kmem_cache *stub_priv_cache;
34 * busid_tables defines matching busids that usbip can grab. A user can change
35 * dynamically what device is locally used and what device is exported to a
39 static struct bus_id_priv busid_table[MAX_BUSID];
40 static spinlock_t busid_table_lock;
42 int match_busid(const char *busid)
46 spin_lock(&busid_table_lock);
48 for (i = 0; i < MAX_BUSID; i++)
49 if (busid_table[i].name[0])
50 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
51 /* already registerd */
52 spin_unlock(&busid_table_lock);
56 spin_unlock(&busid_table_lock);
61 struct bus_id_priv *get_busid_priv(const char *busid)
65 spin_lock(&busid_table_lock);
67 for (i = 0; i < MAX_BUSID; i++)
68 if (busid_table[i].name[0])
69 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
70 /* already registerd */
71 spin_unlock(&busid_table_lock);
72 return &(busid_table[i]);
75 spin_unlock(&busid_table_lock);
80 static ssize_t show_match_busid(struct device_driver *drv, char *buf)
85 spin_lock(&busid_table_lock);
87 for (i = 0; i < MAX_BUSID; i++)
88 if (busid_table[i].name[0])
89 out += sprintf(out, "%s ", busid_table[i].name);
91 spin_unlock(&busid_table_lock);
93 out += sprintf(out, "\n");
98 static int add_match_busid(char *busid)
102 if (!match_busid(busid))
105 spin_lock(&busid_table_lock);
107 for (i = 0; i < MAX_BUSID; i++)
108 if (!busid_table[i].name[0]) {
109 strncpy(busid_table[i].name, busid, BUSID_SIZE);
110 if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
111 (busid_table[i].status != STUB_BUSID_REMOV))
112 busid_table[i].status = STUB_BUSID_ADDED;
113 spin_unlock(&busid_table_lock);
117 spin_unlock(&busid_table_lock);
122 int del_match_busid(char *busid)
126 spin_lock(&busid_table_lock);
128 for (i = 0; i < MAX_BUSID; i++)
129 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
131 if (busid_table[i].status == STUB_BUSID_OTHER)
132 memset(busid_table[i].name, 0, BUSID_SIZE);
133 if ((busid_table[i].status != STUB_BUSID_OTHER) &&
134 (busid_table[i].status != STUB_BUSID_ADDED)) {
135 busid_table[i].status = STUB_BUSID_REMOV;
137 spin_unlock(&busid_table_lock);
141 spin_unlock(&busid_table_lock);
146 static void init_busid_table(void)
150 for (i = 0; i < MAX_BUSID; i++) {
151 memset(busid_table[i].name, 0, BUSID_SIZE);
152 busid_table[i].status = STUB_BUSID_OTHER;
153 busid_table[i].interf_count = 0;
154 busid_table[i].sdev = NULL;
155 busid_table[i].shutdown_busid = 0;
158 spin_lock_init(&busid_table_lock);
161 static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
165 char busid[BUSID_SIZE];
170 /* strnlen() does not include \0 */
171 len = strnlen(buf + 4, BUSID_SIZE);
173 /* busid needs to include \0 termination */
174 if (!(len < BUSID_SIZE))
177 strncpy(busid, buf + 4, BUSID_SIZE);
179 if (!strncmp(buf, "add ", 4)) {
180 if (add_match_busid(busid) < 0)
183 usbip_udbg("add busid %s\n", busid);
186 } else if (!strncmp(buf, "del ", 4)) {
187 if (del_match_busid(busid) < 0)
190 usbip_udbg("del busid %s\n", busid);
196 static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid,
199 static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
201 struct stub_priv *priv, *tmp;
203 list_for_each_entry_safe(priv, tmp, listhead, list) {
204 list_del(&priv->list);
211 static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
214 struct stub_priv *priv;
216 spin_lock_irqsave(&sdev->priv_lock, flags);
218 priv = stub_priv_pop_from_listhead(&sdev->priv_init);
220 spin_unlock_irqrestore(&sdev->priv_lock, flags);
224 priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
226 spin_unlock_irqrestore(&sdev->priv_lock, flags);
230 priv = stub_priv_pop_from_listhead(&sdev->priv_free);
232 spin_unlock_irqrestore(&sdev->priv_lock, flags);
236 spin_unlock_irqrestore(&sdev->priv_lock, flags);
240 void stub_device_cleanup_urbs(struct stub_device *sdev)
242 struct stub_priv *priv;
244 usbip_udbg("free sdev %p\n", sdev);
246 while ((priv = stub_priv_pop(sdev))) {
247 struct urb *urb = priv->urb;
249 usbip_udbg(" free urb %p\n", urb);
252 kmem_cache_free(stub_priv_cache, priv);
254 kfree(urb->transfer_buffer);
255 kfree(urb->setup_packet);
261 static int __init usb_stub_init(void)
265 stub_priv_cache = kmem_cache_create("stub_priv",
266 sizeof(struct stub_priv), 0,
267 SLAB_HWCACHE_ALIGN, NULL);
269 if (!stub_priv_cache) {
270 printk(KERN_ERR KBUILD_MODNAME
271 ": create stub_priv_cache error\n");
275 ret = usb_register(&stub_driver);
277 printk(KERN_ERR KBUILD_MODNAME ": usb_register failed %d\n",
279 goto error_usb_register;
282 printk(KERN_INFO KBUILD_MODNAME ":" DRIVER_DESC ":" DRIVER_VERSION
287 ret = driver_create_file(&stub_driver.drvwrap.driver,
288 &driver_attr_match_busid);
291 printk(KERN_ERR KBUILD_MODNAME ": create driver sysfs\n");
292 goto error_create_file;
297 usb_deregister(&stub_driver);
299 kmem_cache_destroy(stub_priv_cache);
303 static void __exit usb_stub_exit(void)
305 driver_remove_file(&stub_driver.drvwrap.driver,
306 &driver_attr_match_busid);
309 * deregister() calls stub_disconnect() for all devices. Device
310 * specific data is cleared in stub_disconnect().
312 usb_deregister(&stub_driver);
314 kmem_cache_destroy(stub_priv_cache);
317 module_init(usb_stub_init);
318 module_exit(usb_stub_exit);
320 MODULE_AUTHOR(DRIVER_AUTHOR);
321 MODULE_DESCRIPTION(DRIVER_DESC);
322 MODULE_LICENSE("GPL");