| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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. | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 9 | * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10 | * Thanks to Randy Dunlap for the original version of this code. | 
|  | 11 | * | 
|  | 12 | */ | 
|  | 13 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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> | 
| Greg Kroah-Hartman | a969888 | 2006-07-11 21:22:58 -0700 | [diff] [blame] | 20 | #include <linux/usb/serial.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
|  | 22 | static int debug; | 
|  | 23 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 | struct usbcons_info { | 
|  | 25 | int			magic; | 
|  | 26 | int			break_flag; | 
|  | 27 | struct usb_serial_port	*port; | 
|  | 28 | }; | 
|  | 29 |  | 
|  | 30 | static struct usbcons_info usbcons_info; | 
|  | 31 | static 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 | */ | 
| Paul Fulghum | 69a4bf7 | 2006-04-12 23:41:59 +0200 | [diff] [blame] | 55 | static int usb_console_setup(struct console *co, char *options) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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; | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 67 | struct tty_struct *tty = NULL; | 
|  | 68 | struct ktermios *termios = NULL, dummy; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 |  | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 70 | dbg("%s", __func__); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | } | 
| Alan Cox | c17ee88 | 2008-07-22 11:10:08 +0100 | [diff] [blame] | 84 |  | 
|  | 85 | /* Sane default */ | 
|  | 86 | if (baud == 0) | 
|  | 87 | baud = 9600; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 89 | switch (bits) { | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 90 | case 7: | 
|  | 91 | cflag |= CS7; | 
|  | 92 | break; | 
|  | 93 | default: | 
|  | 94 | case 8: | 
|  | 95 | cflag |= CS8; | 
|  | 96 | break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 97 | } | 
|  | 98 | switch (parity) { | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 99 | case 'o': case 'O': | 
|  | 100 | cflag |= PARODD; | 
|  | 101 | break; | 
|  | 102 | case 'e': case 'E': | 
|  | 103 | cflag |= PARENB; | 
|  | 104 | break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 | } | 
|  | 106 | co->cflag = cflag; | 
|  | 107 |  | 
| Aristeu Rozanski | 27680d2 | 2007-11-12 15:14:49 -0500 | [diff] [blame] | 108 | /* | 
|  | 109 | * no need to check the index here: if the index is wrong, console | 
|  | 110 | * code won't call us | 
|  | 111 | */ | 
|  | 112 | serial = usb_serial_get_by_index(co->index); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 113 | if (serial == NULL) { | 
|  | 114 | /* no device is connected yet, sorry :( */ | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 115 | err("No USB device connected to ttyUSB%i", co->index); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | return -ENODEV; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | port = serial->port[0]; | 
| Alan Cox | 4a90f09 | 2008-10-13 10:39:46 +0100 | [diff] [blame] | 120 | tty_port_tty_set(&port->port, NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 121 |  | 
|  | 122 | info->port = port; | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 123 |  | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 124 | ++port->port.count; | 
|  | 125 | if (port->port.count == 1) { | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 126 | if (serial->type->set_termios) { | 
|  | 127 | /* | 
|  | 128 | * allocate a fake tty so the driver can initialize | 
|  | 129 | * the termios structure, then later call set_termios to | 
|  | 130 | * configure according to command line arguments | 
|  | 131 | */ | 
|  | 132 | tty = kzalloc(sizeof(*tty), GFP_KERNEL); | 
|  | 133 | if (!tty) { | 
|  | 134 | retval = -ENOMEM; | 
|  | 135 | err("no more memory"); | 
|  | 136 | goto reset_open_count; | 
|  | 137 | } | 
| Kevin Hao | e540458 | 2008-12-01 11:36:16 +0000 | [diff] [blame] | 138 | kref_init(&tty->kref); | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 139 | termios = kzalloc(sizeof(*termios), GFP_KERNEL); | 
|  | 140 | if (!termios) { | 
|  | 141 | retval = -ENOMEM; | 
|  | 142 | err("no more memory"); | 
|  | 143 | goto free_tty; | 
|  | 144 | } | 
|  | 145 | memset(&dummy, 0, sizeof(struct ktermios)); | 
|  | 146 | tty->termios = termios; | 
| Alan Cox | 4a90f09 | 2008-10-13 10:39:46 +0100 | [diff] [blame] | 147 | tty_port_tty_set(&port->port, tty); | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 148 | } | 
|  | 149 |  | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 150 | /* only call the device specific open if this | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 151 | * is the first time the port is opened */ | 
|  | 152 | if (serial->type->open) | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 153 | retval = serial->type->open(NULL, port, NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 154 | else | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 155 | retval = usb_serial_generic_open(NULL, port, NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 156 |  | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 157 | if (retval) { | 
|  | 158 | err("could not open USB console port"); | 
|  | 159 | goto free_termios; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 161 |  | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 162 | if (serial->type->set_termios) { | 
|  | 163 | termios->c_cflag = cflag; | 
| Alan Cox | c17ee88 | 2008-07-22 11:10:08 +0100 | [diff] [blame] | 164 | tty_termios_encode_baud_rate(termios, baud, baud); | 
| Jason Wessel | 06dd881 | 2008-09-08 14:53:37 +0100 | [diff] [blame] | 165 | serial->type->set_termios(tty, port, &dummy); | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 166 |  | 
| Alan Cox | 4a90f09 | 2008-10-13 10:39:46 +0100 | [diff] [blame] | 167 | tty_port_tty_set(&port->port, NULL); | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 168 | kfree(termios); | 
|  | 169 | kfree(tty); | 
|  | 170 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 171 | } | 
| Jason Wessel | 6e40612 | 2009-06-22 11:32:20 -0500 | [diff] [blame] | 172 | /* Now that any required fake tty operations are completed restore | 
|  | 173 | * the tty port count */ | 
|  | 174 | --port->port.count; | 
|  | 175 | /* The console is special in terms of closing the device so | 
|  | 176 | * indicate this port is now acting as a system console. */ | 
| Aristeu Rozanski | 9a6b1ef | 2007-11-12 15:15:02 -0500 | [diff] [blame] | 177 | port->console = 1; | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 178 | retval = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 179 |  | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 180 | out: | 
|  | 181 | return retval; | 
|  | 182 | free_termios: | 
|  | 183 | kfree(termios); | 
| Alan Cox | 4a90f09 | 2008-10-13 10:39:46 +0100 | [diff] [blame] | 184 | tty_port_tty_set(&port->port, NULL); | 
| Aristeu Rozanski | c87d6a4 | 2007-11-13 17:22:07 -0500 | [diff] [blame] | 185 | free_tty: | 
|  | 186 | kfree(tty); | 
|  | 187 | reset_open_count: | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 188 | port->port.count = 0; | 
| Alan Cox | 335f851 | 2009-06-11 12:26:29 +0100 | [diff] [blame] | 189 | goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 192 | static void usb_console_write(struct console *co, | 
|  | 193 | const char *buf, unsigned count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 194 | { | 
|  | 195 | static struct usbcons_info *info = &usbcons_info; | 
|  | 196 | struct usb_serial_port *port = info->port; | 
|  | 197 | struct usb_serial *serial; | 
|  | 198 | int retval = -ENODEV; | 
|  | 199 |  | 
| Guennadi Liakhovetski | 73e487f | 2006-04-25 07:46:17 +0200 | [diff] [blame] | 200 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 201 | return; | 
|  | 202 | serial = port->serial; | 
|  | 203 |  | 
|  | 204 | if (count == 0) | 
|  | 205 | return; | 
|  | 206 |  | 
| Harvey Harrison | 441b62c | 2008-03-03 16:08:34 -0800 | [diff] [blame] | 207 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 208 |  | 
| Jason Wessel | 6e40612 | 2009-06-22 11:32:20 -0500 | [diff] [blame] | 209 | if (!port->console) { | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 210 | dbg("%s - port not opened", __func__); | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 211 | return; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 212 | } | 
|  | 213 |  | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 214 | while (count) { | 
|  | 215 | unsigned int i; | 
|  | 216 | unsigned int lf; | 
|  | 217 | /* search for LF so we can insert CR if necessary */ | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 218 | for (i = 0, lf = 0 ; i < count ; i++) { | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 219 | if (*(buf + i) == 10) { | 
|  | 220 | lf = 1; | 
|  | 221 | i++; | 
|  | 222 | break; | 
|  | 223 | } | 
|  | 224 | } | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 225 | /* pass on to the driver specific version of this function if | 
|  | 226 | it is available */ | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 227 | if (serial->type->write) | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 228 | retval = serial->type->write(NULL, port, buf, i); | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 229 | else | 
| Alan Cox | 95da310 | 2008-07-22 11:09:07 +0100 | [diff] [blame] | 230 | retval = usb_serial_generic_write(NULL, port, buf, i); | 
| Harvey Harrison | 441b62c | 2008-03-03 16:08:34 -0800 | [diff] [blame] | 231 | dbg("%s - return value : %d", __func__, retval); | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 232 | if (lf) { | 
|  | 233 | /* append CR after LF */ | 
|  | 234 | unsigned char cr = 13; | 
|  | 235 | if (serial->type->write) | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 236 | retval = serial->type->write(NULL, | 
|  | 237 | port, &cr, 1); | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 238 | else | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 239 | retval = usb_serial_generic_write(NULL, | 
|  | 240 | port, &cr, 1); | 
| Harvey Harrison | 441b62c | 2008-03-03 16:08:34 -0800 | [diff] [blame] | 241 | dbg("%s - return value : %d", __func__, retval); | 
| Paul Fulghum | c10746d | 2006-04-13 22:26:35 +0200 | [diff] [blame] | 242 | } | 
|  | 243 | buf += i; | 
|  | 244 | count -= i; | 
|  | 245 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 246 | } | 
|  | 247 |  | 
| Kevin Hao | 39efd19 | 2009-01-02 13:44:34 +0000 | [diff] [blame] | 248 | static struct tty_driver *usb_console_device(struct console *co, int *index) | 
|  | 249 | { | 
|  | 250 | struct tty_driver **p = (struct tty_driver **)co->data; | 
|  | 251 |  | 
|  | 252 | if (!*p) | 
|  | 253 | return NULL; | 
|  | 254 |  | 
|  | 255 | *index = co->index; | 
|  | 256 | return *p; | 
|  | 257 | } | 
|  | 258 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 259 | static struct console usbcons = { | 
|  | 260 | .name =		"ttyUSB", | 
|  | 261 | .write =	usb_console_write, | 
| Kevin Hao | 39efd19 | 2009-01-02 13:44:34 +0000 | [diff] [blame] | 262 | .device =	usb_console_device, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 263 | .setup =	usb_console_setup, | 
|  | 264 | .flags =	CON_PRINTBUFFER, | 
|  | 265 | .index =	-1, | 
| Kevin Hao | 39efd19 | 2009-01-02 13:44:34 +0000 | [diff] [blame] | 266 | .data = 	&usb_serial_tty_driver, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 267 | }; | 
|  | 268 |  | 
| Guennadi Liakhovetski | 73e487f | 2006-04-25 07:46:17 +0200 | [diff] [blame] | 269 | void usb_serial_console_disconnect(struct usb_serial *serial) | 
|  | 270 | { | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 271 | if (serial && serial->port && serial->port[0] | 
|  | 272 | && serial->port[0] == usbcons_info.port) { | 
| Guennadi Liakhovetski | 73e487f | 2006-04-25 07:46:17 +0200 | [diff] [blame] | 273 | usb_serial_console_exit(); | 
|  | 274 | usb_serial_put(serial); | 
|  | 275 | } | 
|  | 276 | } | 
|  | 277 |  | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 278 | void usb_serial_console_init(int serial_debug, int minor) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 279 | { | 
|  | 280 | debug = serial_debug; | 
|  | 281 |  | 
|  | 282 | if (minor == 0) { | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 283 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 | * Call register_console() if this is the first device plugged | 
|  | 285 | * in.  If we call it earlier, then the callback to | 
|  | 286 | * console_setup() will fail, as there is not a device seen by | 
|  | 287 | * the USB subsystem yet. | 
|  | 288 | */ | 
|  | 289 | /* | 
|  | 290 | * Register console. | 
|  | 291 | * NOTES: | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 292 | * console_setup() is called (back) immediately (from | 
|  | 293 | * register_console). console_write() is called immediately | 
|  | 294 | * from register_console iff CON_PRINTBUFFER is set in flags. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 295 | */ | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 296 | dbg("registering the USB serial console."); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 297 | register_console(&usbcons); | 
|  | 298 | } | 
|  | 299 | } | 
|  | 300 |  | 
| Alan Cox | 4dbd5a0 | 2008-07-22 11:09:57 +0100 | [diff] [blame] | 301 | void usb_serial_console_exit(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 302 | { | 
| Guennadi Liakhovetski | 73e487f | 2006-04-25 07:46:17 +0200 | [diff] [blame] | 303 | if (usbcons_info.port) { | 
|  | 304 | unregister_console(&usbcons); | 
| Jason Wessel | 6e40612 | 2009-06-22 11:32:20 -0500 | [diff] [blame] | 305 | usbcons_info.port->console = 0; | 
| Guennadi Liakhovetski | 73e487f | 2006-04-25 07:46:17 +0200 | [diff] [blame] | 306 | usbcons_info.port = NULL; | 
|  | 307 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 308 | } | 
|  | 309 |  |