1/*
2 * The USB Monitor, inspired by Dave Harding's USBMon.
3 *
4 * mon_main.c: Main file, module initiation and exit, registrations, etc.
5 *
6 * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/usb.h>
12#include <linux/notifier.h>
13#include <linux/mutex.h>
14
15#include "usb_mon.h"
16#include "../core/hcd.h"
17
18static void mon_stop(struct mon_bus *mbus);
19static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
20static void mon_bus_drop(struct kref *r);
21static void mon_bus_init(struct usb_bus *ubus);
22
23DEFINE_MUTEX(mon_lock);
24
25struct mon_bus mon_bus0;		/* Pseudo bus meaning "all buses" */
26static LIST_HEAD(mon_buses);		/* All buses we know: struct mon_bus */
27
28/*
29 * Link a reader into the bus.
30 *
31 * This must be called with mon_lock taken because of mbus->ref.
32 */
33void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
34{
35	unsigned long flags;
36	struct list_head *p;
37
38	spin_lock_irqsave(&mbus->lock, flags);
39	if (mbus->nreaders == 0) {
40		if (mbus == &mon_bus0) {
41			list_for_each (p, &mon_buses) {
42				struct mon_bus *m1;
43				m1 = list_entry(p, struct mon_bus, bus_link);
44				m1->u_bus->monitored = 1;
45			}
46		} else {
47			mbus->u_bus->monitored = 1;
48		}
49	}
50	mbus->nreaders++;
51	list_add_tail(&r->r_link, &mbus->r_list);
52	spin_unlock_irqrestore(&mbus->lock, flags);
53
54	kref_get(&mbus->ref);
55}
56
57/*
58 * Unlink reader from the bus.
59 *
60 * This is called with mon_lock taken, so we can decrement mbus->ref.
61 */
62void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
63{
64	unsigned long flags;
65
66	spin_lock_irqsave(&mbus->lock, flags);
67	list_del(&r->r_link);
68	--mbus->nreaders;
69	if (mbus->nreaders == 0)
70		mon_stop(mbus);
71	spin_unlock_irqrestore(&mbus->lock, flags);
72
73	kref_put(&mbus->ref, mon_bus_drop);
74}
75
76/*
77 */
78static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb)
79{
80	unsigned long flags;
81	struct list_head *pos;
82	struct mon_reader *r;
83
84	spin_lock_irqsave(&mbus->lock, flags);
85	mbus->cnt_events++;
86	list_for_each (pos, &mbus->r_list) {
87		r = list_entry(pos, struct mon_reader, r_link);
88		r->rnf_submit(r->r_data, urb);
89	}
90	spin_unlock_irqrestore(&mbus->lock, flags);
91	return;
92}
93
94static void mon_submit(struct usb_bus *ubus, struct urb *urb)
95{
96	struct mon_bus *mbus;
97
98	if ((mbus = ubus->mon_bus) != NULL)
99		mon_bus_submit(mbus, urb);
100	mon_bus_submit(&mon_bus0, urb);
101}
102
103/*
104 */
105static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error)
106{
107	unsigned long flags;
108	struct list_head *pos;
109	struct mon_reader *r;
110
111	spin_lock_irqsave(&mbus->lock, flags);
112	mbus->cnt_events++;
113	list_for_each (pos, &mbus->r_list) {
114		r = list_entry(pos, struct mon_reader, r_link);
115		r->rnf_error(r->r_data, urb, error);
116	}
117	spin_unlock_irqrestore(&mbus->lock, flags);
118	return;
119}
120
121static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
122{
123	struct mon_bus *mbus;
124
125	if ((mbus = ubus->mon_bus) != NULL)
126		mon_bus_submit_error(mbus, urb, error);
127	mon_bus_submit_error(&mon_bus0, urb, error);
128}
129
130/*
131 */
132static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb)
133{
134	unsigned long flags;
135	struct list_head *pos;
136	struct mon_reader *r;
137
138	spin_lock_irqsave(&mbus->lock, flags);
139	mbus->cnt_events++;
140	list_for_each (pos, &mbus->r_list) {
141		r = list_entry(pos, struct mon_reader, r_link);
142		r->rnf_complete(r->r_data, urb);
143	}
144	spin_unlock_irqrestore(&mbus->lock, flags);
145}
146
147static void mon_complete(struct usb_bus *ubus, struct urb *urb)
148{
149	struct mon_bus *mbus;
150
151	mbus = ubus->mon_bus;
152	if (mbus == NULL) {
153		/*
154		 * This should not happen.
155		 * At this point we do not even know the bus number...
156		 */
157		printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
158		    urb->pipe);
159		return;
160	}
161
162	mon_bus_complete(mbus, urb);
163	mon_bus_complete(&mon_bus0, urb);
164}
165
166/* int (*unlink_urb) (struct urb *urb, int status); */
167
168/*
169 * Stop monitoring.
170 */
171static void mon_stop(struct mon_bus *mbus)
172{
173	struct usb_bus *ubus = mbus->u_bus;
174	struct list_head *p;
175
176	if (mbus == &mon_bus0) {
177		list_for_each (p, &mon_buses) {
178			mbus = list_entry(p, struct mon_bus, bus_link);
179			/*
180			 * We do not change nreaders here, so rely on mon_lock.
181			 */
182			if (mbus->nreaders == 0 && (ubus = mbus->u_bus) != NULL)
183				ubus->monitored = 0;
184		}
185	} else {
186		/*
187		 * A stop can be called for a dissolved mon_bus in case of
188		 * a reader staying across an rmmod foo_hcd, so test ->u_bus.
189		 */
190		if (mon_bus0.nreaders == 0 && (ubus = mbus->u_bus) != NULL) {
191			ubus->monitored = 0;
192			mb();
193		}
194	}
195}
196
197/*
198 * Add a USB bus (usually by a modprobe foo-hcd)
199 *
200 * This does not return an error code because the core cannot care less
201 * if monitoring is not established.
202 */
203static void mon_bus_add(struct usb_bus *ubus)
204{
205	mon_bus_init(ubus);
206	mutex_lock(&mon_lock);
207	if (mon_bus0.nreaders != 0)
208		ubus->monitored = 1;
209	mutex_unlock(&mon_lock);
210}
211
212/*
213 * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
214 */
215static void mon_bus_remove(struct usb_bus *ubus)
216{
217	struct mon_bus *mbus = ubus->mon_bus;
218
219	mutex_lock(&mon_lock);
220	list_del(&mbus->bus_link);
221	if (mbus->text_inited)
222		mon_text_del(mbus);
223
224	mon_dissolve(mbus, ubus);
225	kref_put(&mbus->ref, mon_bus_drop);
226	mutex_unlock(&mon_lock);
227}
228
229static int mon_notify(struct notifier_block *self, unsigned long action,
230		      void *dev)
231{
232	switch (action) {
233	case USB_BUS_ADD:
234		mon_bus_add(dev);
235		break;
236	case USB_BUS_REMOVE:
237		mon_bus_remove(dev);
238	}
239	return NOTIFY_OK;
240}
241
242static struct notifier_block mon_nb = {
243	.notifier_call = 	mon_notify,
244};
245
246/*
247 * Ops
248 */
249static struct usb_mon_operations mon_ops_0 = {
250	.urb_submit =	mon_submit,
251	.urb_submit_error = mon_submit_error,
252	.urb_complete =	mon_complete,
253};
254
255/*
256 * Tear usb_bus and mon_bus apart.
257 */
258static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
259{
260
261	if (ubus->monitored) {
262		ubus->monitored = 0;
263		mb();
264	}
265
266	ubus->mon_bus = NULL;
267	mbus->u_bus = NULL;
268	mb();
269
270	/* We want synchronize_irq() here, but that needs an argument. */
271}
272
273/*
274 */
275static void mon_bus_drop(struct kref *r)
276{
277	struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
278	kfree(mbus);
279}
280
281/*
282 * Initialize a bus for us:
283 *  - allocate mon_bus
284 *  - refcount USB bus struct
285 *  - link
286 */
287static void mon_bus_init(struct usb_bus *ubus)
288{
289	struct mon_bus *mbus;
290
291	if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
292		goto err_alloc;
293	kref_init(&mbus->ref);
294	spin_lock_init(&mbus->lock);
295	INIT_LIST_HEAD(&mbus->r_list);
296
297	/*
298	 * We don't need to take a reference to ubus, because we receive
299	 * a notification if the bus is about to be removed.
300	 */
301	mbus->u_bus = ubus;
302	ubus->mon_bus = mbus;
303
304	mbus->text_inited = mon_text_add(mbus, ubus->busnum);
305	// mon_bin_add(...)
306
307	mutex_lock(&mon_lock);
308	list_add_tail(&mbus->bus_link, &mon_buses);
309	mutex_unlock(&mon_lock);
310	return;
311
312err_alloc:
313	return;
314}
315
316static void mon_bus0_init(void)
317{
318	struct mon_bus *mbus = &mon_bus0;
319
320	kref_init(&mbus->ref);
321	spin_lock_init(&mbus->lock);
322	INIT_LIST_HEAD(&mbus->r_list);
323
324	mbus->text_inited = mon_text_add(mbus, 0);
325	// mbus->bin_inited = mon_bin_add(mbus, 0);
326}
327
328/*
329 * Search a USB bus by number. Notice that USB bus numbers start from one,
330 * which we may later use to identify "all" with zero.
331 *
332 * This function must be called with mon_lock held.
333 *
334 * This is obviously inefficient and may be revised in the future.
335 */
336struct mon_bus *mon_bus_lookup(unsigned int num)
337{
338	struct list_head *p;
339	struct mon_bus *mbus;
340
341	if (num == 0) {
342		return &mon_bus0;
343	}
344	list_for_each (p, &mon_buses) {
345		mbus = list_entry(p, struct mon_bus, bus_link);
346		if (mbus->u_bus->busnum == num) {
347			return mbus;
348		}
349	}
350	return NULL;
351}
352
353static int __init mon_init(void)
354{
355	struct usb_bus *ubus;
356	int rc;
357
358	if ((rc = mon_text_init()) != 0)
359		goto err_text;
360	if ((rc = mon_bin_init()) != 0)
361		goto err_bin;
362
363	mon_bus0_init();
364
365	if (usb_mon_register(&mon_ops_0) != 0) {
366		printk(KERN_NOTICE TAG ": unable to register with the core\n");
367		rc = -ENODEV;
368		goto err_reg;
369	}
370	// MOD_INC_USE_COUNT(which_module?);
371
372	usb_register_notify(&mon_nb);
373
374	mutex_lock(&usb_bus_list_lock);
375	list_for_each_entry (ubus, &usb_bus_list, bus_list) {
376		mon_bus_init(ubus);
377	}
378	mutex_unlock(&usb_bus_list_lock);
379	return 0;
380
381err_reg:
382	mon_bin_exit();
383err_bin:
384	mon_text_exit();
385err_text:
386	return rc;
387}
388
389static void __exit mon_exit(void)
390{
391	struct mon_bus *mbus;
392	struct list_head *p;
393
394	usb_unregister_notify(&mon_nb);
395	usb_mon_deregister();
396
397	mutex_lock(&mon_lock);
398
399	while (!list_empty(&mon_buses)) {
400		p = mon_buses.next;
401		mbus = list_entry(p, struct mon_bus, bus_link);
402		list_del(p);
403
404		if (mbus->text_inited)
405			mon_text_del(mbus);
406
407		/*
408		 * This never happens, because the open/close paths in
409		 * file level maintain module use counters and so rmmod fails
410		 * before reaching here. However, better be safe...
411		 */
412		if (mbus->nreaders) {
413			printk(KERN_ERR TAG
414			    ": Outstanding opens (%d) on usb%d, leaking...\n",
415			    mbus->nreaders, mbus->u_bus->busnum);
416			atomic_set(&mbus->ref.refcount, 2);	/* Force leak */
417		}
418
419		mon_dissolve(mbus, mbus->u_bus);
420		kref_put(&mbus->ref, mon_bus_drop);
421	}
422
423	mbus = &mon_bus0;
424	if (mbus->text_inited)
425		mon_text_del(mbus);
426
427	mutex_unlock(&mon_lock);
428
429	mon_text_exit();
430	mon_bin_exit();
431}
432
433module_init(mon_init);
434module_exit(mon_exit);
435
436MODULE_LICENSE("GPL");
437