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