int gserial_alloc_line(unsigned char *line_num) { struct usb_cdc_line_coding coding; struct device *tty_dev; int ret; int port_num; coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; for (port_num = 0; port_num < MAX_U_SERIAL_PORTS; port_num++) { ret = gs_port_alloc(port_num, &coding); if (ret == -EBUSY) continue; if (ret) return ret; break; } if (ret) return ret; /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ tty_dev = tty_port_register_device(&ports[port_num].port->port, gs_tty_driver, port_num, NULL); if (IS_ERR(tty_dev)) { struct gs_port *port; pr_err("%s: failed to register tty for port %d, err %ld\n", __func__, port_num, PTR_ERR(tty_dev)); ret = PTR_ERR(tty_dev); port = ports[port_num].port; ports[port_num].port = NULL; gserial_free_port(port); goto err; } *line_num = port_num; err: return ret; }
/** * gserial_setup - initialize TTY driver for one or more ports * @g: gadget to associate with these ports * @count: how many ports to support * Context: may sleep * * The TTY stack needs to know in advance how many devices it should * plan to manage. Use this call to set up the ports you will be * exporting through USB. Later, connect them to functions based * on what configuration is activated by the USB host; and disconnect * them as appropriate. * * An example would be a two-configuration device in which both * configurations expose port 0, but through different functions. * One configuration could even expose port 1 while the other * one doesn't. * * Returns negative errno or zero. */ int gserial_setup(struct usb_gadget *g, unsigned count) { unsigned i; struct usb_cdc_line_coding coding; int status; if (count == 0 || count > N_PORTS) return -EINVAL; gs_tty_driver = alloc_tty_driver(count); if (!gs_tty_driver) return -ENOMEM; gs_tty_driver->driver_name = "g_serial"; gs_tty_driver->name = PREFIX; /* uses dynamically assigned dev_t values */ gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_RESET_TERMIOS; gs_tty_driver->init_termios = tty_std_termios; /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on * MS-Windows. Otherwise, most of these flags shouldn't affect * anything unless we were to actually hook up to a serial line. */ gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; tty_set_operations(gs_tty_driver, &gs_tty_ops); gserial_wq = create_singlethread_workqueue("k_gserial"); if (!gserial_wq) { status = -ENOMEM; goto fail; } /* make devices be openable */ for (i = 0; i < count; i++) { mutex_init(&ports[i].lock); status = gs_port_alloc(i, &coding); if (status) { count = i; goto fail; } } n_ports = count; /* export the driver ... */ status = tty_register_driver(gs_tty_driver); if (status) { pr_err("%s: cannot register, err %d\n", __func__, status); goto fail; } /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ for (i = 0; i < count; i++) { struct device *tty_dev; tty_dev = tty_register_device(gs_tty_driver, i, &g->dev); if (IS_ERR(tty_dev)) pr_warning("%s: no classdev for port %d, err %ld\n", __func__, i, PTR_ERR(tty_dev)); } for (i = 0; i < count; i++) usb_debugfs_init(ports[i].port, i); pr_debug("%s: registered %d ttyGS* device%s\n", __func__, count, (count == 1) ? "" : "s"); return status; fail: while (count--) kfree(ports[count].port); if (gserial_wq) destroy_workqueue(gserial_wq); put_tty_driver(gs_tty_driver); gs_tty_driver = NULL; return status; }
int gserial_setup(struct usb_gadget *g, unsigned count) { unsigned i; struct usb_cdc_line_coding coding; int status; if (count == 0 || count > N_PORTS) return -EINVAL; gs_tty_driver = alloc_tty_driver(count); if (!gs_tty_driver) return -ENOMEM; gs_tty_driver->owner = THIS_MODULE; gs_tty_driver->driver_name = "g_serial"; gs_tty_driver->name = PREFIX; gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_RESET_TERMIOS; gs_tty_driver->init_termios = tty_std_termios; gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; tty_set_operations(gs_tty_driver, &gs_tty_ops); gserial_wq = create_singlethread_workqueue("k_gserial"); if (!gserial_wq) { status = -ENOMEM; goto fail; } for (i = 0; i < count; i++) { mutex_init(&ports[i].lock); status = gs_port_alloc(i, &coding); if (status) { count = i; goto fail; } } n_ports = count; status = tty_register_driver(gs_tty_driver); if (status) { put_tty_driver(gs_tty_driver); pr_err("%s: cannot register, err %d\n", __func__, status); goto fail; } for (i = 0; i < count; i++) { struct device *tty_dev; tty_dev = tty_register_device(gs_tty_driver, i, &g->dev); if (IS_ERR(tty_dev)) pr_warning("%s: no classdev for port %d, err %ld\n", __func__, i, PTR_ERR(tty_dev)); } pr_debug("%s: registered %d ttyGS* device%s\n", __func__, count, (count == 1) ? "" : "s"); return status; fail: while (count--) kfree(ports[count].port); destroy_workqueue(gserial_wq); put_tty_driver(gs_tty_driver); gs_tty_driver = NULL; return status; }
int bsp_usb_console_init(void) { struct console* uart_console; struct usb_cdc_line_coding coding; int status = 0; /* alloc first tty driver for console */ gs_console_tty_driver = alloc_tty_driver(1); if (!gs_console_tty_driver) return -ENOMEM; gs_console_tty_driver->driver_name = "console_ser"; gs_console_tty_driver->name = g_acm_tty_type_table[ACM_CONSOLE_IDX].name; /* uses dynamically assigned dev_t values */ gs_console_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gs_console_tty_driver->subtype = SERIAL_TYPE_NORMAL; gs_console_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; gs_console_tty_driver->init_termios = tty_std_termios; /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on * MS-Windows. Otherwise, most of these flags shouldn't affect * anything unless we were to actually hook up to a serial line. */ gs_console_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; gs_console_tty_driver->init_termios.c_ispeed = 9600; gs_console_tty_driver->init_termios.c_ospeed = 9600; gs_console_tty_driver->num = 1; coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; tty_set_operations(gs_console_tty_driver, &gs_tty_ops); /* export the driver ... */ status = tty_register_driver(gs_console_tty_driver); if (status) { pr_err("%s: cannot register, err %d\n", __func__, status); goto console_init_fail; } mutex_init(&ports[0].lock); status = gs_port_alloc(0, &coding); if (status) { goto console_init_fail; } if (gs_acm_is_console_enable()) { /* reg from uart shell to usb shell */ uart_console = bsp_get_uart_console(); if (uart_console) { unregister_console(uart_console); } register_console(&gs_console); console_start(&gs_console); } return 0; console_init_fail: put_tty_driver(gs_console_tty_driver); return status; }
/** * gserial_setup - initialize TTY driver for one or more ports * @g: gadget to associate with these ports * @count: how many ports to support * Context: may sleep * * The TTY stack needs to know in advance how many devices it should * plan to manage. Use this call to set up the ports you will be * exporting through USB. Later, connect them to functions based * on what configuration is activated by the USB host; and disconnect * them as appropriate. * * An example would be a two-configuration device in which both * configurations expose port 0, but through different functions. * One configuration could even expose port 1 while the other * one doesn't. * * Returns negative errno or zero. */ int gserial_setup(struct usb_gadget *g, unsigned count) { unsigned i; struct usb_cdc_line_coding coding; int status; struct device *tty_dev; if (count == 0 || count > ACM_TTY_COUNT) return -EINVAL; /* count:0 is init in the bsp_usb_console_init */ if (count > 1) { gs_tty_driver = alloc_tty_driver(count-1); if (!gs_tty_driver) return -ENOMEM; gs_tty_driver->driver_name = "g_serial"; gs_tty_driver->name = PREFIX; /* uses dynamically assigned dev_t values */ gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; gs_tty_driver->init_termios = tty_std_termios; /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on * MS-Windows. Otherwise, most of these flags shouldn't affect * anything unless we were to actually hook up to a serial line. */ gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; gs_tty_driver->num = 1; coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; tty_set_operations(gs_tty_driver, &gs_tty_ops); /* export the driver ... */ status = tty_register_driver(gs_tty_driver); if (status) { pr_err("%s: cannot register, err %d\n", __func__, status); goto fail; } } /* make devices be openable */ for (i = 1; i < count; i++) { mutex_init(&ports[i].lock); status = gs_port_alloc(i, &coding); if (status) { count = i; goto fail; } } n_ports = count; /* 1. reg tty device for console tty */ tty_dev = tty_register_device(gs_console_tty_driver, 0, &g->dev); if (IS_ERR(tty_dev)) pr_warning("%s: no classdev for port %d, err %ld\n", __func__, 0, PTR_ERR(tty_dev)); /* 2. reg other tty ... */ /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ for (i = 1; i < count; i++) { //struct device *tty_dev; /* i-1 means index start from 0 */ tty_dev = tty_register_device(gs_tty_driver, i-1, &g->dev); if (IS_ERR(tty_dev)) pr_warning("%s: no classdev for port %d, err %ld\n", __func__, i, PTR_ERR(tty_dev)); } pr_vdebug("%s: registered %d ttyGS* device%s\n", __func__, count, (count == 1) ? "" : "s"); return status;/* [false alarm]:fortify disable */ fail: /* never free console tty port */ while (count-- > 1) kfree(ports[count].port); put_tty_driver(gs_tty_driver); gs_tty_driver = NULL; return status; }