Linux的USB-Serial 代码跟踪

我们在Linux dev目录看到的ttyUSB*一系列的终端,这些读写在Linux底层是如何处理的呢?


首先看USB serial 核心层,kernel\drivers\usb\serial\usb-serial.c文件里面实现


static int __init usb_serial_init(void)
{
int i;
int result;


usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); //也是注册了tty设备
if (!usb_serial_tty_driver)
return -ENOMEM;


/* Initialize our global data */
for (i = 0; i < SERIAL_TTY_MINORS; ++i)
serial_table[i] = NULL;


result = bus_register(&usb_serial_bus_type);
if (result) {
printk(KERN_ERR "usb-serial: %s - registering bus driver "
      "failed\n", __func__);
goto exit_bus;
}


usb_serial_tty_driver->driver_name = "usbserial";
usb_serial_tty_driver->name = "ttyUSB";//子Linux终端下面看到的名字
usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
usb_serial_tty_driver->minor_start = 1;
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); //serial_ops 这函数操作集合,抽象了底层读写操作

result = tty_register_driver(usb_serial_tty_driver);
if (result) {
printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
      __func__);
goto exit_reg_driver;
}


/* register the USB driver */
result = usb_register(&usb_serial_driver);
if (result < 0) {
printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
      __func__);
goto exit_tty;
}


/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if (result < 0) {
printk(KERN_ERR "usb-serial: %s - registering generic "
      "driver failed\n", __func__);
goto exit_generic;
}


printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");


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:
printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
      __func__, result);
put_tty_driver(usb_serial_tty_driver);
return result;
}

serial_ops主要抽象了方法集合有:

static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
.hangup = serial_hangup,
.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,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
.get_icount = serial_get_icount,
.cleanup = serial_cleanup,
.install = serial_install,
.proc_fops = &serial_proc_fops,
};

我们来典型分析一下这个两个函数:

static int serial_write(struct tty_struct *tty, const unsigned char *buf,
int count)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;


if (port->serial->dev->state == USB_STATE_NOTATTACHED)
goto exit;


dbg("%s - port %d, %d byte(s)", __func__, port->number, count);


/* pass on to the driver specific version of this function */
retval = port->serial->type->write(tty, port, buf, count); //通过函数指针从这里write数据到底层
if (retval < 0)
retval = usb_translate_errors(retval);
exit:
return retval;
}

读函数对于tty设备来说比较,通过tty核心层的读缓存,底层往上送数据,tty层往上读,它们维护了一个缓冲队列

看接口serial_chars_in_buffer


static int serial_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);


/* if the device was unplugged then any remaining characters
  fell out of the connector ;) */
if (port->serial->disconnected)
return 0;
/* pass on to the driver specific version of this function */
return port->serial->type->chars_in_buffer(tty);
}

跑到这里USB serial核心层就算注册好接下来就是用一栗子来说明如何向核心层注册

看到kernel\drivers\usb\serial\opticon.c文件

static struct usb_driver opticon_driver = {
.name = "opticon",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.suspend = opticon_suspend,
.resume = opticon_resume,
.id_table = id_table,
};


static struct usb_serial_driver opticon_device = {
.driver = {
.owner = THIS_MODULE,
.name = "opticon",
},
.id_table = id_table,
.num_ports = 1,
.attach = opticon_startup,
.open = opticon_open,
.close = opticon_close,
.write = opticon_write,
.write_room = opticon_write_room,
.disconnect = opticon_disconnect,
.release = opticon_release,
.throttle = opticon_throttle,
.unthrottle = opticon_unthrottle,
.ioctl = opticon_ioctl,
.tiocmget = opticon_tiocmget,
.tiocmset = opticon_tiocmset,
};


static struct usb_serial_driver * const serial_drivers[] = {
&opticon_device, NULL
};

module_usb_serial_driver(opticon_driver, serial_drivers);

找到这个宏通过宏展开我们知道

/*
 * module_usb_serial_driver() - Helper macro for registering a USB Serial driver
 * @__usb_driver: usb_driver struct to register
 * @__serial_drivers: list of usb_serial drivers to register
 *
 * Helper macro for USB serial drivers which do not do anything special
 * in module init/exit. This eliminates a lot of boilerplate. Each
 * module may only use this macro once, and calling it replaces
 * module_init() and module_exit()
 *
 */
#define module_usb_serial_driver(__usb_driver, __serial_drivers) \
module_driver(__usb_driver, usb_serial_register_drivers, \
      usb_serial_deregister_drivers, __serial_drivers)


/**
 * module_driver() - Helper macro for drivers that don't do anything
 * special in module init/exit. This eliminates a lot of boilerplate.
 * Each module may only use this macro once, and calling it replaces
 * module_init() and module_exit().
 *
 * @__driver: driver name
 * @__register: register function for this driver type
 * @__unregister: unregister function for this driver type
 * @...: Additional arguments to be passed to __register and __unregister.
 *
 * Use this macro to construct bus specific macros for registering
 * drivers, and do not use it on its own.
 */
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

惊喜吧,看到这里,是那么亲切,是我们的module_init(__driver##_init); opticon_driver 是标准USB驱动接口,serial_drivers是USB serial标准的操作集合,有了这两个后,如何绑定他们在一起干活呢?


这个桥梁就是usb_serial_register_drivers,usb_serial_deregister_drivers一个是注册一个注销。

原型是

/**
 * usb_serial_register_drivers - register drivers for a usb-serial module
 * @udriver: usb_driver used for matching devices/interfaces
 * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
 *
 * Registers @udriver and all the drivers in the @serial_drivers array.
 * Automatically fills in the .no_dynamic_id and PM fields in @udriver and
 * the .usb_driver field in each serial driver.
 */
int usb_serial_register_drivers(struct usb_driver *udriver,
struct usb_serial_driver * const serial_drivers[])
{
int rc;
const struct usb_device_id *saved_id_table;
struct usb_serial_driver * const *sd;


/*
* udriver must be registered before any of the serial drivers,
* because the store_new_id() routine for the serial drivers (in
* bus.c) probes udriver.
*
* Performance hack: We don't want udriver to be probed until
* the serial drivers are registered, because the probe would
* simply fail for lack of a matching serial driver.
* Therefore save off udriver's id_table until we are all set.
*
* Suspend/resume support is implemented in the usb-serial core,
* so fill in the PM-related fields in udriver.
*/
saved_id_table = udriver->id_table;
udriver->id_table = NULL;


udriver->no_dynamic_id = 1;
udriver->supports_autosuspend = 1;
udriver->suspend = usb_serial_suspend;
udriver->resume = usb_serial_resume;
rc = usb_register(udriver);//注册标准USB驱动
if (rc)
return rc;


for (sd = serial_drivers; *sd; ++sd) {
(*sd)->usb_driver = udriver;
rc = usb_serial_register(*sd);//向USB serial 注册操作集合,也是就USBserial底层传递上来的指针opticon_device 
if (rc)
goto failed;
}


/* Now restore udriver's id_table and look for matches */
udriver->id_table = saved_id_table;
rc = driver_attach(&udriver->drvwrap.driver);
return 0;


 failed:
while (sd-- > serial_drivers)
usb_serial_deregister(*sd);
usb_deregister(udriver);
return rc;
}
EXPORT_SYMBOL_GPL(usb_serial_register_drivers);


/**
 * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
 * @udriver: usb_driver to unregister
 * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
 *
 * Deregisters @udriver and all the drivers in the @serial_drivers array.
 */
void usb_serial_deregister_drivers(struct usb_driver *udriver,
struct usb_serial_driver * const serial_drivers[])
{
for (; *serial_drivers; ++serial_drivers)
usb_serial_deregister(*serial_drivers);
usb_deregister(udriver);
}
EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);

到此USB serial层应用结束。我们在终端cat echo ttyUSB*这些终端的时候,就回调用到读写函数来。


你可能感兴趣的:(Linux内核)