2 * USB ZyXEL omni.net LCD PLUS driver
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.
9 * See Documentation/usb/usb-serial.txt for more information on using this driver
11 * Please report both successes and troubles to the author at omninet@kroah.com
13 * (11/01/2000) Adam J. Richter
14 * usb_device_id table support
17 * Fixed bug with urb->dev not being set properly, now that the usb
21 * Added locks for SMP safeness.
22 * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
24 * Fixed potential race in omninet_write_bulk_callback
27 * Added module_init and module_exit functions to handle the fact that this
28 * driver is a loadable module now.
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>
48 #ifdef CONFIG_USB_SERIAL_DEBUG
49 #define isalpha(x) ( ( x > 96 && x < 123) || ( x > 64 && x < 91) || (x > 47 && x < 58) )
55 #include <linux/usb.h>
57 #include "usb-serial.h"
60 #define ZYXEL_VENDOR_ID 0x0586
61 #define ZYXEL_OMNINET_ID 0x1000
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);
72 static __devinitdata struct usb_device_id id_table [] = {
73 { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
74 { } /* Terminating entry */
77 MODULE_DEVICE_TABLE (usb, id_table);
80 struct usb_serial_device_type zyxel_omninet_device = {
81 name: "ZyXEL - omni.net lcd plus usb",
83 needs_interrupt_in: MUST_HAVE,
84 needs_bulk_in: MUST_HAVE,
85 needs_bulk_out: MUST_HAVE,
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,
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.
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.
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.
119 * After the header you will find data bytes if oh_len was greater than zero.
123 struct omninet_header
133 __u8 od_outseq; // Sequence number for bulk_out URBs
136 static int omninet_open (struct usb_serial_port *port, struct file *filp)
138 struct usb_serial *serial;
139 struct usb_serial_port *wport;
140 struct omninet_data *od;
144 if (port_paranoia_check (port, __FUNCTION__))
147 dbg(__FUNCTION__ " - port %d", port->number);
149 serial = get_usb_serial (port, __FUNCTION__);
153 spin_lock_irqsave (&port->port_lock, flags);
161 od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
163 err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
166 spin_unlock_irqrestore (&port->port_lock, flags);
172 wport = &serial->port[1];
173 wport->tty = port->tty;
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);
182 err(__FUNCTION__ " - failed submitting read urb, error %d", result);
185 spin_unlock_irqrestore (&port->port_lock, flags);
190 static void omninet_close (struct usb_serial_port *port, struct file * filp)
192 struct usb_serial *serial;
193 struct usb_serial_port *wport;
194 struct omninet_data *od;
197 if (port_paranoia_check (port, __FUNCTION__))
200 dbg(__FUNCTION__ " - port %d", port->number);
202 serial = get_usb_serial (port, __FUNCTION__);
206 spin_lock_irqsave (&port->port_lock, flags);
211 if (port->open_count <= 0) {
212 od = (struct omninet_data *)port->private;
213 wport = &serial->port[1];
215 usb_unlink_urb (wport->write_urb);
216 usb_unlink_urb (port->read_urb);
219 port->open_count = 0;
224 spin_unlock_irqrestore (&port->port_lock, flags);
228 #define OMNINET_DATAOFFSET 0x04
229 #define OMNINET_HEADERLEN sizeof(struct omninet_header)
230 #define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN)
232 static void omninet_read_bulk_callback (struct urb *urb)
234 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
235 struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
237 unsigned char *data = urb->transfer_buffer;
238 struct omninet_header *header = (struct omninet_header *) &data[0];
243 // dbg("omninet_read_bulk_callback");
246 dbg(__FUNCTION__ " - bad serial pointer, exiting");
251 dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
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]);
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);
271 tty_flip_buffer_push(port->tty);
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);
281 err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
286 static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
288 struct usb_serial *serial = port->serial;
289 struct usb_serial_port *wport = &serial->port[1];
291 struct omninet_data *od = (struct omninet_data *) port->private;
292 struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
297 // dbg("omninet_write port %d", port->number);
300 dbg(__FUNCTION__" - write request of 0 bytes");
303 if (wport->write_urb->status == -EINPROGRESS) {
304 dbg (__FUNCTION__" - already writing");
308 spin_lock_irqsave (&port->port_lock, flags);
310 count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
313 copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
316 memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
319 usb_serial_debug_data (__FILE__, __FUNCTION__, count, wport->write_urb->transfer_buffer);
321 header->oh_seq = od->od_outseq++;
322 header->oh_len = count;
323 header->oh_xxx = 0x03;
324 header->oh_pad = 0x00;
326 /* send the data out the bulk port, always 64 bytes */
327 wport->write_urb->transfer_buffer_length = 64;
329 wport->write_urb->dev = serial->dev;
330 result = usb_submit_urb(wport->write_urb);
332 err(__FUNCTION__ " - failed submitting write urb, error %d", result);
333 spin_unlock_irqrestore (&port->port_lock, flags);
337 // dbg("omninet_write returns %d", count);
339 spin_unlock_irqrestore (&port->port_lock, flags);
344 static int omninet_write_room (struct usb_serial_port *port)
346 struct usb_serial *serial = port->serial;
347 struct usb_serial_port *wport = &serial->port[1];
349 int room = 0; // Default: no room
351 if (wport->write_urb->status != -EINPROGRESS)
352 room = wport->bulk_out_size - OMNINET_HEADERLEN;
354 // dbg("omninet_write_room returns %d", room);
359 static void omninet_write_bulk_callback (struct urb *urb)
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;
365 // dbg("omninet_write_bulk_callback, port %0x\n", port);
368 if (port_paranoia_check (port, __FUNCTION__)) {
372 serial = port->serial;
373 if (serial_paranoia_check (serial, __FUNCTION__)) {
378 dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);
382 queue_task(&port->tqueue, &tq_immediate);
383 mark_bh(IMMEDIATE_BH);
385 // dbg("omninet_write_bulk_callback, tty %0x\n", tty);
391 static void omninet_shutdown (struct usb_serial *serial)
395 while (serial->port[0].open_count > 0) {
396 omninet_close (&serial->port[0], NULL);
401 static int __init omninet_init (void)
403 usb_serial_register (&zyxel_omninet_device);
408 static void __exit omninet_exit (void)
410 usb_serial_deregister (&zyxel_omninet_device);
414 module_init(omninet_init);
415 module_exit(omninet_exit);