aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon/mon_main.c
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2006-12-31 01:43:10 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:44:34 -0500
commit6f23ee1fefdc1f80bd8a3ab04a1c41ab2dec14c9 (patch)
tree36a5241c29333580de3e3c75e2c62edc1cdf583c /drivers/usb/mon/mon_main.c
parenta8ef36bc0a5fe973bddaa54a5a07cda29e04a602 (diff)
USB: add binary API to usbmon
This patch adds a new, "binary" API in addition to the old, text API usbmon had before. The new API allows for less CPU use, and it allows to capture all data from a packet where old API only captured 32 bytes at most. There are some limitations and conditions to this, e.g. in case someone constructs a URB with 1GB of data, it's not likely to be captured, because even the huge buffers of the new reader are finite. Nonetheless, I expect this new capability to capture all data for all real life scenarios. The downside is, a special user mode application is required where cat(1) worked before. I have sample code at http://people.redhat.com/zaitcev/linux/ and Paolo Abeni is working on patching libpcap. This patch was initially written by Paolo and later I tweaked it, and we had a little back-and-forth. So this is a jointly authored patch, but I am submitting this I am responsible for the bugs. Signed-off-by: Paolo Abeni <paolo.abeni@email.it> Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon/mon_main.c')
-rw-r--r--drivers/usb/mon/mon_main.c97
1 files changed, 48 insertions, 49 deletions
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 394bbf2f68d4..c9739e7b35e5 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -9,7 +9,6 @@
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/usb.h> 11#include <linux/usb.h>
12#include <linux/debugfs.h>
13#include <linux/smp_lock.h> 12#include <linux/smp_lock.h>
14#include <linux/notifier.h> 13#include <linux/notifier.h>
15#include <linux/mutex.h> 14#include <linux/mutex.h>
@@ -22,11 +21,10 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb);
22static void mon_stop(struct mon_bus *mbus); 21static void mon_stop(struct mon_bus *mbus);
23static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); 22static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
24static void mon_bus_drop(struct kref *r); 23static void mon_bus_drop(struct kref *r);
25static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); 24static void mon_bus_init(struct usb_bus *ubus);
26 25
27DEFINE_MUTEX(mon_lock); 26DEFINE_MUTEX(mon_lock);
28 27
29static struct dentry *mon_dir; /* /dbg/usbmon */
30static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ 28static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */
31 29
32/* 30/*
@@ -200,7 +198,7 @@ static void mon_stop(struct mon_bus *mbus)
200 */ 198 */
201static void mon_bus_add(struct usb_bus *ubus) 199static void mon_bus_add(struct usb_bus *ubus)
202{ 200{
203 mon_bus_init(mon_dir, ubus); 201 mon_bus_init(ubus);
204} 202}
205 203
206/* 204/*
@@ -212,8 +210,8 @@ static void mon_bus_remove(struct usb_bus *ubus)
212 210
213 mutex_lock(&mon_lock); 211 mutex_lock(&mon_lock);
214 list_del(&mbus->bus_link); 212 list_del(&mbus->bus_link);
215 debugfs_remove(mbus->dent_t); 213 if (mbus->text_inited)
216 debugfs_remove(mbus->dent_s); 214 mon_text_del(mbus);
217 215
218 mon_dissolve(mbus, ubus); 216 mon_dissolve(mbus, ubus);
219 kref_put(&mbus->ref, mon_bus_drop); 217 kref_put(&mbus->ref, mon_bus_drop);
@@ -281,13 +279,9 @@ static void mon_bus_drop(struct kref *r)
281 * - refcount USB bus struct 279 * - refcount USB bus struct
282 * - link 280 * - link
283 */ 281 */
284static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) 282static void mon_bus_init(struct usb_bus *ubus)
285{ 283{
286 struct dentry *d;
287 struct mon_bus *mbus; 284 struct mon_bus *mbus;
288 enum { NAMESZ = 10 };
289 char name[NAMESZ];
290 int rc;
291 285
292 if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) 286 if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
293 goto err_alloc; 287 goto err_alloc;
@@ -303,57 +297,54 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
303 ubus->mon_bus = mbus; 297 ubus->mon_bus = mbus;
304 mbus->uses_dma = ubus->uses_dma; 298 mbus->uses_dma = ubus->uses_dma;
305 299
306 rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); 300 mbus->text_inited = mon_text_add(mbus, ubus);
307 if (rc <= 0 || rc >= NAMESZ) 301 // mon_bin_add(...)
308 goto err_print_t;
309 d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
310 if (d == NULL)
311 goto err_create_t;
312 mbus->dent_t = d;
313
314 rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
315 if (rc <= 0 || rc >= NAMESZ)
316 goto err_print_s;
317 d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
318 if (d == NULL)
319 goto err_create_s;
320 mbus->dent_s = d;
321 302
322 mutex_lock(&mon_lock); 303 mutex_lock(&mon_lock);
323 list_add_tail(&mbus->bus_link, &mon_buses); 304 list_add_tail(&mbus->bus_link, &mon_buses);
324 mutex_unlock(&mon_lock); 305 mutex_unlock(&mon_lock);
325 return; 306 return;
326 307
327err_create_s:
328err_print_s:
329 debugfs_remove(mbus->dent_t);
330err_create_t:
331err_print_t:
332 kfree(mbus);
333err_alloc: 308err_alloc:
334 return; 309 return;
335} 310}
336 311
312/*
313 * Search a USB bus by number. Notice that USB bus numbers start from one,
314 * which we may later use to identify "all" with zero.
315 *
316 * This function must be called with mon_lock held.
317 *
318 * This is obviously inefficient and may be revised in the future.
319 */
320struct mon_bus *mon_bus_lookup(unsigned int num)
321{
322 struct list_head *p;
323 struct mon_bus *mbus;
324
325 list_for_each (p, &mon_buses) {
326 mbus = list_entry(p, struct mon_bus, bus_link);
327 if (mbus->u_bus->busnum == num) {
328 return mbus;
329 }
330 }
331 return NULL;
332}
333
337static int __init mon_init(void) 334static int __init mon_init(void)
338{ 335{
339 struct usb_bus *ubus; 336 struct usb_bus *ubus;
340 struct dentry *mondir; 337 int rc;
341 338
342 mondir = debugfs_create_dir("usbmon", NULL); 339 if ((rc = mon_text_init()) != 0)
343 if (IS_ERR(mondir)) { 340 goto err_text;
344 printk(KERN_NOTICE TAG ": debugfs is not available\n"); 341 if ((rc = mon_bin_init()) != 0)
345 return -ENODEV; 342 goto err_bin;
346 }
347 if (mondir == NULL) {
348 printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
349 return -ENODEV;
350 }
351 mon_dir = mondir;
352 343
353 if (usb_mon_register(&mon_ops_0) != 0) { 344 if (usb_mon_register(&mon_ops_0) != 0) {
354 printk(KERN_NOTICE TAG ": unable to register with the core\n"); 345 printk(KERN_NOTICE TAG ": unable to register with the core\n");
355 debugfs_remove(mondir); 346 rc = -ENODEV;
356 return -ENODEV; 347 goto err_reg;
357 } 348 }
358 // MOD_INC_USE_COUNT(which_module?); 349 // MOD_INC_USE_COUNT(which_module?);
359 350
@@ -361,10 +352,17 @@ static int __init mon_init(void)
361 352
362 mutex_lock(&usb_bus_list_lock); 353 mutex_lock(&usb_bus_list_lock);
363 list_for_each_entry (ubus, &usb_bus_list, bus_list) { 354 list_for_each_entry (ubus, &usb_bus_list, bus_list) {
364 mon_bus_init(mondir, ubus); 355 mon_bus_init(ubus);
365 } 356 }
366 mutex_unlock(&usb_bus_list_lock); 357 mutex_unlock(&usb_bus_list_lock);
367 return 0; 358 return 0;
359
360err_reg:
361 mon_bin_exit();
362err_bin:
363 mon_text_exit();
364err_text:
365 return rc;
368} 366}
369 367
370static void __exit mon_exit(void) 368static void __exit mon_exit(void)
@@ -381,8 +379,8 @@ static void __exit mon_exit(void)
381 mbus = list_entry(p, struct mon_bus, bus_link); 379 mbus = list_entry(p, struct mon_bus, bus_link);
382 list_del(p); 380 list_del(p);
383 381
384 debugfs_remove(mbus->dent_t); 382 if (mbus->text_inited)
385 debugfs_remove(mbus->dent_s); 383 mon_text_del(mbus);
386 384
387 /* 385 /*
388 * This never happens, because the open/close paths in 386 * This never happens, because the open/close paths in
@@ -401,7 +399,8 @@ static void __exit mon_exit(void)
401 } 399 }
402 mutex_unlock(&mon_lock); 400 mutex_unlock(&mon_lock);
403 401
404 debugfs_remove(mon_dir); 402 mon_text_exit();
403 mon_bin_exit();
405} 404}
406 405
407module_init(mon_init); 406module_init(mon_init);