1. 前言
...
2. 流程图
3. usb serial源码分析
3.1 usb serial驱动加载
module_init(usb_serial_init);
module_exit(usb_serial_exit);
3.2 usb serial初始化
static int __init usb_serial_init(void)
{
int i;
int result;
usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); //分配一个usb tty driver结构体
if (!usb_serial_tty_driver)
return -ENOMEM;
/* Initialize our global data */
for (i = 0; i < SERIAL_TTY_MINORS; ++i) //为tty次设备usb-serial结构体初始化,在usb口热插拔创建设备/dev/ttyUSBx时就会使用一个serial_table[x]
serial_table[i] = NULL;
result = bus_register(&usb_serial_bus_type); //"usb-serial"总线注册
if (result) {
pr_err("%s - registering bus driver failed\n", __func__);
goto exit_bus;
}
usb_serial_tty_driver->driver_name = "usbserial"; //以下是初始化tty 核心层,包括设备名、驱动名
usb_serial_tty_driver->name = "ttyUSB";
usb_serial_tty_driver->major = 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); //绑定tty核心层的操作句柄
result = tty_register_driver(usb_serial_tty_driver); //tty驱动注册
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); //usb驱动注册
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;
}
usb_serial_init()初始化函数主要包括如下几个重要部分:
1> 动态分配一个tty驱动,usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
2> "usb-serial"总线注册,result = bus_register(&usb_serial_bus_type);
3> tty驱动注册,result = tty_register_driver(usb_serial_tty_driver);
4> usb串口驱动注册,result = usb_register(&usb_serial_driver);
下面逐个分析...
3.3 动态分配一个tty驱动结构体
usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); //SERIAL_TTY_MINORS为254
if (!usb_serial_tty_driver)
return -ENOMEM;
static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
{
struct tty_driver *ret = tty_alloc_driver(lines, 0);
if (IS_ERR(ret))
return NULL;
return ret;
}
#define tty_alloc_driver(lines, flags) \
__tty_alloc_driver(lines, THIS_MODULE, flags)
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
unsigned long flags)
{
struct tty_driver *driver;
unsigned int cdevs = 1;
int err;
if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
return ERR_PTR(-EINVAL);
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); //动态分配一个tty_driver内存空间
if (!driver)
return ERR_PTR(-ENOMEM);
kref_init(&driver->kref);
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines; //绑定tty_driver驱动个数
driver->owner = owner;
driver->flags = flags; //flags=0
if (!(flags & TTY_DRIVER_DEVPTS_MEM)) { //条件成立
driver->ttys = kcalloc(lines, sizeof(*driver->ttys), //分配lines个tty_struct设备
GFP_KERNEL);
driver->termios = kcalloc(lines, sizeof(*driver->termios), //分配lines个ktermios内核终端输入、输出配置
GFP_KERNEL);
if (!driver->ttys || !driver->termios) {
err = -ENOMEM;
goto err_free_all;
}
}
if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) { //条件成立
driver->ports = kcalloc(lines, sizeof(*driver->ports), //分配lines个tty_port结构体
GFP_KERNEL);
if (!driver->ports) {
err = -ENOMEM;
goto err_free_all;
}
cdevs = lines; //初始化字符设备的个数
}
driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL); //分配lines个cedv字符设备
if (!driver->cdevs) {
err = -ENOMEM;
goto err_free_all;
}
return driver;
err_free_all:
kfree(driver->ports);
kfree(driver->ttys);
kfree(driver->termios);
kfree(driver);
return ERR_PTR(err);
}
EXPORT_SYMBOL(__tty_alloc_driver);
3.4 “usb-serial”总线注册
struct bus_type usb_serial_bus_type = {
.name = "usb-serial", //总线名称
.match = usb_serial_device_match, //总线上驱动和设备匹配接口
.probe = usb_serial_device_probe, //匹配成功调用的探测接口
.remove = usb_serial_device_remove,
.drv_attrs = drv_attrs,
};
result = bus_register(&usb_serial_bus_type);
if (result) {
pr_err("%s - registering bus driver failed\n", __func__);
goto exit_bus;
}
int bus_register(struct bus_type *bus)
{
int retval;
struct subsys_private *priv;
struct lock_class_key *key = &bus->lock_key;
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); //分配一个内核对象子系统
if (!priv)
return -ENOMEM;
priv->bus = bus; //初始化子系统的当前总线
bus->p = priv; //绑定当前总线的子系统
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); //初始化一个阻塞通知链
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); //给当前子系统的内核对象命名
if (retval)
goto out;
priv->subsys.kobj.kset = bus_kset; //初始化当前子系统的父内核集合为bus_kset
priv->subsys.kobj.ktype = &bus_ktype; //初始化当前子系统内核对象属性(内核对象属性就是表示对文件的操作)
priv->drivers_autoprobe = 1; //设置设备和驱动匹配为自动,即从总线上获取对应相同的名称
retval = kset_register(&priv->subsys); //子系统内核集合初始化
if (retval)
goto out;
retval = bus_create_file(bus, &bus_attr_uevent); //创建当前总线的事件属性文件
if (retval)
goto bus_uevent_fail;
priv->devices_kset = kset_create_and_add("devices", NULL, //创建当前总线的“设备”内核集合,即该总线下的设备都把它作为父集合对象
&priv->subsys.kobj);
if (!priv->devices_kset) {
retval = -ENOMEM;
goto bus_devices_fail;
}
priv->drivers_kset = kset_create_and_add("drivers", NULL, //创建当前总线下的“驱动”内核集合,即该总线下的驱动都把它作为集合对象
&priv->subsys.kobj);
if (!priv->drivers_kset) {
retval = -ENOMEM;
goto bus_drivers_fail;
}
INIT_LIST_HEAD(&priv->interfaces); //初始化接口链表
__mutex_init(&priv->mutex, "subsys mutex", key); //初始化子系统互斥锁
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); //创建一个设备链表,即当前总线下的设备都挂接在该链表上
klist_init(&priv->klist_drivers, NULL, NULL); //创建一个驱动链表,即当前总线下的驱动都挂接在该链表上
retval = add_probe_files(bus); //增加当前总线的属性文件(如driver_auto_probe、drivers_probe)到sys文件系统
if (retval)
goto bus_probe_files_fail;
retval = bus_add_attrs(bus); //为当前总线增加属性文件
if (retval)
goto bus_attrs_fail;
pr_debug("bus: '%s': registered\n", bus->name);
return 0;
bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
out:
kfree(bus->p);
bus->p = NULL;
return retval;
}
EXPORT_SYMBOL_GPL(bus_register);
3.5 tty驱动注册
usb_serial_tty_driver->driver_name = "usbserial"; //设置驱动名称,在总线上用来与设备相匹配
usb_serial_tty_driver->name = "ttyUSB"; //初始化tty设备的名称
usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; //tty主设备号188
usb_serial_tty_driver->minor_start = 0; //次设备的起始值为0,表示动态分配次设备
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; //tty驱动类型为串口(tty的类型有很多,如console、pty...)
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; //tty驱动子类型
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); //绑定tty操作集,即tty核心层的接口
result = tty_register_driver(usb_serial_tty_driver); //tty驱动注册
if (result) {
pr_err("%s - tty_register_driver failed\n", __func__);
goto exit_reg_driver;
}
tty核心层操作接口:
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,
.wait_until_sent = serial_wait_until_sent,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
.get_icount = serial_get_icount,
.cleanup = serial_cleanup,
.install = serial_install,
.proc_fops = &serial_proc_fops,
};
result = tty_register_driver(usb_serial_tty_driver);
int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
dev_t dev;
struct device *d;
if (!driver->major) { //major=188
error = alloc_chrdev_region(&dev, driver->minor_start,
driver->num, driver->name);
if (!error) {
driver->major = MAJOR(dev);
driver->minor_start = MINOR(dev);
}
} else {
dev = MKDEV(driver->major, driver->minor_start); //创建主、次设备号
error = register_chrdev_region(dev, driver->num, driver->name); //注册num个字符设备
}
if (error < 0)
goto err;
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) {
error = tty_cdev_add(driver, dev, 0, driver->num); //tty字符设备增加(会绑定tty_io层的操作集),这个函数内部详见下面
if (error)
goto err_unreg_char;
}
mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers); //将当前驱动加入到全局链表tty_drivers
mutex_unlock(&tty_mutex);
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
for (i = 0; i < driver->num; i++) {
d = tty_register_device(driver, i, NULL); //注册tty字符设备
if (IS_ERR(d)) {
error = PTR_ERR(d);
goto err_unreg_devs;
}
}
}
proc_tty_register_driver(driver); //tty proc文件系统注册
driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
err_unreg_devs:
for (i--; i >= 0; i--)
tty_unregister_device(driver, i);
mutex_lock(&tty_mutex);
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);
err_unreg_char:
unregister_chrdev_region(dev, driver->num);
err:
return error;
}
EXPORT_SYMBOL(tty_register_driver);
字符设备增加:
error = tty_cdev_add(driver, dev, 0, driver->num);
static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
unsigned int index, unsigned int count)
{
/* init here, since reused cdevs cause crashes */
cdev_init(&driver->cdevs[index], &tty_fops); //绑定tty_io层的操作集
driver->cdevs[index].owner = driver->owner;
return cdev_add(&driver->cdevs[index], dev, count);
}
static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};
这个是文件操作集合,对应系统调用的第一层。
3.6 usb驱动注册
static struct usb_driver usb_serial_driver = {
.name = "usbserial", //驱动名称
.probe = usb_serial_probe, //驱动探测接口
.disconnect = usb_serial_disconnect,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
.no_dynamic_id = 1,
.supports_autosuspend = 1,
};
result = usb_register(&usb_serial_driver);
#define usb_register(driver) \
usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
const char *mod_name)
{
int retval = 0;
if (usb_disabled())
return -ENODEV;
new_driver->drvwrap.for_devices = 0;
new_driver->drvwrap.driver.name = (char *) new_driver->name; //“usbserial”
new_driver->drvwrap.driver.bus = &usb_bus_type; //绑定总线为“usb”
new_driver->drvwrap.driver.probe = usb_probe_interface; //绑定接口
new_driver->drvwrap.driver.remove = usb_unbind_interface;
new_driver->drvwrap.driver.owner = owner;
new_driver->drvwrap.driver.mod_name = mod_name;
spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->drvwrap.driver); //驱动注册
if (retval)
goto out;
retval = usb_create_newid_files(new_driver);
if (retval)
goto out_newid;
pr_info("%s: registered new interface driver %s\n",
usbcore_name, new_driver->name);
out:
return retval;
out_newid:
driver_unregister(&new_driver->drvwrap.driver);
printk(KERN_ERR "%s: error %d registering interface "
" driver %s\n",
usbcore_name, retval, new_driver->name);
goto out;
}
EXPORT_SYMBOL_GPL(usb_register_driver);
至此,就完成了"usb-serial"的总线注册,usb tty(254个tty【ttyUSBx】)驱动"usbserial"的注册,usb串口驱动"usbserial"注册。