1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * adutux - driver for ADU devices from Ontrak Control Systems
4*4882a593Smuzhiyun * This is an experimental driver. Use at your own risk.
5*4882a593Smuzhiyun * This driver is not supported by Ontrak Control Systems.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2003 John Homppi (SCO, leave this notice here)
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * derived from the Lego USB Tower driver 0.56:
10*4882a593Smuzhiyun * Copyright (c) 2003 David Glance <davidgsf@sourceforge.net>
11*4882a593Smuzhiyun * 2001 Juergen Stuber <stuber@loria.fr>
12*4882a593Smuzhiyun * that was derived from USB Skeleton driver - 0.5
13*4882a593Smuzhiyun * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <linux/kernel.h>
20*4882a593Smuzhiyun #include <linux/sched/signal.h>
21*4882a593Smuzhiyun #include <linux/errno.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/module.h>
24*4882a593Smuzhiyun #include <linux/usb.h>
25*4882a593Smuzhiyun #include <linux/mutex.h>
26*4882a593Smuzhiyun #include <linux/uaccess.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define DRIVER_AUTHOR "John Homppi"
29*4882a593Smuzhiyun #define DRIVER_DESC "adutux (see www.ontrak.net)"
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* Define these values to match your device */
32*4882a593Smuzhiyun #define ADU_VENDOR_ID 0x0a07
33*4882a593Smuzhiyun #define ADU_PRODUCT_ID 0x0064
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* table of devices that work with this driver */
36*4882a593Smuzhiyun static const struct usb_device_id device_table[] = {
37*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) }, /* ADU100 */
38*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */
39*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */
40*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) }, /* ADU200 */
41*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) }, /* ADU208 */
42*4882a593Smuzhiyun { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) }, /* ADU218 */
43*4882a593Smuzhiyun { } /* Terminating entry */
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, device_table);
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #ifdef CONFIG_USB_DYNAMIC_MINORS
49*4882a593Smuzhiyun #define ADU_MINOR_BASE 0
50*4882a593Smuzhiyun #else
51*4882a593Smuzhiyun #define ADU_MINOR_BASE 67
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* we can have up to this number of device plugged in at once */
55*4882a593Smuzhiyun #define MAX_DEVICES 16
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #define COMMAND_TIMEOUT (2*HZ)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun * The locking scheme is a vanilla 3-lock:
61*4882a593Smuzhiyun * adu_device.buflock: A spinlock, covers what IRQs touch.
62*4882a593Smuzhiyun * adutux_mutex: A Static lock to cover open_count. It would also cover
63*4882a593Smuzhiyun * any globals, but we don't have them in 2.6.
64*4882a593Smuzhiyun * adu_device.mtx: A mutex to hold across sleepers like copy_from_user.
65*4882a593Smuzhiyun * It covers all of adu_device, except the open_count
66*4882a593Smuzhiyun * and what .buflock covers.
67*4882a593Smuzhiyun */
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* Structure to hold all of our device specific stuff */
70*4882a593Smuzhiyun struct adu_device {
71*4882a593Smuzhiyun struct mutex mtx;
72*4882a593Smuzhiyun struct usb_device *udev; /* save off the usb device pointer */
73*4882a593Smuzhiyun struct usb_interface *interface;
74*4882a593Smuzhiyun unsigned int minor; /* the starting minor number for this device */
75*4882a593Smuzhiyun char serial_number[8];
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun int open_count; /* number of times this port has been opened */
78*4882a593Smuzhiyun unsigned long disconnected:1;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun char *read_buffer_primary;
81*4882a593Smuzhiyun int read_buffer_length;
82*4882a593Smuzhiyun char *read_buffer_secondary;
83*4882a593Smuzhiyun int secondary_head;
84*4882a593Smuzhiyun int secondary_tail;
85*4882a593Smuzhiyun spinlock_t buflock;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun wait_queue_head_t read_wait;
88*4882a593Smuzhiyun wait_queue_head_t write_wait;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun char *interrupt_in_buffer;
91*4882a593Smuzhiyun struct usb_endpoint_descriptor *interrupt_in_endpoint;
92*4882a593Smuzhiyun struct urb *interrupt_in_urb;
93*4882a593Smuzhiyun int read_urb_finished;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun char *interrupt_out_buffer;
96*4882a593Smuzhiyun struct usb_endpoint_descriptor *interrupt_out_endpoint;
97*4882a593Smuzhiyun struct urb *interrupt_out_urb;
98*4882a593Smuzhiyun int out_urb_finished;
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun static DEFINE_MUTEX(adutux_mutex);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun static struct usb_driver adu_driver;
104*4882a593Smuzhiyun
adu_debug_data(struct device * dev,const char * function,int size,const unsigned char * data)105*4882a593Smuzhiyun static inline void adu_debug_data(struct device *dev, const char *function,
106*4882a593Smuzhiyun int size, const unsigned char *data)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun dev_dbg(dev, "%s - length = %d, data = %*ph\n",
109*4882a593Smuzhiyun function, size, size, data);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /*
113*4882a593Smuzhiyun * adu_abort_transfers
114*4882a593Smuzhiyun * aborts transfers and frees associated data structures
115*4882a593Smuzhiyun */
adu_abort_transfers(struct adu_device * dev)116*4882a593Smuzhiyun static void adu_abort_transfers(struct adu_device *dev)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun unsigned long flags;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (dev->disconnected)
121*4882a593Smuzhiyun return;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* shutdown transfer */
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /* XXX Anchor these instead */
126*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
127*4882a593Smuzhiyun if (!dev->read_urb_finished) {
128*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
129*4882a593Smuzhiyun usb_kill_urb(dev->interrupt_in_urb);
130*4882a593Smuzhiyun } else
131*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
134*4882a593Smuzhiyun if (!dev->out_urb_finished) {
135*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
136*4882a593Smuzhiyun wait_event_timeout(dev->write_wait, dev->out_urb_finished,
137*4882a593Smuzhiyun COMMAND_TIMEOUT);
138*4882a593Smuzhiyun usb_kill_urb(dev->interrupt_out_urb);
139*4882a593Smuzhiyun } else
140*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
adu_delete(struct adu_device * dev)143*4882a593Smuzhiyun static void adu_delete(struct adu_device *dev)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun /* free data structures */
146*4882a593Smuzhiyun usb_free_urb(dev->interrupt_in_urb);
147*4882a593Smuzhiyun usb_free_urb(dev->interrupt_out_urb);
148*4882a593Smuzhiyun kfree(dev->read_buffer_primary);
149*4882a593Smuzhiyun kfree(dev->read_buffer_secondary);
150*4882a593Smuzhiyun kfree(dev->interrupt_in_buffer);
151*4882a593Smuzhiyun kfree(dev->interrupt_out_buffer);
152*4882a593Smuzhiyun usb_put_dev(dev->udev);
153*4882a593Smuzhiyun kfree(dev);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
adu_interrupt_in_callback(struct urb * urb)156*4882a593Smuzhiyun static void adu_interrupt_in_callback(struct urb *urb)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun struct adu_device *dev = urb->context;
159*4882a593Smuzhiyun int status = urb->status;
160*4882a593Smuzhiyun unsigned long flags;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun adu_debug_data(&dev->udev->dev, __func__,
163*4882a593Smuzhiyun urb->actual_length, urb->transfer_buffer);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun if (status != 0) {
168*4882a593Smuzhiyun if ((status != -ENOENT) && (status != -ECONNRESET) &&
169*4882a593Smuzhiyun (status != -ESHUTDOWN)) {
170*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
171*4882a593Smuzhiyun "%s : nonzero status received: %d\n",
172*4882a593Smuzhiyun __func__, status);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun goto exit;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) {
178*4882a593Smuzhiyun if (dev->read_buffer_length <
179*4882a593Smuzhiyun (4 * usb_endpoint_maxp(dev->interrupt_in_endpoint)) -
180*4882a593Smuzhiyun (urb->actual_length)) {
181*4882a593Smuzhiyun memcpy (dev->read_buffer_primary +
182*4882a593Smuzhiyun dev->read_buffer_length,
183*4882a593Smuzhiyun dev->interrupt_in_buffer, urb->actual_length);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun dev->read_buffer_length += urb->actual_length;
186*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,"%s reading %d\n", __func__,
187*4882a593Smuzhiyun urb->actual_length);
188*4882a593Smuzhiyun } else {
189*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,"%s : read_buffer overflow\n",
190*4882a593Smuzhiyun __func__);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun exit:
195*4882a593Smuzhiyun dev->read_urb_finished = 1;
196*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
197*4882a593Smuzhiyun /* always wake up so we recover from errors */
198*4882a593Smuzhiyun wake_up_interruptible(&dev->read_wait);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
adu_interrupt_out_callback(struct urb * urb)201*4882a593Smuzhiyun static void adu_interrupt_out_callback(struct urb *urb)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun struct adu_device *dev = urb->context;
204*4882a593Smuzhiyun int status = urb->status;
205*4882a593Smuzhiyun unsigned long flags;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun adu_debug_data(&dev->udev->dev, __func__,
208*4882a593Smuzhiyun urb->actual_length, urb->transfer_buffer);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (status != 0) {
211*4882a593Smuzhiyun if ((status != -ENOENT) &&
212*4882a593Smuzhiyun (status != -ESHUTDOWN) &&
213*4882a593Smuzhiyun (status != -ECONNRESET)) {
214*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
215*4882a593Smuzhiyun "%s :nonzero status received: %d\n", __func__,
216*4882a593Smuzhiyun status);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun return;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
222*4882a593Smuzhiyun dev->out_urb_finished = 1;
223*4882a593Smuzhiyun wake_up(&dev->write_wait);
224*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
adu_open(struct inode * inode,struct file * file)227*4882a593Smuzhiyun static int adu_open(struct inode *inode, struct file *file)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct adu_device *dev = NULL;
230*4882a593Smuzhiyun struct usb_interface *interface;
231*4882a593Smuzhiyun int subminor;
232*4882a593Smuzhiyun int retval;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun subminor = iminor(inode);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun retval = mutex_lock_interruptible(&adutux_mutex);
237*4882a593Smuzhiyun if (retval)
238*4882a593Smuzhiyun goto exit_no_lock;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun interface = usb_find_interface(&adu_driver, subminor);
241*4882a593Smuzhiyun if (!interface) {
242*4882a593Smuzhiyun pr_err("%s - error, can't find device for minor %d\n",
243*4882a593Smuzhiyun __func__, subminor);
244*4882a593Smuzhiyun retval = -ENODEV;
245*4882a593Smuzhiyun goto exit_no_device;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun dev = usb_get_intfdata(interface);
249*4882a593Smuzhiyun if (!dev) {
250*4882a593Smuzhiyun retval = -ENODEV;
251*4882a593Smuzhiyun goto exit_no_device;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /* check that nobody else is using the device */
255*4882a593Smuzhiyun if (dev->open_count) {
256*4882a593Smuzhiyun retval = -EBUSY;
257*4882a593Smuzhiyun goto exit_no_device;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun ++dev->open_count;
261*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s: open count %d\n", __func__,
262*4882a593Smuzhiyun dev->open_count);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /* save device in the file's private structure */
265*4882a593Smuzhiyun file->private_data = dev;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* initialize in direction */
268*4882a593Smuzhiyun dev->read_buffer_length = 0;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* fixup first read by having urb waiting for it */
271*4882a593Smuzhiyun usb_fill_int_urb(dev->interrupt_in_urb, dev->udev,
272*4882a593Smuzhiyun usb_rcvintpipe(dev->udev,
273*4882a593Smuzhiyun dev->interrupt_in_endpoint->bEndpointAddress),
274*4882a593Smuzhiyun dev->interrupt_in_buffer,
275*4882a593Smuzhiyun usb_endpoint_maxp(dev->interrupt_in_endpoint),
276*4882a593Smuzhiyun adu_interrupt_in_callback, dev,
277*4882a593Smuzhiyun dev->interrupt_in_endpoint->bInterval);
278*4882a593Smuzhiyun dev->read_urb_finished = 0;
279*4882a593Smuzhiyun if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL))
280*4882a593Smuzhiyun dev->read_urb_finished = 1;
281*4882a593Smuzhiyun /* we ignore failure */
282*4882a593Smuzhiyun /* end of fixup for first read */
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /* initialize out direction */
285*4882a593Smuzhiyun dev->out_urb_finished = 1;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun retval = 0;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun exit_no_device:
290*4882a593Smuzhiyun mutex_unlock(&adutux_mutex);
291*4882a593Smuzhiyun exit_no_lock:
292*4882a593Smuzhiyun return retval;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
adu_release_internal(struct adu_device * dev)295*4882a593Smuzhiyun static void adu_release_internal(struct adu_device *dev)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun /* decrement our usage count for the device */
298*4882a593Smuzhiyun --dev->open_count;
299*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : open count %d\n", __func__,
300*4882a593Smuzhiyun dev->open_count);
301*4882a593Smuzhiyun if (dev->open_count <= 0) {
302*4882a593Smuzhiyun adu_abort_transfers(dev);
303*4882a593Smuzhiyun dev->open_count = 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
adu_release(struct inode * inode,struct file * file)307*4882a593Smuzhiyun static int adu_release(struct inode *inode, struct file *file)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun struct adu_device *dev;
310*4882a593Smuzhiyun int retval = 0;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (file == NULL) {
313*4882a593Smuzhiyun retval = -ENODEV;
314*4882a593Smuzhiyun goto exit;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun dev = file->private_data;
318*4882a593Smuzhiyun if (dev == NULL) {
319*4882a593Smuzhiyun retval = -ENODEV;
320*4882a593Smuzhiyun goto exit;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun mutex_lock(&adutux_mutex); /* not interruptible */
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (dev->open_count <= 0) {
326*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : device not opened\n", __func__);
327*4882a593Smuzhiyun retval = -ENODEV;
328*4882a593Smuzhiyun goto unlock;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun adu_release_internal(dev);
332*4882a593Smuzhiyun if (dev->disconnected) {
333*4882a593Smuzhiyun /* the device was unplugged before the file was released */
334*4882a593Smuzhiyun if (!dev->open_count) /* ... and we're the last user */
335*4882a593Smuzhiyun adu_delete(dev);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun unlock:
338*4882a593Smuzhiyun mutex_unlock(&adutux_mutex);
339*4882a593Smuzhiyun exit:
340*4882a593Smuzhiyun return retval;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
adu_read(struct file * file,__user char * buffer,size_t count,loff_t * ppos)343*4882a593Smuzhiyun static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
344*4882a593Smuzhiyun loff_t *ppos)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct adu_device *dev;
347*4882a593Smuzhiyun size_t bytes_read = 0;
348*4882a593Smuzhiyun size_t bytes_to_read = count;
349*4882a593Smuzhiyun int retval = 0;
350*4882a593Smuzhiyun int timeout = 0;
351*4882a593Smuzhiyun int should_submit = 0;
352*4882a593Smuzhiyun unsigned long flags;
353*4882a593Smuzhiyun DECLARE_WAITQUEUE(wait, current);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun dev = file->private_data;
356*4882a593Smuzhiyun if (mutex_lock_interruptible(&dev->mtx))
357*4882a593Smuzhiyun return -ERESTARTSYS;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* verify that the device wasn't unplugged */
360*4882a593Smuzhiyun if (dev->disconnected) {
361*4882a593Smuzhiyun retval = -ENODEV;
362*4882a593Smuzhiyun pr_err("No device or device unplugged %d\n", retval);
363*4882a593Smuzhiyun goto exit;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /* verify that some data was requested */
367*4882a593Smuzhiyun if (count == 0) {
368*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : read request of 0 bytes\n",
369*4882a593Smuzhiyun __func__);
370*4882a593Smuzhiyun goto exit;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun timeout = COMMAND_TIMEOUT;
374*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__);
375*4882a593Smuzhiyun while (bytes_to_read) {
376*4882a593Smuzhiyun size_t data_in_secondary = dev->secondary_tail - dev->secondary_head;
377*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
378*4882a593Smuzhiyun "%s : while, data_in_secondary=%zu, status=%d\n",
379*4882a593Smuzhiyun __func__, data_in_secondary,
380*4882a593Smuzhiyun dev->interrupt_in_urb->status);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun if (data_in_secondary) {
383*4882a593Smuzhiyun /* drain secondary buffer */
384*4882a593Smuzhiyun size_t amount = min(bytes_to_read, data_in_secondary);
385*4882a593Smuzhiyun if (copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount)) {
386*4882a593Smuzhiyun retval = -EFAULT;
387*4882a593Smuzhiyun goto exit;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun dev->secondary_head += amount;
390*4882a593Smuzhiyun bytes_read += amount;
391*4882a593Smuzhiyun bytes_to_read -= amount;
392*4882a593Smuzhiyun } else {
393*4882a593Smuzhiyun /* we check the primary buffer */
394*4882a593Smuzhiyun spin_lock_irqsave (&dev->buflock, flags);
395*4882a593Smuzhiyun if (dev->read_buffer_length) {
396*4882a593Smuzhiyun /* we secure access to the primary */
397*4882a593Smuzhiyun char *tmp;
398*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
399*4882a593Smuzhiyun "%s : swap, read_buffer_length = %d\n",
400*4882a593Smuzhiyun __func__, dev->read_buffer_length);
401*4882a593Smuzhiyun tmp = dev->read_buffer_secondary;
402*4882a593Smuzhiyun dev->read_buffer_secondary = dev->read_buffer_primary;
403*4882a593Smuzhiyun dev->read_buffer_primary = tmp;
404*4882a593Smuzhiyun dev->secondary_head = 0;
405*4882a593Smuzhiyun dev->secondary_tail = dev->read_buffer_length;
406*4882a593Smuzhiyun dev->read_buffer_length = 0;
407*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
408*4882a593Smuzhiyun /* we have a free buffer so use it */
409*4882a593Smuzhiyun should_submit = 1;
410*4882a593Smuzhiyun } else {
411*4882a593Smuzhiyun /* even the primary was empty - we may need to do IO */
412*4882a593Smuzhiyun if (!dev->read_urb_finished) {
413*4882a593Smuzhiyun /* somebody is doing IO */
414*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
415*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
416*4882a593Smuzhiyun "%s : submitted already\n",
417*4882a593Smuzhiyun __func__);
418*4882a593Smuzhiyun } else {
419*4882a593Smuzhiyun /* we must initiate input */
420*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
421*4882a593Smuzhiyun "%s : initiate input\n",
422*4882a593Smuzhiyun __func__);
423*4882a593Smuzhiyun dev->read_urb_finished = 0;
424*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun usb_fill_int_urb(dev->interrupt_in_urb, dev->udev,
427*4882a593Smuzhiyun usb_rcvintpipe(dev->udev,
428*4882a593Smuzhiyun dev->interrupt_in_endpoint->bEndpointAddress),
429*4882a593Smuzhiyun dev->interrupt_in_buffer,
430*4882a593Smuzhiyun usb_endpoint_maxp(dev->interrupt_in_endpoint),
431*4882a593Smuzhiyun adu_interrupt_in_callback,
432*4882a593Smuzhiyun dev,
433*4882a593Smuzhiyun dev->interrupt_in_endpoint->bInterval);
434*4882a593Smuzhiyun retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
435*4882a593Smuzhiyun if (retval) {
436*4882a593Smuzhiyun dev->read_urb_finished = 1;
437*4882a593Smuzhiyun if (retval == -ENOMEM) {
438*4882a593Smuzhiyun retval = bytes_read ? bytes_read : -ENOMEM;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
441*4882a593Smuzhiyun "%s : submit failed\n",
442*4882a593Smuzhiyun __func__);
443*4882a593Smuzhiyun goto exit;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun /* we wait for I/O to complete */
448*4882a593Smuzhiyun set_current_state(TASK_INTERRUPTIBLE);
449*4882a593Smuzhiyun add_wait_queue(&dev->read_wait, &wait);
450*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
451*4882a593Smuzhiyun if (!dev->read_urb_finished) {
452*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
453*4882a593Smuzhiyun timeout = schedule_timeout(COMMAND_TIMEOUT);
454*4882a593Smuzhiyun } else {
455*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
456*4882a593Smuzhiyun set_current_state(TASK_RUNNING);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun remove_wait_queue(&dev->read_wait, &wait);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun if (timeout <= 0) {
461*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
462*4882a593Smuzhiyun "%s : timeout\n", __func__);
463*4882a593Smuzhiyun retval = bytes_read ? bytes_read : -ETIMEDOUT;
464*4882a593Smuzhiyun goto exit;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (signal_pending(current)) {
468*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
469*4882a593Smuzhiyun "%s : signal pending\n",
470*4882a593Smuzhiyun __func__);
471*4882a593Smuzhiyun retval = bytes_read ? bytes_read : -EINTR;
472*4882a593Smuzhiyun goto exit;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun retval = bytes_read;
479*4882a593Smuzhiyun /* if the primary buffer is empty then use it */
480*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
481*4882a593Smuzhiyun if (should_submit && dev->read_urb_finished) {
482*4882a593Smuzhiyun dev->read_urb_finished = 0;
483*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
484*4882a593Smuzhiyun usb_fill_int_urb(dev->interrupt_in_urb, dev->udev,
485*4882a593Smuzhiyun usb_rcvintpipe(dev->udev,
486*4882a593Smuzhiyun dev->interrupt_in_endpoint->bEndpointAddress),
487*4882a593Smuzhiyun dev->interrupt_in_buffer,
488*4882a593Smuzhiyun usb_endpoint_maxp(dev->interrupt_in_endpoint),
489*4882a593Smuzhiyun adu_interrupt_in_callback,
490*4882a593Smuzhiyun dev,
491*4882a593Smuzhiyun dev->interrupt_in_endpoint->bInterval);
492*4882a593Smuzhiyun if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0)
493*4882a593Smuzhiyun dev->read_urb_finished = 1;
494*4882a593Smuzhiyun /* we ignore failure */
495*4882a593Smuzhiyun } else {
496*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun exit:
500*4882a593Smuzhiyun /* unlock the device */
501*4882a593Smuzhiyun mutex_unlock(&dev->mtx);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun return retval;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
adu_write(struct file * file,const __user char * buffer,size_t count,loff_t * ppos)506*4882a593Smuzhiyun static ssize_t adu_write(struct file *file, const __user char *buffer,
507*4882a593Smuzhiyun size_t count, loff_t *ppos)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun DECLARE_WAITQUEUE(waita, current);
510*4882a593Smuzhiyun struct adu_device *dev;
511*4882a593Smuzhiyun size_t bytes_written = 0;
512*4882a593Smuzhiyun size_t bytes_to_write;
513*4882a593Smuzhiyun size_t buffer_size;
514*4882a593Smuzhiyun unsigned long flags;
515*4882a593Smuzhiyun int retval;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun dev = file->private_data;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun retval = mutex_lock_interruptible(&dev->mtx);
520*4882a593Smuzhiyun if (retval)
521*4882a593Smuzhiyun goto exit_nolock;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* verify that the device wasn't unplugged */
524*4882a593Smuzhiyun if (dev->disconnected) {
525*4882a593Smuzhiyun retval = -ENODEV;
526*4882a593Smuzhiyun pr_err("No device or device unplugged %d\n", retval);
527*4882a593Smuzhiyun goto exit;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun /* verify that we actually have some data to write */
531*4882a593Smuzhiyun if (count == 0) {
532*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : write request of 0 bytes\n",
533*4882a593Smuzhiyun __func__);
534*4882a593Smuzhiyun goto exit;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun while (count > 0) {
538*4882a593Smuzhiyun add_wait_queue(&dev->write_wait, &waita);
539*4882a593Smuzhiyun set_current_state(TASK_INTERRUPTIBLE);
540*4882a593Smuzhiyun spin_lock_irqsave(&dev->buflock, flags);
541*4882a593Smuzhiyun if (!dev->out_urb_finished) {
542*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun mutex_unlock(&dev->mtx);
545*4882a593Smuzhiyun if (signal_pending(current)) {
546*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : interrupted\n",
547*4882a593Smuzhiyun __func__);
548*4882a593Smuzhiyun set_current_state(TASK_RUNNING);
549*4882a593Smuzhiyun retval = -EINTR;
550*4882a593Smuzhiyun goto exit_onqueue;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
553*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
554*4882a593Smuzhiyun "%s - command timed out.\n", __func__);
555*4882a593Smuzhiyun retval = -ETIMEDOUT;
556*4882a593Smuzhiyun goto exit_onqueue;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun remove_wait_queue(&dev->write_wait, &waita);
559*4882a593Smuzhiyun retval = mutex_lock_interruptible(&dev->mtx);
560*4882a593Smuzhiyun if (retval) {
561*4882a593Smuzhiyun retval = bytes_written ? bytes_written : retval;
562*4882a593Smuzhiyun goto exit_nolock;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
566*4882a593Smuzhiyun "%s : in progress, count = %zd\n",
567*4882a593Smuzhiyun __func__, count);
568*4882a593Smuzhiyun } else {
569*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->buflock, flags);
570*4882a593Smuzhiyun set_current_state(TASK_RUNNING);
571*4882a593Smuzhiyun remove_wait_queue(&dev->write_wait, &waita);
572*4882a593Smuzhiyun dev_dbg(&dev->udev->dev, "%s : sending, count = %zd\n",
573*4882a593Smuzhiyun __func__, count);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun /* write the data into interrupt_out_buffer from userspace */
576*4882a593Smuzhiyun buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint);
577*4882a593Smuzhiyun bytes_to_write = count > buffer_size ? buffer_size : count;
578*4882a593Smuzhiyun dev_dbg(&dev->udev->dev,
579*4882a593Smuzhiyun "%s : buffer_size = %zd, count = %zd, bytes_to_write = %zd\n",
580*4882a593Smuzhiyun __func__, buffer_size, count, bytes_to_write);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
583*4882a593Smuzhiyun retval = -EFAULT;
584*4882a593Smuzhiyun goto exit;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun /* send off the urb */
588*4882a593Smuzhiyun usb_fill_int_urb(
589*4882a593Smuzhiyun dev->interrupt_out_urb,
590*4882a593Smuzhiyun dev->udev,
591*4882a593Smuzhiyun usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
592*4882a593Smuzhiyun dev->interrupt_out_buffer,
593*4882a593Smuzhiyun bytes_to_write,
594*4882a593Smuzhiyun adu_interrupt_out_callback,
595*4882a593Smuzhiyun dev,
596*4882a593Smuzhiyun dev->interrupt_out_endpoint->bInterval);
597*4882a593Smuzhiyun dev->interrupt_out_urb->actual_length = bytes_to_write;
598*4882a593Smuzhiyun dev->out_urb_finished = 0;
599*4882a593Smuzhiyun retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
600*4882a593Smuzhiyun if (retval < 0) {
601*4882a593Smuzhiyun dev->out_urb_finished = 1;
602*4882a593Smuzhiyun dev_err(&dev->udev->dev, "Couldn't submit "
603*4882a593Smuzhiyun "interrupt_out_urb %d\n", retval);
604*4882a593Smuzhiyun goto exit;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun buffer += bytes_to_write;
608*4882a593Smuzhiyun count -= bytes_to_write;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun bytes_written += bytes_to_write;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun mutex_unlock(&dev->mtx);
614*4882a593Smuzhiyun return bytes_written;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun exit:
617*4882a593Smuzhiyun mutex_unlock(&dev->mtx);
618*4882a593Smuzhiyun exit_nolock:
619*4882a593Smuzhiyun return retval;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun exit_onqueue:
622*4882a593Smuzhiyun remove_wait_queue(&dev->write_wait, &waita);
623*4882a593Smuzhiyun return retval;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /* file operations needed when we register this driver */
627*4882a593Smuzhiyun static const struct file_operations adu_fops = {
628*4882a593Smuzhiyun .owner = THIS_MODULE,
629*4882a593Smuzhiyun .read = adu_read,
630*4882a593Smuzhiyun .write = adu_write,
631*4882a593Smuzhiyun .open = adu_open,
632*4882a593Smuzhiyun .release = adu_release,
633*4882a593Smuzhiyun .llseek = noop_llseek,
634*4882a593Smuzhiyun };
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun /*
637*4882a593Smuzhiyun * usb class driver info in order to get a minor number from the usb core,
638*4882a593Smuzhiyun * and to have the device registered with devfs and the driver core
639*4882a593Smuzhiyun */
640*4882a593Smuzhiyun static struct usb_class_driver adu_class = {
641*4882a593Smuzhiyun .name = "usb/adutux%d",
642*4882a593Smuzhiyun .fops = &adu_fops,
643*4882a593Smuzhiyun .minor_base = ADU_MINOR_BASE,
644*4882a593Smuzhiyun };
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun /*
647*4882a593Smuzhiyun * adu_probe
648*4882a593Smuzhiyun *
649*4882a593Smuzhiyun * Called by the usb core when a new device is connected that it thinks
650*4882a593Smuzhiyun * this driver might be interested in.
651*4882a593Smuzhiyun */
adu_probe(struct usb_interface * interface,const struct usb_device_id * id)652*4882a593Smuzhiyun static int adu_probe(struct usb_interface *interface,
653*4882a593Smuzhiyun const struct usb_device_id *id)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun struct usb_device *udev = interface_to_usbdev(interface);
656*4882a593Smuzhiyun struct adu_device *dev = NULL;
657*4882a593Smuzhiyun int retval = -ENOMEM;
658*4882a593Smuzhiyun int in_end_size;
659*4882a593Smuzhiyun int out_end_size;
660*4882a593Smuzhiyun int res;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun /* allocate memory for our device state and initialize it */
663*4882a593Smuzhiyun dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
664*4882a593Smuzhiyun if (!dev)
665*4882a593Smuzhiyun return -ENOMEM;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun mutex_init(&dev->mtx);
668*4882a593Smuzhiyun spin_lock_init(&dev->buflock);
669*4882a593Smuzhiyun dev->udev = usb_get_dev(udev);
670*4882a593Smuzhiyun init_waitqueue_head(&dev->read_wait);
671*4882a593Smuzhiyun init_waitqueue_head(&dev->write_wait);
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun res = usb_find_common_endpoints_reverse(interface->cur_altsetting,
674*4882a593Smuzhiyun NULL, NULL,
675*4882a593Smuzhiyun &dev->interrupt_in_endpoint,
676*4882a593Smuzhiyun &dev->interrupt_out_endpoint);
677*4882a593Smuzhiyun if (res) {
678*4882a593Smuzhiyun dev_err(&interface->dev, "interrupt endpoints not found\n");
679*4882a593Smuzhiyun retval = res;
680*4882a593Smuzhiyun goto error;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun in_end_size = usb_endpoint_maxp(dev->interrupt_in_endpoint);
684*4882a593Smuzhiyun out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL);
687*4882a593Smuzhiyun if (!dev->read_buffer_primary)
688*4882a593Smuzhiyun goto error;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun /* debug code prime the buffer */
691*4882a593Smuzhiyun memset(dev->read_buffer_primary, 'a', in_end_size);
692*4882a593Smuzhiyun memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size);
693*4882a593Smuzhiyun memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size);
694*4882a593Smuzhiyun memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL);
697*4882a593Smuzhiyun if (!dev->read_buffer_secondary)
698*4882a593Smuzhiyun goto error;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun /* debug code prime the buffer */
701*4882a593Smuzhiyun memset(dev->read_buffer_secondary, 'e', in_end_size);
702*4882a593Smuzhiyun memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size);
703*4882a593Smuzhiyun memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size);
704*4882a593Smuzhiyun memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size);
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL);
707*4882a593Smuzhiyun if (!dev->interrupt_in_buffer)
708*4882a593Smuzhiyun goto error;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /* debug code prime the buffer */
711*4882a593Smuzhiyun memset(dev->interrupt_in_buffer, 'i', in_end_size);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
714*4882a593Smuzhiyun if (!dev->interrupt_in_urb)
715*4882a593Smuzhiyun goto error;
716*4882a593Smuzhiyun dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL);
717*4882a593Smuzhiyun if (!dev->interrupt_out_buffer)
718*4882a593Smuzhiyun goto error;
719*4882a593Smuzhiyun dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
720*4882a593Smuzhiyun if (!dev->interrupt_out_urb)
721*4882a593Smuzhiyun goto error;
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number,
724*4882a593Smuzhiyun sizeof(dev->serial_number))) {
725*4882a593Smuzhiyun dev_err(&interface->dev, "Could not retrieve serial number\n");
726*4882a593Smuzhiyun retval = -EIO;
727*4882a593Smuzhiyun goto error;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number);
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun /* we can register the device now, as it is ready */
732*4882a593Smuzhiyun usb_set_intfdata(interface, dev);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun retval = usb_register_dev(interface, &adu_class);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun if (retval) {
737*4882a593Smuzhiyun /* something prevented us from registering this driver */
738*4882a593Smuzhiyun dev_err(&interface->dev, "Not able to get a minor for this device.\n");
739*4882a593Smuzhiyun usb_set_intfdata(interface, NULL);
740*4882a593Smuzhiyun goto error;
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun dev->minor = interface->minor;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun /* let the user know what node this device is now attached to */
746*4882a593Smuzhiyun dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n",
747*4882a593Smuzhiyun le16_to_cpu(udev->descriptor.idProduct), dev->serial_number,
748*4882a593Smuzhiyun (dev->minor - ADU_MINOR_BASE));
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun return 0;
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun error:
753*4882a593Smuzhiyun adu_delete(dev);
754*4882a593Smuzhiyun return retval;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun /*
758*4882a593Smuzhiyun * adu_disconnect
759*4882a593Smuzhiyun *
760*4882a593Smuzhiyun * Called by the usb core when the device is removed from the system.
761*4882a593Smuzhiyun */
adu_disconnect(struct usb_interface * interface)762*4882a593Smuzhiyun static void adu_disconnect(struct usb_interface *interface)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun struct adu_device *dev;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun dev = usb_get_intfdata(interface);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun usb_deregister_dev(interface, &adu_class);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun usb_poison_urb(dev->interrupt_in_urb);
771*4882a593Smuzhiyun usb_poison_urb(dev->interrupt_out_urb);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun mutex_lock(&adutux_mutex);
774*4882a593Smuzhiyun usb_set_intfdata(interface, NULL);
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun mutex_lock(&dev->mtx); /* not interruptible */
777*4882a593Smuzhiyun dev->disconnected = 1;
778*4882a593Smuzhiyun mutex_unlock(&dev->mtx);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun /* if the device is not opened, then we clean up right now */
781*4882a593Smuzhiyun if (!dev->open_count)
782*4882a593Smuzhiyun adu_delete(dev);
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun mutex_unlock(&adutux_mutex);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun /* usb specific object needed to register this driver with the usb subsystem */
788*4882a593Smuzhiyun static struct usb_driver adu_driver = {
789*4882a593Smuzhiyun .name = "adutux",
790*4882a593Smuzhiyun .probe = adu_probe,
791*4882a593Smuzhiyun .disconnect = adu_disconnect,
792*4882a593Smuzhiyun .id_table = device_table,
793*4882a593Smuzhiyun };
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun module_usb_driver(adu_driver);
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun MODULE_AUTHOR(DRIVER_AUTHOR);
798*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
799*4882a593Smuzhiyun MODULE_LICENSE("GPL");
800