// SPDX-License-Identifier: GPL-2.0 /* * USB Serial Console driver * * Copyright (C) 2001 - 2002 Greg Kroah-Hartman (greg@kroah.com) * * Thanks to Randy Dunlap for the original version of this code. *
*/
/* * ------------------------------------------------------------ * USB Serial console driver * * Much of the code here is copied from drivers/char/serial.c * and implements a phony serial console in the same way that * serial.c does so that in case some software queries it, * it will get the same results. * * Things that are different from the way the serial port code * does things, is that we call the lower level usb-serial * driver code to initialize the device, and we set the initial * console speeds based on the command line arguments. * ------------------------------------------------------------
*/
/* * The parsing of the command line works exactly like the * serial.c code, except that the specifier is "ttyUSB" instead * of "ttyS".
*/ staticint usb_console_setup(struct console *co, char *options)
{ struct usbcons_info *info = &usbcons_info; int baud = 9600; int bits = 8; int parity = 'n'; int doflow = 0; int cflag = CREAD | HUPCL | CLOCAL; char *s; struct usb_serial *serial; struct usb_serial_port *port; int retval; struct tty_struct *tty = NULL; struct ktermios dummy;
if (options) {
baud = simple_strtoul(options, NULL, 10);
s = options; while (*s >= '0' && *s <= '9')
s++; if (*s)
parity = *s++; if (*s)
bits = *s++ - '0'; if (*s)
doflow = (*s++ == 'r');
}
/* * no need to check the index here: if the index is wrong, console * code won't call us
*/
port = usb_serial_port_get_by_minor(co->index); if (port == NULL) { /* no device is connected yet, sorry :( */
pr_err("No USB device connected to ttyUSB%i\n", co->index); return -ENODEV;
}
serial = port->serial;
retval = usb_autopm_get_interface(serial->interface); if (retval) goto error_get_interface;
tty_port_tty_set(&port->port, NULL);
info->port = port;
++port->port.count; if (!tty_port_initialized(&port->port)) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize * the termios structure, then later call set_termios to * configure according to command line arguments
*/
tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) {
retval = -ENOMEM; goto reset_open_count;
}
kref_init(&tty->kref);
tty->driver = usb_serial_tty_driver;
tty->index = co->index;
init_ldsem(&tty->ldisc_sem);
spin_lock_init(&tty->files_lock);
INIT_LIST_HEAD(&tty->tty_files);
kref_get(&tty->driver->kref);
__module_get(tty->driver->owner);
tty->ops = &usb_console_fake_tty_ops;
tty_init_termios(tty);
tty_port_tty_set(&port->port, tty);
}
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(NULL, port); if (retval) {
dev_err(&port->dev, "could not open USB console port\n"); goto fail;
}
tty_port_tty_set(&port->port, NULL);
tty_save_termios(tty);
tty_kref_put(tty);
}
tty_port_set_initialized(&port->port, true);
} /* Now that any required fake tty operations are completed restore
* the tty port count */
--port->port.count; /* The console is special in terms of closing the device so
* indicate this port is now acting as a system console. */
port->port.console = 1;
if (!port->port.console) {
dev_dbg(&port->dev, "%s - port not opened\n", __func__); return;
}
while (count) { unsignedint i; unsignedint lf; /* search for LF so we can insert CR if necessary */ for (i = 0, lf = 0 ; i < count ; i++) { if (*(buf + i) == 10) {
lf = 1;
i++; break;
}
} /* pass on to the driver specific version of this function if
it is available */
retval = serial->type->write(NULL, port, buf, i);
dev_dbg(&port->dev, "%s - write: %d\n", __func__, retval); if (lf) { /* append CR after LF */ unsignedchar cr = 13;
retval = serial->type->write(NULL, port, &cr, 1);
dev_dbg(&port->dev, "%s - write cr: %d\n",
__func__, retval);
}
buf += i;
count -= i;
}
}
void usb_serial_console_init(int minor)
{ if (minor == 0) { /* * Call register_console() if this is the first device plugged * in. If we call it earlier, then the callback to * console_setup() will fail, as there is not a device seen by * the USB subsystem yet.
*/ /* * Register console. * NOTES: * console_setup() is called (back) immediately (from * register_console). console_write() is called immediately * from register_console iff CON_PRINTBUFFER is set in flags.
*/
pr_debug("registering the USB serial console.\n");
register_console(&usbcons);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.