您的位置:首页 > 运维架构 > Linux

Linux的USB-Serial 代码跟踪

2016-03-30 14:01 1061 查看
我们在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*这些终端的时候,就回调用到读写函数来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: