1、目前系统有4类串口设备 omap spi usb 4g,美一类都有自己的信息。需要统一到一个文件里
2、在D:\z_linux_picohood_project\board-support_xj\board-support\linux-4.4.x-mainline\linux-4.4.x-mainline\drivers\tty\serial\serial_core.c
添加自己的lsh_serial_uart_proc_fops
/*add by lsh*/ const struct file_operations lsh_serial_uart_proc_fops = { .owner = THIS_MODULE, .open = uart_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; EXPORT_SYMBOL_GPL(lsh_serial_uart_proc_fops);
3、在D:\z_linux_picohood_project\board-support_xj\board-support\linux-4.4.x-mainline\linux-4.4.x-mainline\fs\proc\proc_tty.c
添加proc_create_data("serial", 0, proc_tty_driver, &lsh_serial_uart_proc_fops, NULL);
void __init proc_tty_init(void) { if (!proc_mkdir("tty", NULL)) return; proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */ /* * /proc/tty/driver/serial reveals the exact character counts for * serial links which is just too easy to abuse for inferring * password lengths and inter-keystroke timings during password * entry. */ proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL); proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops); proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations); /*add by lsh*/ //proc_create("tty/driver/serial", 0, NULL, &lsh_serial_uart_proc_fops); proc_create_data("serial", 0, proc_tty_driver, &lsh_serial_uart_proc_fops, NULL); }
4、添加一个函数通过文件名找到对应的struct tty_driver函数
/*add by lsh*/ struct tty_driver * return_my_serial_proc_tty_driver(const char *name) { struct tty_driver *ttydrv; struct proc_dir_entry * file_dir; file_dir = pde_subdir_find(proc_tty_driver,name,strlen(name)); ttydrv = file_dir->data; return ttydrv; }
5、添加对应驱动的串口统计的数据打印到指定文件
/*add by lsh*/ static void serial_uart_line_info(struct seq_file *m, struct uart_driver *drv, int i, int disp_nr) { struct uart_state *state = drv->state + i; struct tty_port *port = &state->port; enum uart_pm_state pm_state; struct uart_port *uport = state->uart_port; char stat_buf[32]; unsigned int status; int mmio; if (!uport) return; mmio = uport->iotype >= UPIO_MEM; seq_printf(m, "%d: uart:%s %s%08llX irq:%d", disp_nr, mmio ? "OMAPSERI" : "MAX14830", mmio ? "mmio:0x" : "port:0x", mmio ? (unsigned long long)uport->mapbase : (unsigned long long)uport->iobase, uport->irq); if (uport->type == PORT_UNKNOWN) { seq_putc(m, '\n'); return; } if (capable(CAP_SYS_ADMIN)) { mutex_lock(&port->mutex); pm_state = state->pm_state; if (pm_state != UART_PM_STATE_ON) uart_change_pm(state, UART_PM_STATE_ON); spin_lock_irq(&uport->lock); status = uport->ops->get_mctrl(uport); spin_unlock_irq(&uport->lock); if (pm_state != UART_PM_STATE_ON) uart_change_pm(state, pm_state); mutex_unlock(&port->mutex); seq_printf(m, " tx:%d rx:%d", uport->icount.tx, uport->icount.rx); if (uport->icount.frame) seq_printf(m, " fe:%d", uport->icount.frame); if (uport->icount.parity) seq_printf(m, " pe:%d", uport->icount.parity); if (uport->icount.brk) seq_printf(m, " brk:%d", uport->icount.brk); if (uport->icount.overrun) seq_printf(m, " oe:%d", uport->icount.overrun); #define INFOBIT(bit, str) \ if (uport->mctrl & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) #define STATBIT(bit, str) \ if (status & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) stat_buf[0] = '\0'; stat_buf[1] = '\0'; INFOBIT(TIOCM_RTS, "|RTS"); STATBIT(TIOCM_CTS, "|CTS"); INFOBIT(TIOCM_DTR, "|DTR"); STATBIT(TIOCM_DSR, "|DSR"); STATBIT(TIOCM_CAR, "|CD"); STATBIT(TIOCM_RNG, "|RI"); if (stat_buf[0]) stat_buf[0] = ' '; seq_puts(m, stat_buf); } seq_putc(m, '\n'); #undef STATBIT #undef INFOBIT }
6、usb转串口的数据比较不一致,需要单独加显示函数
/* add by lsh*/ static int usb_serial_proc_show(struct seq_file *m,struct tty_driver *ttydrv,int i,int disp_nr) { struct tty_struct *tty; struct usb_serial *serial; struct usb_serial_port *port; char stat_buf[40]; unsigned int status; port = usb_serial_port_get_by_minor(i); if (port == NULL) return 0; serial = port->serial; /*******************************************************************************/ /*add by lsh */ seq_printf(m, "%d: uart:%s %s%08X irq:%d", disp_nr,module_name(serial->type->driver.owner), "port:0x", (unsigned int)port, 183); seq_printf(m, " tx:%d rx:%d", port->icount.tx, port->icount.rx); if (port->icount.frame) seq_printf(m, " fe:%d", port->icount.frame); if (port->icount.parity) seq_printf(m, " pe:%d", port->icount.parity); if (port->icount.brk) seq_printf(m, " brk:%d", port->icount.brk); if (port->icount.overrun) seq_printf(m, " oe:%d", port->icount.overrun); seq_printf(m, " DSR|", port->icount.overrun); seq_printf(m, "CD", port->icount.overrun); /* tty = tty_port_tty_get(&port->port); status = serial->type->tiocmget(tty); //kernel null pointer #define STATBIT(bit, str) \ if (status & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) stat_buf[0] = '\0'; stat_buf[1] = '\0'; STATBIT(TIOCM_RTS, "|RTS"); STATBIT(TIOCM_CTS, "|CTS"); STATBIT(TIOCM_DTR, "|DTR"); STATBIT(TIOCM_DSR, "|DSR"); STATBIT(TIOCM_CAR, "|CD"); STATBIT(TIOCM_RNG, "|RI"); if (stat_buf[0]) stat_buf[0] = ' '; seq_puts(m, stat_buf); */ seq_putc(m, '\n'); /*******************************************************************************/ usb_serial_put(serial); mutex_unlock(&serial->disc_mutex); #undef STATBIT }
7、usb需要通过此设备号,获取当前的串口号,需要将改函数导出usb_serial_port_get_by_minor
D:\z_linux_picohood_project\board-support_xj\board-support\linux-4.4.x-mainline\linux-4.4.x-mainline\drivers\usb\serial\usb-serial.c
struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor) { struct usb_serial *serial; struct usb_serial_port *port; mutex_lock(&table_lock); port = idr_find(&serial_minors, minor); if (!port) goto exit; serial = port->serial; mutex_lock(&serial->disc_mutex); if (serial->disconnected) { mutex_unlock(&serial->disc_mutex); port = NULL; } else { kref_get(&serial->kref); } exit: mutex_unlock(&table_lock); return port; } /*add by lsh*/ EXPORT_SYMBOL_GPL(usb_serial_port_get_by_minor);
8、usb串口要配置一个文件名,才会在、/proc/tty/driver/ 下生成 usbseriver文件,其他的文件都是在对应驱动注册时。加入了配置
D:\z_linux_picohood_project\board-support_xj\board-support\linux-4.4.x-mainline\linux-4.4.x-mainline\drivers\usb\serial\usb-serial.c
static int __init usb_serial_init(void) { int result; usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS); if (!usb_serial_tty_driver) return -ENOMEM; /* Initialize our global data */ result = bus_register(&usb_serial_bus_type); if (result) { pr_err("%s - registering bus driver failed\n", __func__); goto exit_bus; } usb_serial_tty_driver->driver_name = "usbserial"; usb_serial_tty_driver->name = "ttyUSB"; usb_serial_tty_driver->major = USB_SERIAL_TTY_MAJOR; usb_serial_tty_driver->minor_start = 0; usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; usb_serial_tty_driver->init_termios = tty_std_termios; usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; usb_serial_tty_driver->init_termios.c_ispeed = 9600; usb_serial_tty_driver->init_termios.c_ospeed = 9600; tty_set_operations(usb_serial_tty_driver, &serial_ops); result = tty_register_driver(usb_serial_tty_driver); if (result) { pr_err("%s - tty_register_driver failed\n", __func__); goto exit_reg_driver; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { pr_err("%s - usb_register failed\n", __func__); goto exit_tty; } /* register the generic driver, if we should */ result = usb_serial_generic_register(); if (result < 0) { pr_err("%s - registering generic driver failed\n", __func__); goto exit_generic; } return result; exit_generic: usb_deregister(&usb_serial_driver); exit_tty: tty_unregister_driver(usb_serial_tty_driver); exit_reg_driver: bus_unregister(&usb_serial_bus_type); exit_bus: pr_err("%s - returning with error %d\n", __func__, result); put_tty_driver(usb_serial_tty_driver); return result; }