📄 tsc2003andcs7103.c
字号:
ret = kernel_thread(tsc2003ts_thread, d, CLONE_KERNEL); if (ret >= 0) { wait_for_completion(&d->tstask_completion); ret = 0; } up(&d->sem); return ret;}static void tsc2003_idev_close (struct input_dev *idev){ struct tsc2003_data *d = idev->private; down_interruptible(&d->sem); if (d->tstask) { send_sig(SIGKILL, d->tstask, 1); wait_for_completion(&d->tstask_completion); } if (timer_pending(&d->penirq_timer)) del_timer(&d->penirq_timer); up(&d->sem); return;}#if defined(CONFIG_SYSFS) && defined(CONFIG_SENSORS_TSC2003_SYSFS)static ssize_t show_addr (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->client.addr);}static DEVICE_ATTR(addr, S_IRUGO, show_addr, NULL);static ssize_t show_vbat1 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->vbat1);}static DEVICE_ATTR(vbat1, S_IRUGO, show_vbat1, NULL);static ssize_t show_vbat2 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->vbat2);}static DEVICE_ATTR(vbat2, S_IRUGO, show_vbat2, NULL);static ssize_t show_in1 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->in1);}static DEVICE_ATTR(in1, S_IRUGO, show_in1, NULL);static ssize_t show_in2 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->in2);}static DEVICE_ATTR(in2, S_IRUGO, show_in2, NULL);static ssize_t show_temp0 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->temp0);}static DEVICE_ATTR(temp0, S_IRUGO, show_temp0, NULL);static ssize_t show_temp1 (struct device *dev, char *buf){ struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); return sprintf(buf, "%d\n", d->temp1);}static DEVICE_ATTR(temp1, S_IRUGO, show_temp1, NULL);#warning "TODO: this daemon sometimes hangs the touchscreen daemon"#warning "TODO: under periods of heavy touch screen activity."#warning "TODO: Use with caution until the bug is squashed."static int tsc2003s_thread (void *v){ struct tsc2003_data *d = v; daemonize(DRIVER_NAME "sd"); allow_signal(SIGKILL); printk(KERN_INFO "%s: address 0x%x\n", __FUNCTION__, d->client.addr); while (!signal_pending(current)) { if (!down_interruptible(&d->sem)) { if (!timer_pending(&d->penirq_timer)) { tsc2003_read_vbat1(d, d->pd, &d->vbat1); tsc2003_read_vbat2(d, d->pd, &d->vbat2); tsc2003_read_in1(d, d->pd, &d->in1); tsc2003_read_in2(d, d->pd, &d->in2); tsc2003_read_temp0(d, d->pd, &d->temp0); tsc2003_read_temp1(d, d->pd, &d->temp1); } up(&d->sem); } set_task_state(current, TASK_INTERRUPTIBLE); schedule_timeout(5 * HZ); } do_exit(0);}#endifstatic int tsc2003_detect_irq (struct tsc2003_data *d){ d->penirq = IRQ_GPIO(16); //PWM0 GPIO return 0;}/*static int tsc2003_probe (struct device *dev){ //struct platform_device *p = to_platform_device(dev); struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver); int ret = 0; int error; printk(KERN_ERR "TSC2003: tsc2003_probe probing...\n"); error = tsc2003_detect_irq(d); if(error) { printk(KERN_ERR "TSC2003: IRQ probe failed\n"); } if (d->penirq) { ret = request_irq(d->penirq, tsc2003_penirq, IRQF_TRIGGER_FALLING, DRIVER_NAME, d); if (!ret) { printk(KERN_INFO "%s: irq %d\n", __FUNCTION__, d->penirq); } else { printk(KERN_INFO "%s: cannot grab irq %d\n", __FUNCTION__, d->penirq); } }#if defined(CONFIG_SYSFS) && defined(CONFIG_SENSORS_TSC2003_SYSFS) ret = kernel_thread(tsc2003s_thread, d, CLONE_KERNEL); if (ret >= 0) ret = 0; device_create_file(dev, &dev_attr_addr); device_create_file(dev, &dev_attr_vbat1); device_create_file(dev, &dev_attr_vbat2); device_create_file(dev, &dev_attr_in1); device_create_file(dev, &dev_attr_in2); device_create_file(dev, &dev_attr_temp0); device_create_file(dev, &dev_attr_temp1);#endif return ret;}*/static int tsc2003_driver_register (struct tsc2003_data *data){ struct input_dev *idev; int ret = 0; int error; init_MUTEX(&data->sem); init_timer(&data->penirq_timer); data->penirq_timer.data = (unsigned long)data; data->penirq_timer.function = tsc2003_pen_up; error = tsc2003_detect_irq(data); if(error) { printk(KERN_ERR "TSC2003: IRQ probe failed\n"); } if (data->penirq) { ret = request_irq(data->penirq, tsc2003_penirq, IRQF_TRIGGER_FALLING, DRIVER_NAME, data); if (!ret) { printk(KERN_INFO "%s: irq %d\n", __FUNCTION__, data->penirq); init_completion(&data->tstask_completion); init_completion(&data->penirq_completion); } else { printk(KERN_ERR "%s: cannot grab irq %d\n", __FUNCTION__, data->penirq); } } idev = input_allocate_device(); data->idev = idev; idev->private = data; idev->name = DRIVER_NAME; idev->evbit[0] = BIT(EV_ABS); idev->open = tsc2003_idev_open; idev->close = tsc2003_idev_close; idev->absbit[LONG(ABS_X)] = BIT(ABS_X); idev->absbit[LONG(ABS_Y)] = BIT(ABS_Y); idev->absbit[LONG(ABS_PRESSURE)] = BIT(ABS_PRESSURE); input_set_abs_params(idev, ABS_X, 0, ADC_MAX, 0, 0); input_set_abs_params(idev, ABS_Y, 0, ADC_MAX, 0, 0); input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0); if (!ret) { input_register_device(idev); printk(KERN_INFO "tsc2003 - registering input device\n"); } return ret;}static int tsc2003_i2c_attach_adapter(struct i2c_adapter *adapter){ printk(KERN_INFO "tsc2003 i2c touch screen controller\n"); printk(KERN_INFO "Bill Gatliff <bgat at billgatliff.com\n"); printk(KERN_INFO "Nicholas Chen <nchen at cs.umd.edu>\n"); return i2c_probe(adapter, &addr_data, tsc2003_i2c_detect);}static int tsc2003_i2c_detach_client(struct i2c_client *client){ int err; struct tsc2003_data *d = i2c_get_clientdata(client); free_irq(d->penirq,d); input_unregister_device(d->idev); if ((err = i2c_detach_client(client))) { dev_err(&client->dev, "Client deregistration failed, " "client not detached.\n"); return err; } return 0;}static struct i2c_driver tsc2003_driver = { .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, }, .attach_adapter = tsc2003_i2c_attach_adapter, .detach_client = tsc2003_i2c_detach_client, // .command = tsc2003_command,};static int tsc2003_i2c_detect (struct i2c_adapter *adapter, int address, int kind){ struct i2c_client *new_client; struct tsc2003_data *data; int err = 0; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA)) goto exit; data = kcalloc(1, sizeof(*data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &tsc2003_driver; new_client->flags = 0; /* TODO: I'm pretty sure I'm not dealing with kind correctly */ if (kind == 0 /* identification */ || kind < 0 /* detection */) kind = tsc2003; if (kind == tsc2003) name = DRIVER_NAME; /* try a command, see if we get an ack; if we do, assume it's our device */ printk(KERN_INFO "%s: probing address 0x%x\n", __FUNCTION__, address); err = tsc2003_powerdown(data); if (err >= 0) { strlcpy(new_client->name, name, I2C_NAME_SIZE); err = i2c_attach_client(new_client); if (err) goto exit_free; tsc2003_init_client(new_client); err = tsc2003_driver_register(data); if (err < 0) goto exit_free; printk(KERN_INFO "%s: device address 0x%x attached.\n", __FUNCTION__, address); return 0; } /* failure to detect when everything else is ok isn't an error */ else err = 0; exit_free: kfree(new_client); exit: return err;}static int __init tsc2003_init(void){ return i2c_add_driver(&tsc2003_driver);}static void __exit tsc2003_exit(void){ i2c_del_driver(&tsc2003_driver);}MODULE_AUTHOR("Bill Gatliff <bgat at billgatliff.com>");MODULE_DESCRIPTION("TSC2003 Touch Screen Controller driver");MODULE_LICENSE("GPL");module_init(tsc2003_init);module_exit(tsc2003_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -