以i2c总线接口的edt-ft5x06.c触摸屏驱动为例
static struct i2c_driver edt_ft5x06_ts_driver = { .driver = { .owner = THIS_MODULE, .name = "edt_ft5x06", .pm = &edt_ft5x06_ts_pm_ops, }, .id_table = edt_ft5x06_ts_id, .probe = edt_ft5x06_ts_probe, .remove = edt_ft5x06_ts_remove, };标准的驱动框架,主要字段的意义:
pm:电源管理睡眠唤醒时调用;
static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
include/linux/pm.h
#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ const struct dev_pm_ops name = { \ SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ }const struct dev_pm_ops edt_ft5x06_ts_pm_ops= {
#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ .suspend = suspend_fn, \ .resume = resume_fn, \ .freeze = suspend_fn, \ .thaw = resume_fn, \ .poweroff = suspend_fn, \ .restore = resume_fn,
相当于定义了const struct dev_pm_ops edt_ft5x06_ts_pm_ops= {
.resume = edt_ft5x06_ts_resum,
.suspend = edt_ft5x06_ts_suspend,
}
这样一个结构。
id_table:用于device和driver的匹配;
static const struct i2c_device_id edt_ft5x06_ts_id[] = { { "edt-ft5x06", 0 }, { } };
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
include/linux/module.h
#define MODULE_DEVICE_TABLE(type,name) \
MODULE_GENERIC_TABLE(type##_device,name)
上述宏展开为 MODULE_GENERIC_TABLE(i2c_device,edt_ft5x06_ts_id);
#define MODULE_GENERIC_TABLE(gtype,name) \ extern const struct gtype##_id __mod_##gtype##_table \ __attribute__ ((unused, alias(__stringify(name))))再展开为
remove:驱动卸载时执行。
module_i2c_driver(edt_ft5x06_ts_driver);include/linux/i2c.h
#define module_i2c_driver(__i2c_driver) \ module_driver(__i2c_driver, i2c_add_driver, \ i2c_del_driver)展开为module_driver(edt_ft5x06_ts_driver, i2c_add_driver, i2c_del_driver)
include/linux/device.h
#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_i2c_driver(edt_ft5x06_ts_driver);做了很多事情:
module_exit(edt_ft5x06_ts_driver_exit);
#define i2c_add_driver(driver) \ i2c_register_driver(THIS_MODULE, driver)
int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { int res; /* Can't register until after driver model init */ if (unlikely(WARN_ON(!i2c_bus_type.p))) return -EAGAIN; /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. */ res = driver_register(&driver->driver); if (res) return res; /* Drivers should switch to dev_pm_ops instead. */ if (driver->suspend) pr_warn("i2c-core: driver [%s] using legacy suspend method\n", driver->driver.name); if (driver->resume) pr_warn("i2c-core: driver [%s] using legacy resume method\n", driver->driver.name); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ i2c_for_each_dev(driver, __process_new_driver); return 0; }设置driver->driver.bus = &i2c_bus_type;
struct bus_type i2c_bus_type = { .name = "i2c", .match = i2c_device_match, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, .pm = &i2c_device_pm_ops, };
关键函数res = driver_register(&driver->driver);(在这个函数中会执行探测函数driver->probe),接着初始化driver->clients list,i2c_for_each_dev(driver, __process_new_driver);会遍历每个adapter执行i2c_detect、driver->attach_adapter(adap);将adapter和i2c_device的信息相关联,这个过程是双向的register adapter时也会走一遍;现在的driver一般不需要实现attach_adapter,基本被probe取代了。
int driver_register(struct device_driver *drv) { int ret; struct device_driver *other; BUG_ON(!drv->bus->p); if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) printk(KERN_WARNING "Driver '%s' needs updating - please use " "bus_type methods\n", drv->name); other = driver_find(drv->name, drv->bus); if (other) { printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting...\n", drv->name); return -EBUSY; } ret = bus_add_driver(drv); if (ret) return ret; ret = driver_add_groups(drv, drv->groups); if (ret) { bus_remove_driver(drv); return ret; } kobject_uevent(&drv->p->kobj, KOBJ_ADD); return ret; }这是所有driver的注册都要走的流程。先确认该driver没有被注册过,然后注册,添加sysfs接口,向用户空间发送uevent。
bus_add_driver()->driver_attach(drv)->__driver_attach()->driver_match_device()->i2c_match_id()
int driver_attach(struct device_driver *drv) { return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); }
遍历每个i2c device,match client->name, id->name;如果match成功i2c_match_id会返回id,driver_match_device返回1,如果该device没有绑定driver,__driver_attach继续执行driver_probe_device(drv, dev);->really_probe()->(dev->bus->probe(dev))->(drv->probe(dev));终于执行到probe了。really_probe中还会执行driver_bound(dev);
bus_add_driver()->klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);添加到bus->p->klist_drivers,那么register device执行bind的时候才能够遍历到。
static void driver_bound(struct device *dev) { if (klist_node_attached(&dev->p->knode_driver)) { printk(KERN_WARNING "%s: device %s already bound\n", __func__, kobject_name(&dev->kobj)); return; } pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), __func__, dev->driver->name); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); /* * Make sure the device is no longer in one of the deferred lists and * kick off retrying all pending devices */ driver_deferred_probe_del(dev); driver_deferred_probe_trigger(); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev); }主要是把dev->p->knode_driver添加到dev->driver->p->klist_devices上。
driver能够bound的前提是device已经建立了;如果没有建立呢?那就等到device建立的时候bound driver吧。
i2c_new_device()->device_register()->device_add(dev)->bus_add_device(dev)->klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices)添加到bus->p->klist_devices,那么register driver 执行bound的时候才能够遍历到。
device_add()->bus_probe_device()->device_attach()
int device_attach(struct device *dev) { int ret = 0; device_lock(dev); if (dev->driver) { if (klist_node_attached(&dev->p->knode_driver)) { ret = 1; goto out_unlock; } ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_idle(dev); } out_unlock: device_unlock(dev); return ret; }如果dev->driver已经存在了,判断是否执行了bind,没有执行,也会调用device_bind_driver()->driver_bound()执行bind;
否则
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);遍历每个i2c driver,__device_attach()->driver_match_device()同样是match,如果成功继续执行,driver_probe_device()->really_probe()。
总结:driver和device的bind过程是双向的;热插拔设备可以动态地bind driver。
void i2c_del_driver(struct i2c_driver *driver) { i2c_for_each_dev(driver, __process_removed_driver); driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); }遍历i2c device,执行__process_removed_driver()->i2c_do_del_adapter()->(driver->detach_adapter(adapter))解除对应关系。
void driver_unregister(struct device_driver *drv) { if (!drv || !drv->p) { WARN(1, "Unexpected driver unregister!\n"); return; } driver_remove_groups(drv, drv->groups); bus_remove_driver(drv); }remove sysfs接口,remove driver。
void bus_remove_driver(struct device_driver *drv) { if (!drv->bus) return; if (!drv->suppress_bind_attrs) remove_bind_files(drv); driver_remove_attrs(drv->bus, drv); driver_remove_file(drv, &driver_attr_uevent); klist_remove(&drv->p->knode_bus); pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name); driver_detach(drv); module_remove_driver(drv); kobject_put(&drv->p->kobj); bus_put(drv->bus); }
void driver_detach(struct device_driver *drv) { struct device_private *dev_prv; struct device *dev; for (;;) { spin_lock(&drv->p->klist_devices.k_lock); if (list_empty(&drv->p->klist_devices.k_list)) { spin_unlock(&drv->p->klist_devices.k_lock); break; } dev_prv = list_entry(drv->p->klist_devices.k_list.prev, struct device_private, knode_driver.n_node); dev = dev_prv->device; get_device(dev); spin_unlock(&drv->p->klist_devices.k_lock); if (dev->parent) /* Needed for USB */ device_lock(dev->parent); device_lock(dev); if (dev->driver == drv) __device_release_driver(dev); device_unlock(dev); if (dev->parent) device_unlock(dev->parent); put_device(dev); }}
drv->p->klist_devices.k_list.prev是对应&dev->p->knode_driver的list,是bound的时候加进去的;klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
通过这个list可以找到dev->p的p,即dev_prv;__device_release_driver()->devres_release_all()->klist_remove(&dev->p->knode_driver)->klist_del(n)->klist_put(n, true)->klist_dec_and_del()->klist_release()->list_del(&n->n_node);终于把自己给del了,所以drv->p->klist_devices.k_list.prev会自然向前移动,之前被删除list的前驱。用了for (;;)循环,保证drv->p->klist_devices.k_list全都删除,driver关联的每个dev都做del处理,一份driver可以对应多个device,每个device只能对应一个driver。如果dev->driver != drv,那__device_release_driver(dev);就不会执行drv->p->klist_devices.k_list.prev也不会移动了,岂不是死在看for循环了;drv->p->klist_devices.k_list挂的其实是deive,要保证不死循环,这个device对应的driver一定是bound的drvier,事实也是如此。
static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct edt_ft5x06_platform_data *pdata = client->dev.platform_data; struct input_dev *input; input = input_allocate_device(); if (!tsdata || !input) { dev_err(&client->dev, "failed to allocate driver data.\n"); error = -ENOMEM; goto err_free_mem; } input->name = tsdata->name; input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; __set_bit(EV_SYN, input->evbit); __set_bit(EV_KEY, input->evbit); __set_bit(EV_ABS, input->evbit); __set_bit(BTN_TOUCH, input->keybit); input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0); input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_X, 0, tsdata->num_x * 64 - 1, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, tsdata->num_y * 64 - 1, 0, 0); error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); if (error) { dev_err(&client->dev, "Unable to init MT slots.\n"); goto err_free_mem; } error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, error = input_register_device(input); if (error) goto err_remove_attrs; return 0; err_remove_attrs: sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); err_free_irq: free_irq(client->irq, tsdata); err_free_mem: input_free_device(input); kfree(tsdata); if (gpio_is_valid(pdata->irq_pin)) gpio_free(pdata->irq_pin); return error;input_dev结构代表一个具体的input设备,getevent –p可以查看到,如果用到idc文件,也可以根据这个name匹配。}
static inline void __set_bit(int nr, volatile unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); *p |= mask; } #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BITS_PER_LONG 32
int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); struct input_devres *devres = NULL; struct input_handler *handler; unsigned int packet_size; const char *path; int error; if (dev->devres_managed) { devres = devres_alloc(devm_input_device_unregister, sizeof(struct input_devres), GFP_KERNEL); if (!devres) return -ENOMEM; devres->input = dev; } /* Every input device generates EV_SYN/SYN_REPORT events. */ __set_bit(EV_SYN, dev->evbit); /* KEY_RESERVED is not supposed to be transmitted to userspace. */ __clear_bit(KEY_RESERVED, dev->keybit); /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); packet_size = input_estimate_events_per_packet(dev); if (dev->hint_events_per_packet < packet_size) dev->hint_events_per_packet = packet_size; dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); if (!dev->vals) { error = -ENOMEM; goto err_devres_free; } /* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. */ init_timer(&dev->timer); if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { dev->timer.data = (long) dev; dev->timer.function = input_repeat_key; dev->rep[REP_DELAY] = 250; dev->rep[REP_PERIOD] = 33; } if (!dev->getkeycode) dev->getkeycode = input_default_getkeycode; if (!dev->setkeycode) dev->setkeycode = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); error = device_add(&dev->dev); if (error) goto err_free_vals; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n", dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); error = mutex_lock_interruptible(&input_mutex); if (error) goto err_device_del; list_add_tail(&dev->node, &input_dev_list); list_for_each_entry(handler, &input_handler_list, node) input_attach_handler(dev, handler); input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); if (dev->devres_managed) { dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n", __func__, dev_name(&dev->dev)); devres_add(dev->dev.parent, devres); } return 0; err_device_del: device_del(&dev->dev); err_free_vals: kfree(dev->vals); dev->vals = NULL; err_devres_free: devres_free(devres); return error; }重新set了EV_SYN,因为么给input设备都要产生EV_SYN/SYN_REPORT事件,还要clear KEY_RESERVED,这个事件不允许传入到用户空间,是个保留事件。clean位掩码是说如果test出evbit[]中该type事件类型没有设置,那么相应位掩码对应的code事件编码就无效;自然需要清除了。比如说没有设置EV_KEY(这是一个type);那么keybit[]就清0了。hint_events_per_packet是一个packet里事件的平均值,被事件处理器用于估计hold event需要的buffer size。这个均值的计算分为几种情况,
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler) { const struct input_device_id *id; int error; id = input_match_device(handler, dev); if (!id) return -ENODEV; error = handler->connect(handler, dev, id); if (error && error != -ENODEV) pr_err("failed to attach handler %s to device %s, error: %d\n", handler->name, kobject_name(&dev->dev.kobj), error); return error; }
input_match_device()中根据handler->id_table(input_device_id)的设置与input device的设置进行匹配,触摸屏对应的handler是evdev..c。
static const struct input_device_id evdev_ids[] = { { .driver_info = 1 }, /* Matches all devices */ { }, /* Terminating zero entry */ };
static inline int bitmap_subset(const unsigned long *src1, const unsigned long *src2, int nbits) { if (small_const_nbits(nbits)) return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits)); else return __bitmap_subset(src1, src2, nbits); }
#define small_const_nbits(nbits) \ (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
做匹配时,主要是位图的匹配。例如:
bitmap_subset(id->absbit, dev->absbit, ABS_MAX);就是比较dev->absbit的设置与id->absbit设置是否完全一致,一致就算匹配成功。
__builtin_constant_p(x)gcc的内建函数,当x为常数时返回1, x为变量时返回0。常数是指编译时常数。int len = sizeof(struct ...);紧接着的__builtin_constant_p(len)返回值就是1,len虽然为变量,但编译时可确定其值。
走到最后要调用handler->match(handler, dev);貌似evdev.c没有实现这个match。
匹配成功就要进行连接了。
static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct evdev *evdev; int minor; int dev_no; int error; minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true); if (minor < 0) { error = minor; pr_err("failed to reserve new minor: %d\n", error); return error; } evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); if (!evdev) { error = -ENOMEM; goto err_free_minor; } INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); evdev->exist = true; dev_no = minor; /* Normalize device number if it falls into legacy range */ if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) dev_no -= EVDEV_MINOR_BASE; dev_set_name(&evdev->dev, "event%d", dev_no); evdev->handle.dev = input_get_device(dev); evdev->handle.name = dev_name(&evdev->dev); evdev->handle.handler = handler; evdev->handle.private = evdev; evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; device_initialize(&evdev->dev); error = input_register_handle(&evdev->handle); if (error) goto err_free_evdev; cdev_init(&evdev->cdev, &evdev_fops); evdev->cdev.kobj.parent = &evdev->dev.kobj; error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; error = device_add(&evdev->dev); if (error) goto err_cleanup_evdev; return 0; err_cleanup_evdev: evdev_cleanup(evdev); err_unregister_handle: input_unregister_handle(&evdev->handle); err_free_evdev: put_device(&evdev->dev); err_free_minor: input_free_minor(minor); return error; }为每个匹配的设备,分配一个evdev结构,并初始化,注意handle.dev是当前的input device,handle.handler是匹配上的handler,这个信息在事件处理的时候还要用。evdev对应的eventx,是一个char设备。