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