Subversion Repositories shark

Rev

Rev 846 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
846 giacomo 1
/*
2
 * USB Serial Console driver
3
 *
4
 * Copyright (C) 2001 - 2002 Greg Kroah-Hartman (greg@kroah.com)
5
 *
6
 *      This program is free software; you can redistribute it and/or
7
 *      modify it under the terms of the GNU General Public License version
8
 *      2 as published by the Free Software Foundation.
9
 *
10
 * Thanks to Randy Dunlap for the original version of this code.
11
 *
12
 */
13
 
14
#include <linuxcomp.h>
15
 
16
#include <linux/config.h>
17
#include <linux/kernel.h>
18
#include <linux/init.h>
19
#include <linux/slab.h>
20
#include <linux/tty.h>
21
#include <linux/console.h>
22
#include <linux/usb.h>
23
 
24
static int debug;
25
 
26
#include "usb-serial.h"
27
 
28
struct usbcons_info {
29
        int                     magic;
30
        int                     break_flag;
31
        struct usb_serial_port  *port;
32
};
33
 
34
static struct usbcons_info usbcons_info;
35
static struct console usbcons;
36
 
37
/*
38
 * ------------------------------------------------------------
39
 * USB Serial console driver
40
 *
41
 * Much of the code here is copied from drivers/char/serial.c
42
 * and implements a phony serial console in the same way that
43
 * serial.c does so that in case some software queries it,
44
 * it will get the same results.
45
 *
46
 * Things that are different from the way the serial port code
47
 * does things, is that we call the lower level usb-serial
48
 * driver code to initialize the device, and we set the initial
49
 * console speeds based on the command line arguments.
50
 * ------------------------------------------------------------
51
 */
52
 
53
 
54
/*
55
 * The parsing of the command line works exactly like the
56
 * serial.c code, except that the specifier is "ttyUSB" instead
57
 * of "ttyS".
58
 */
59
static int __init usb_console_setup(struct console *co, char *options)
60
{
61
        struct usbcons_info *info = &usbcons_info;
62
        int baud = 9600;
63
        int bits = 8;
64
        int parity = 'n';
65
        int doflow = 0;
66
        int cflag = CREAD | HUPCL | CLOCAL;
67
        char *s;
68
        struct usb_serial *serial;
69
        struct usb_serial_port *port;
70
        int retval = 0;
71
        struct tty_struct *tty;
72
        struct termios *termios;
73
 
74
        dbg ("%s", __FUNCTION__);
75
 
76
        if (options) {
77
                baud = simple_strtoul(options, NULL, 10);
78
                s = options;
79
                while (*s >= '0' && *s <= '9')
80
                        s++;
81
                if (*s)
82
                        parity = *s++;
83
                if (*s)
84
                        bits   = *s++ - '0';
85
                if (*s)
86
                        doflow = (*s++ == 'r');
87
        }
88
 
89
        /* build a cflag setting */
90
        switch (baud) {
91
                case 1200:
92
                        cflag |= B1200;
93
                        break;
94
                case 2400:
95
                        cflag |= B2400;
96
                        break;
97
                case 4800:
98
                        cflag |= B4800;
99
                        break;
100
                case 19200:
101
                        cflag |= B19200;
102
                        break;
103
                case 38400:
104
                        cflag |= B38400;
105
                        break;
106
                case 57600:
107
                        cflag |= B57600;
108
                        break;
109
                case 115200:
110
                        cflag |= B115200;
111
                        break;
112
                case 9600:
113
                default:
114
                        cflag |= B9600;
115
                        /*
116
                         * Set this to a sane value to prevent a divide error
117
                         */
118
                        baud  = 9600;
119
                        break;
120
        }
121
        switch (bits) {
122
                case 7:
123
                        cflag |= CS7;
124
                        break;
125
                default:
126
                case 8:
127
                        cflag |= CS8;
128
                        break;
129
        }
130
        switch (parity) {
131
                case 'o': case 'O':
132
                        cflag |= PARODD;
133
                        break;
134
                case 'e': case 'E':
135
                        cflag |= PARENB;
136
                        break;
137
        }
138
        co->cflag = cflag;
139
 
140
        /* grab the first serial port that happens to be connected */
141
        serial = usb_serial_get_by_index(0);
142
        if (serial_paranoia_check (serial, __FUNCTION__)) {
143
                /* no device is connected yet, sorry :( */
144
                err ("No USB device connected to ttyUSB0");
145
                return -ENODEV;
146
        }
147
 
148
        port = serial->port[0];
149
        port->tty = NULL;
150
 
151
        info->port = port;
152
 
153
        ++port->open_count;
154
        if (port->open_count == 1) {
155
                /* only call the device specific open if this
156
                 * is the first time the port is opened */
157
                if (serial->type->open)
158
                        retval = serial->type->open(port, NULL);
159
                else
160
                        retval = usb_serial_generic_open(port, NULL);
161
                if (retval)
162
                        port->open_count = 0;
163
        }
164
 
165
        if (retval) {
166
                err ("could not open USB console port");
167
                return retval;
168
        }
169
 
170
        if (serial->type->set_termios) {
171
                /* build up a fake tty structure so that the open call has something
172
                 * to look at to get the cflag value */
173
                tty = kmalloc (sizeof (*tty), GFP_KERNEL);
174
                if (!tty) {
175
                        err ("no more memory");
176
                        return -ENOMEM;
177
                }
178
                termios = kmalloc (sizeof (*termios), GFP_KERNEL);
179
                if (!termios) {
180
                        err ("no more memory");
181
                        kfree (tty);
182
                        return -ENOMEM;
183
                }
184
                memset (tty, 0x00, sizeof(*tty));
185
                memset (termios, 0x00, sizeof(*termios));
186
                termios->c_cflag = cflag;
187
                tty->termios = termios;
188
                port->tty = tty;
189
 
190
                /* set up the initial termios settings */
191
                serial->type->set_termios(port, NULL);
192
                port->tty = NULL;
193
                kfree (termios);
194
                kfree (tty);
195
        }
196
 
197
        return retval;
198
}
199
 
200
static void usb_console_write(struct console *co, const char *buf, unsigned count)
201
{
202
        static struct usbcons_info *info = &usbcons_info;
203
        struct usb_serial_port *port = info->port;
204
        struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
205
        int retval = -ENODEV;
206
 
207
        if (!serial || !port)
208
                return;
209
 
210
        if (count == 0)
211
                return;
212
 
213
        dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
214
 
215
        if (!port->open_count) {
216
                dbg ("%s - port not opened", __FUNCTION__);
217
                goto exit;
218
        }
219
 
220
        /* pass on to the driver specific version of this function if it is available */
221
        if (serial->type->write)
222
                retval = serial->type->write(port, 0, buf, count);
223
        else
224
                retval = usb_serial_generic_write(port, 0, buf, count);
225
 
226
exit:
227
        dbg("%s - return value (if we had one): %d", __FUNCTION__, retval);
228
}
229
 
230
static struct console usbcons = {
231
        .name =         "ttyUSB",
232
        .write =        usb_console_write,
233
        .setup =        usb_console_setup,
234
        .flags =        CON_PRINTBUFFER,
235
        .index =        -1,
236
};
237
 
238
void usb_serial_console_init (int serial_debug, int minor)
239
{
240
        debug = serial_debug;
241
 
242
        if (minor == 0) {
243
                /*
244
                 * Call register_console() if this is the first device plugged
245
                 * in.  If we call it earlier, then the callback to
246
                 * console_setup() will fail, as there is not a device seen by
247
                 * the USB subsystem yet.
248
                 */
249
                /*
250
                 * Register console.
251
                 * NOTES:
252
                 * console_setup() is called (back) immediately (from register_console).
253
                 * console_write() is called immediately from register_console iff
254
                 * CON_PRINTBUFFER is set in flags.
255
                 */
256
                dbg ("registering the USB serial console.");
257
                register_console(&usbcons);
258
        }
259
}
260
 
261
void usb_serial_console_exit (void)
262
{
263
        unregister_console(&usbcons);
264
}
265