📄 usbserial.c
字号:
port = &serial->port[i]; if (port->interrupt_in_urb) usb_free_urb (port->interrupt_in_urb); if (port->interrupt_in_buffer) kfree (port->interrupt_in_buffer); } /* return the minor range that this device had */ return_serial (serial); /* free up any memory that we allocated */ kfree (serial); return NULL;}static void usb_serial_disconnect(struct usb_device *dev, void *ptr){ struct usb_serial *serial = (struct usb_serial *) ptr; struct usb_serial_port *port; int i; dbg(__FUNCTION__); if (serial) { /* fail all future close/read/write/ioctl/etc calls */ for (i = 0; i < serial->num_ports; ++i) { port = &serial->port[i]; down (&port->sem); if (port->tty != NULL) { while (port->open_count > 0) { __serial_close(port, NULL); } port->tty->driver_data = NULL; } up (&port->sem); } serial->dev = NULL; serial_shutdown (serial); for (i = 0; i < serial->num_ports; ++i) serial->port[i].open_count = 0; for (i = 0; i < serial->num_bulk_in; ++i) { port = &serial->port[i]; if (port->read_urb) { usb_unlink_urb (port->read_urb); usb_free_urb (port->read_urb); } if (port->bulk_in_buffer) kfree (port->bulk_in_buffer); } for (i = 0; i < serial->num_bulk_out; ++i) { port = &serial->port[i]; if (port->write_urb) { usb_unlink_urb (port->write_urb); usb_free_urb (port->write_urb); } if (port->bulk_out_buffer) kfree (port->bulk_out_buffer); } for (i = 0; i < serial->num_interrupt_in; ++i) { port = &serial->port[i]; if (port->interrupt_in_urb) { usb_unlink_urb (port->interrupt_in_urb); usb_free_urb (port->interrupt_in_urb); } if (port->interrupt_in_buffer) kfree (port->interrupt_in_buffer); } for (i = 0; i < serial->num_ports; ++i) { tty_unregister_devfs (&serial_tty_driver, serial->port[i].number); info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->port[i].number); } /* return the minor range that this device had */ return_serial (serial); /* free up any memory that we allocated */ kfree (serial); } else { info("device disconnected"); }}static struct tty_driver serial_tty_driver = { magic: TTY_DRIVER_MAGIC, driver_name: "usb-serial", name: "usb/tts/%d", major: SERIAL_TTY_MAJOR, minor_start: 0, num: SERIAL_TTY_MINORS, type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, refcount: &serial_refcount, table: serial_tty, termios: serial_termios, termios_locked: serial_termios_locked, open: serial_open, close: serial_close, write: serial_write, write_room: serial_write_room, ioctl: serial_ioctl, set_termios: serial_set_termios, throttle: serial_throttle, unthrottle: serial_unthrottle, break_ctl: serial_break, chars_in_buffer: serial_chars_in_buffer, read_proc: serial_read_proc,};static int __init usb_serial_init(void){ int i; int result; /* Initalize our global data */ for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } /* register the tty driver */ serial_tty_driver.init_termios = tty_std_termios; serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; if (tty_register_driver (&serial_tty_driver)) { err(__FUNCTION__ " - failed to register tty driver"); return -1; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { tty_unregister_driver(&serial_tty_driver); err("usb_register failed for the usb-serial driver. Error number %d", result); return -1; }#ifdef CONFIG_USB_SERIAL_GENERIC generic_device_ids[0].idVendor = vendor; generic_device_ids[0].idProduct = product; generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ usb_serial_register (&generic_device);#endif info(DRIVER_DESC " " DRIVER_VERSION); return 0;}static void __exit usb_serial_exit(void){#ifdef CONFIG_USB_SERIAL_CONSOLE unregister_console(&usbcons);#endif#ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ usb_serial_deregister (&generic_device);#endif usb_deregister(&usb_serial_driver); tty_unregister_driver(&serial_tty_driver);}module_init(usb_serial_init);module_exit(usb_serial_exit);int usb_serial_register(struct usb_serial_device_type *new_device){ /* Add this device to our list of devices */ list_add(&new_device->driver_list, &usb_serial_driver_list); info ("USB Serial support registered for %s", new_device->name); usb_scan_devices(); return 0;}void usb_serial_deregister(struct usb_serial_device_type *device){ struct usb_serial *serial; int i; info("USB Serial deregistering driver %s", device->name); /* clear out the serial_table if the device is attached to a port */ for(i = 0; i < SERIAL_TTY_MINORS; ++i) { serial = serial_table[i]; if ((serial != NULL) && (serial->type == device)) { usb_driver_release_interface (&usb_serial_driver, serial->interface); usb_serial_disconnect (NULL, serial); } } list_del(&device->driver_list);}/* If the usb-serial core is built into the core, the usb-serial drivers need these symbols to load properly as modules. */EXPORT_SYMBOL(usb_serial_register);EXPORT_SYMBOL(usb_serial_deregister);#ifdef USES_EZUSB_FUNCTIONS EXPORT_SYMBOL(ezusb_writememory); EXPORT_SYMBOL(ezusb_set_reset);#endif#ifdef CONFIG_USB_SERIAL_CONSOLE/* * ------------------------------------------------------------ * 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. * ------------------------------------------------------------ */#if 0static kdev_t usb_console_device(struct console *co){ return MKDEV(SERIAL_TTY_MAJOR, co->index); /* TBD */}#endif/* * The parsing of the command line works exactly like the * serial.c code, except that the specifier is "ttyUSB" instead * of "ttyS". */static int __init 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 = 0; struct tty_struct *tty; struct termios *termios; dbg ("%s", __FUNCTION__); 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'); } /* build a cflag setting */ switch (baud) { case 1200: cflag |= B1200; break; case 2400: cflag |= B2400; break; case 4800: cflag |= B4800; break; case 19200: cflag |= B19200; break; case 38400: cflag |= B38400; break; case 57600: cflag |= B57600; break; case 115200: cflag |= B115200; break; case 9600: default: cflag |= B9600; /* * Set this to a sane value to prevent a divide error */ baud = 9600; break; } switch (bits) { case 7: cflag |= CS7; break; default: case 8: cflag |= CS8; break; } switch (parity) { case 'o': case 'O': cflag |= PARODD; break; case 'e': case 'E': cflag |= PARENB; break; } co->cflag = cflag; /* grab the first serial port that happens to be connected */ serial = get_serial_by_minor (0); if (serial_paranoia_check (serial, __FUNCTION__)) { /* no device is connected yet, sorry :( */ err ("No USB device connected to ttyUSB0"); return -ENODEV; } port = &serial->port[0]; down (&port->sem); port->tty = NULL; info->port = port; ++port->open_count; if (port->open_count == 1) { /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) retval = serial->type->open(port, NULL); else retval = generic_open(port, NULL); if (retval) port->open_count = 0; } up (&port->sem); if (retval) { err ("could not open USB console port"); return retval; } if (serial->type->set_termios) { /* build up a fake tty structure so that the open call has something * to look at to get the cflag value */ tty = kmalloc (sizeof (*tty), GFP_KERNEL); if (!tty) { err ("no more memory"); return -ENOMEM; } termios = kmalloc (sizeof (*termios), GFP_KERNEL); if (!termios) { err ("no more memory"); kfree (tty); return -ENOMEM; } memset (tty, 0x00, sizeof(*tty)); memset (termios, 0x00, sizeof(*termios)); termios->c_cflag = cflag; tty->termios = termios; port->tty = tty; /* set up the initial termios settings */ serial->type->set_termios(port, NULL); port->tty = NULL; kfree (termios); kfree (tty); } return retval;}static void usb_console_write(struct console *co, const char *buf, unsigned count){ static struct usbcons_info *info = &usbcons_info; struct usb_serial_port *port = info->port; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); int retval = -ENODEV; if (!serial || !port) return; if (count == 0) return; down (&port->sem); dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); if (!port->open_count) { dbg (__FUNCTION__ " - port not opened"); goto exit; } /* pass on to the driver specific version of this function if it is available */ if (serial->type->write) retval = serial->type->write(port, 0, buf, count); else retval = generic_write(port, 0, buf, count);exit: up (&port->sem); dbg("%s - return value (if we had one): %d", __FUNCTION__, retval);}#if 0/* * Receive character from the serial port */static int usb_console_wait_key(struct console *co){ static struct usbcons_info *info = &usbcons_info; int c = 0; dbg("%s", __FUNCTION__); /* maybe use generic_read_bulk_callback ??? */ return c;}#endifstatic struct console usbcons = { name: "ttyUSB", /* only [8] */ write: usb_console_write,#if 0 device: usb_console_device, /* TBD */ wait_key: usb_console_wait_key, /* TBD */#endif setup: usb_console_setup, flags: CON_PRINTBUFFER, index: -1,};#endif /* CONFIG_USB_SERIAL_CONSOLE *//* Module information */MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");#ifdef CONFIG_USB_SERIAL_GENERICMODULE_PARM(vendor, "h");MODULE_PARM_DESC(vendor, "User specified USB idVendor");MODULE_PARM(product, "h");MODULE_PARM_DESC(product, "User specified USB idProduct");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -