OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [usb/] [serial/] [omninet.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.