? ? ? ? ? ? ?
10 11 12 13 14 15 16
client表示一个i2c的设备; input表示一个输入设备;
work表示一个工作,用于处理中断到来之后获取坐标等信息; wq表示一个工作队列,将上面的work加入到该工作队列中; dd和touch_data用来存储坐标的相关信息; device_id表示i2c设备的设备号; irq申请的中断号; irq_pin中断引脚;
wake_pin复位引脚;这两个引脚信息可以通过dts获取到.
tp创建一个为tp_device的数据结构,里面有个成员notifier_block用来接收
LCD背光灯的亮暗的通知进而调用suspend()和resume()。主要的实现在tp_suspend.h中。至于这里面的详细机制还不是很明白。
(2)、检查i2c适配器的能力
在很多i2c设备驱动程序中,一进入probe()就要检查i2c适配器的能力。现在还不清楚这么做的目的是什么。后面会仔细的学习一下linux 的i2c子系统。
(3)、获取wake和irq的引脚信息
在前面配置dts说过:dts中设备节点的属性的值可以通过of_接口获取到。 // 从设备节点np中获取到irq和wake 的gpio的信息
ts->irq_pin=of_get_named_gpio_flags(np, \m of_gpio_flags *)&irq_flags); ts->wake_pin=of_get_named_gpio_flags(np, \ake_flags); ? ? ? 1 2 3 可以通过设备节点np获取到它irq-gpio这一个属性的值存放在ts->irq_pin中,以及将其flag刚到变量irq_flags中。因此我们可以知道: ts->irq_pin = GPIO_A2 irq_flag = IRQ_TYPE_LEVEL_HIGH ? ? 1 2 同理,wake_pin也是一样。 (4)、申请gpio并设置输出电平 将irq和wake 引脚电平都设置输出低电平。 (5)、gslX680_ts_init static int gslX680_ts_init(struct i2c_client *client, struct gsl_ts *ts) { struct input_dev *input_device; int rc = 0; printk(\ // 配置获取坐标信息 ts->dd = &devices[ts->device_id]; if(ts->device_id == 0) { ts->dd->data_size = MAX_FINGERS * ts->dd->touch_bytes + ts->dd->touch_meta_data; ts->dd->touch_index = 0; } // 申请空间存放坐标信息 ts->touch_data = kzalloc(ts->dd->data_size, GFP_KERNEL); if(!ts->touch_data) { pr_err(\ return -ENOMEM; } // 申请一个input_dev 设备 input_device = input_allocate_device(); if (!input_device) { rc = -ENOMEM; goto error_alloc_dev; } // 初始化input_device ts->input = input_device; input_device->name = GSLX680_I2C_NAME; input_device->id.bustype = BUS_I2C; input_device->dev.parent = &client->dev; input_set_drvdata(input_device, ts); // #ifdef REPORT_DATA_ANDROID_4_0 __set_bit(EV_ABS, input_device->evbit); __set_bit(EV_KEY, input_device->evbit); __set_bit(EV_REP, input_device->evbit); __set_bit(INPUT_PROP_DIRECT, input_device->propbit); input_mt_init_slots(input_device, (MAX_CONTACTS+1),0); #else input_set_abs_params(input_device,ABS_MT_TRACKING_ID, 0, (MAX_CONTACTS+1), 0, 0); set_bit(EV_ABS, input_device->evbit); set_bit(EV_KEY, input_device->evbit); __set_bit(INPUT_PROP_DIRECT, input_device->propbit); input_device->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); #endif #ifdef HAVE_TOUCH_KEY input_device->evbit[0] = BIT_MASK(EV_KEY); //input_device->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); for (i = 0; i < MAX_KEY_NUM; i++) set_bit(key_array[i], input_device->keybit); #endif set_bit(ABS_MT_POSITION_X, input_device->absbit); set_bit(ABS_MT_POSITION_Y, input_device->absbit); set_bit(ABS_MT_TOUCH_MAJOR, input_device->absbit); set_bit(ABS_MT_WIDTH_MAJOR, input_device->absbit); input_set_abs_params(input_device,ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0); input_set_abs_params(input_device,ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0); input_set_abs_params(input_device,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0); input_set_abs_params(input_device,ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); // 创建工作队列 ts->wq = create_singlethread_workqueue(\ if(!ts->wq) { dev_err(&client->dev, \ goto error_wq_create; } flush_workqueue(ts->wq); // 初始化工作 ts->work,其操作为 gslX680_ts_worker() INIT_WORK(&ts->work, gslX680_ts_worker); // 向input子系统注册一个input_dev rc = input_register_device(input_device); if (rc) goto error_unreg_device; return 0; error_unreg_device: destroy_workqueue(ts->wq); error_wq_create: input_free_device(input_device); error_alloc_dev: kfree(ts->touch_data);