v2.4.2.7 -> v2.4.2.8
[linux-flexiantxendom0-3.2.10.git] / drivers / usb / serial / omninet.c
1 /*
2  * USB ZyXEL omni.net LCD PLUS driver
3  *
4  *      This program 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  * See Documentation/usb/usb-serial.txt for more information on using this driver
10  *
11  * Please report both successes and troubles to the author at omninet@kroah.com
12  *
13  * (11/01/2000) Adam J. Richter
14  *      usb_device_id table support
15  * 
16  * (10/05/2000) gkh
17  *      Fixed bug with urb->dev not being set properly, now that the usb
18  *      core needs it.
19  * 
20  * (08/28/2000) gkh
21  *      Added locks for SMP safeness.
22  *      Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
23  *      than once.
24  *      Fixed potential race in omninet_write_bulk_callback
25  *
26  * (07/19/2000) gkh
27  *      Added module_init and module_exit functions to handle the fact that this
28  *      driver is a loadable module now.
29  *
30  */
31
32 #include <linux/config.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/signal.h>
36 #include <linux/errno.h>
37 #include <linux/poll.h>
38 #include <linux/init.h>
39 #include <linux/slab.h>
40 #include <linux/fcntl.h>
41 #include <linux/tty.h>
42 #include <linux/tty_driver.h>
43 #include <linux/tty_flip.h>
44 #include <linux/module.h>
45 #include <linux/spinlock.h>
46
47
48 #ifdef CONFIG_USB_SERIAL_DEBUG
49         #define isalpha(x) ( ( x > 96 && x < 123) || ( x > 64 && x < 91) || (x > 47 && x < 58) )
50         #define DEBUG
51 #else
52         #undef DEBUG
53 #endif
54
55 #include <linux/usb.h>
56
57 #include "usb-serial.h"
58
59
60 #define ZYXEL_VENDOR_ID         0x0586
61 #define ZYXEL_OMNINET_ID        0x1000
62
63 /* function prototypes */
64 static int  omninet_open                (struct usb_serial_port *port, struct file *filp);
65 static void omninet_close               (struct usb_serial_port *port, struct file *filp);
66 static void omninet_read_bulk_callback  (struct urb *urb);
67 static void omninet_write_bulk_callback (struct urb *urb);
68 static int  omninet_write               (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
69 static int  omninet_write_room          (struct usb_serial_port *port);
70 static void omninet_shutdown            (struct usb_serial *serial);
71
72 static __devinitdata struct usb_device_id id_table [] = {
73         { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
74         { }                                             /* Terminating entry */
75 };
76
77 MODULE_DEVICE_TABLE (usb, id_table);
78
79
80 struct usb_serial_device_type zyxel_omninet_device = {
81         name:                   "ZyXEL - omni.net lcd plus usb",
82         id_table:               id_table,
83         needs_interrupt_in:     MUST_HAVE,
84         needs_bulk_in:          MUST_HAVE,
85         needs_bulk_out:         MUST_HAVE,
86         num_interrupt_in:       1,
87         num_bulk_in:            1,
88         num_bulk_out:           2,
89         num_ports:              1,
90         open:                   omninet_open,
91         close:                  omninet_close,
92         write:                  omninet_write,
93         write_room:             omninet_write_room,
94         read_bulk_callback:     omninet_read_bulk_callback,
95         write_bulk_callback:    omninet_write_bulk_callback,
96         shutdown:               omninet_shutdown,
97 };
98
99
100 /* The protocol.
101  *
102  * The omni.net always exchange 64 bytes of data with the host. The first
103  * four bytes are the control header, you can see it in the above structure.
104  *
105  * oh_seq is a sequence number. Don't know if/how it's used.
106  * oh_len is the length of the data bytes in the packet.
107  * oh_xxx Bit-mapped, related to handshaking and status info.
108  *      I normally set it to 0x03 in trasmitted frames.
109  *      7: Active when the TA is in a CONNECTed state.
110  *      6: unknown
111  *      5: handshaking, unknown
112  *      4: handshaking, unknown
113  *      3: unknown, usually 0
114  *      2: unknown, usually 0
115  *      1: handshaking, unknown, usually set to 1 in trasmitted frames
116  *      0: handshaking, unknown, usually set to 1 in trasmitted frames
117  * oh_pad Probably a pad byte.
118  *
119  * After the header you will find data bytes if oh_len was greater than zero.
120  *
121  */
122
123 struct omninet_header
124 {
125         __u8    oh_seq;
126         __u8    oh_len;
127         __u8    oh_xxx;
128         __u8    oh_pad;
129 };
130
131 struct omninet_data
132 {
133         __u8    od_outseq;      // Sequence number for bulk_out URBs
134 };
135
136 static int omninet_open (struct usb_serial_port *port, struct file *filp)
137 {
138         struct usb_serial       *serial;
139         struct usb_serial_port  *wport;
140         struct omninet_data     *od;
141         unsigned long           flags;
142         int                     result;
143
144         if (port_paranoia_check (port, __FUNCTION__))
145                 return -ENODEV;
146
147         dbg(__FUNCTION__ " - port %d", port->number);
148
149         serial = get_usb_serial (port, __FUNCTION__);
150         if (!serial)
151                 return -ENODEV;
152
153         spin_lock_irqsave (&port->port_lock, flags);
154
155         MOD_INC_USE_COUNT;
156         ++port->open_count;
157
158         if (!port->active) {
159                 port->active = 1;
160
161                 od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
162                 if( !od ) {
163                         err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
164                         --port->open_count;
165                         port->active = 0;
166                         spin_unlock_irqrestore (&port->port_lock, flags);
167                         MOD_DEC_USE_COUNT;
168                         return -ENOMEM;
169                 }
170
171                 port->private = od;
172                 wport = &serial->port[1];
173                 wport->tty = port->tty;
174
175                 /* Start reading from the device */
176                 FILL_BULK_URB(port->read_urb, serial->dev, 
177                               usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
178                               port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
179                               omninet_read_bulk_callback, port);
180                 result = usb_submit_urb(port->read_urb);
181                 if (result)
182                         err(__FUNCTION__ " - failed submitting read urb, error %d", result);
183         }
184
185         spin_unlock_irqrestore (&port->port_lock, flags);
186
187         return (0);
188 }
189
190 static void omninet_close (struct usb_serial_port *port, struct file * filp)
191 {
192         struct usb_serial       *serial;
193         struct usb_serial_port  *wport;
194         struct omninet_data     *od;
195         unsigned long           flags;
196
197         if (port_paranoia_check (port, __FUNCTION__))
198                 return;
199
200         dbg(__FUNCTION__ " - port %d", port->number);
201
202         serial = get_usb_serial (port, __FUNCTION__);
203         if (!serial)
204                 return;
205
206         spin_lock_irqsave (&port->port_lock, flags);
207
208         --port->open_count;
209         MOD_DEC_USE_COUNT;
210
211         if (port->open_count <= 0) {
212                 od = (struct omninet_data *)port->private;
213                 wport = &serial->port[1];
214
215                 usb_unlink_urb (wport->write_urb);
216                 usb_unlink_urb (port->read_urb);
217
218                 port->active = 0;
219                 port->open_count = 0;
220                 if (od)
221                         kfree(od);
222         }
223
224         spin_unlock_irqrestore (&port->port_lock, flags);
225 }
226
227
228 #define OMNINET_DATAOFFSET      0x04
229 #define OMNINET_HEADERLEN       sizeof(struct omninet_header)
230 #define OMNINET_BULKOUTSIZE     (64 - OMNINET_HEADERLEN)
231
232 static void omninet_read_bulk_callback (struct urb *urb)
233 {
234         struct usb_serial_port  *port   = (struct usb_serial_port *)urb->context;
235         struct usb_serial       *serial = get_usb_serial (port, __FUNCTION__);
236
237         unsigned char           *data   = urb->transfer_buffer;
238         struct omninet_header   *header = (struct omninet_header *) &data[0];
239
240         int i;
241         int result;
242
243 //      dbg("omninet_read_bulk_callback");
244
245         if (!serial) {
246                 dbg(__FUNCTION__ " - bad serial pointer, exiting");
247                 return;
248         }
249
250         if (urb->status) {
251                 dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
252                 return;
253         }
254
255 #ifdef DEBUG
256         if(header->oh_xxx != 0x30) {
257                 if (urb->actual_length) {
258                         printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
259                         for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
260                                 printk ("%.2x ", data[i]);
261                         }
262                         printk ("\n");
263                 }
264         }
265 #endif
266
267         if (urb->actual_length && header->oh_len) {
268                 for (i = 0; i < header->oh_len; i++) {
269                          tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0);
270                 }
271                 tty_flip_buffer_push(port->tty);
272         }
273
274         /* Continue trying to always read  */
275         FILL_BULK_URB(urb, serial->dev, 
276                       usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
277                       urb->transfer_buffer, urb->transfer_buffer_length,
278                       omninet_read_bulk_callback, port);
279         result = usb_submit_urb(urb);
280         if (result)
281                 err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
282
283         return;
284 }
285
286 static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
287 {
288         struct usb_serial       *serial = port->serial;
289         struct usb_serial_port  *wport  = &serial->port[1];
290
291         struct omninet_data     *od     = (struct omninet_data   *) port->private;
292         struct omninet_header   *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
293
294         unsigned long           flags;
295         int                     result;
296
297 //      dbg("omninet_write port %d", port->number);
298
299         if (count == 0) {
300                 dbg(__FUNCTION__" - write request of 0 bytes");
301                 return (0);
302         }
303         if (wport->write_urb->status == -EINPROGRESS) {
304                 dbg (__FUNCTION__" - already writing");
305                 return (0);
306         }
307
308         spin_lock_irqsave (&port->port_lock, flags);
309         
310         count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
311
312         if (from_user) {
313                 copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
314         }
315         else {
316                 memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
317         }
318
319         usb_serial_debug_data (__FILE__, __FUNCTION__, count, wport->write_urb->transfer_buffer);
320
321         header->oh_seq  = od->od_outseq++;
322         header->oh_len  = count;
323         header->oh_xxx  = 0x03;
324         header->oh_pad  = 0x00;
325
326         /* send the data out the bulk port, always 64 bytes */
327         wport->write_urb->transfer_buffer_length = 64;
328
329         wport->write_urb->dev = serial->dev;
330         result = usb_submit_urb(wport->write_urb);
331         if (result) {
332                 err(__FUNCTION__ " - failed submitting write urb, error %d", result);
333                 spin_unlock_irqrestore (&port->port_lock, flags);
334                 return 0;
335         }
336
337 //      dbg("omninet_write returns %d", count);
338
339         spin_unlock_irqrestore (&port->port_lock, flags);
340         return (count);
341 }
342
343
344 static int omninet_write_room (struct usb_serial_port *port)
345 {
346         struct usb_serial       *serial = port->serial;
347         struct usb_serial_port  *wport  = &serial->port[1];
348
349         int room = 0; // Default: no room
350
351         if (wport->write_urb->status != -EINPROGRESS)
352                 room = wport->bulk_out_size - OMNINET_HEADERLEN;
353
354 //      dbg("omninet_write_room returns %d", room);
355
356         return (room);
357 }
358
359 static void omninet_write_bulk_callback (struct urb *urb)
360 {
361 /*      struct omninet_header   *header = (struct omninet_header  *) urb->transfer_buffer; */
362         struct usb_serial_port  *port   = (struct usb_serial_port *) urb->context;
363         struct usb_serial       *serial;
364
365 //      dbg("omninet_write_bulk_callback, port %0x\n", port);
366
367
368         if (port_paranoia_check (port, __FUNCTION__)) {
369                 return;
370         }
371
372         serial = port->serial;
373         if (serial_paranoia_check (serial, __FUNCTION__)) {
374                 return;
375         }
376
377         if (urb->status) {
378                 dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);
379                 return;
380         }
381
382         queue_task(&port->tqueue, &tq_immediate);
383         mark_bh(IMMEDIATE_BH);
384
385 //      dbg("omninet_write_bulk_callback, tty %0x\n", tty);
386
387         return;
388 }
389
390
391 static void omninet_shutdown (struct usb_serial *serial)
392 {
393         dbg (__FUNCTION__);
394
395         while (serial->port[0].open_count > 0) {
396                 omninet_close (&serial->port[0], NULL);
397         }
398 }
399
400
401 static int __init omninet_init (void)
402 {
403         usb_serial_register (&zyxel_omninet_device);
404         return 0;
405 }
406
407
408 static void __exit omninet_exit (void)
409 {
410         usb_serial_deregister (&zyxel_omninet_device);
411 }
412
413
414 module_init(omninet_init);
415 module_exit(omninet_exit);
416