在/proc/tty/driver/ 添加serial文件,来统计系统的串口设备的统计信息


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;
}

  

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM