(1)三星的触摸屏驱动s3c-ts.c:
s3c_ts_init-》platform_driver_register(&s3c_ts_driver);
static struct platform_driver s3c_ts_driver = {
.probe = s3c_ts_probe,
.driver = {
.owner = THIS_MODULE,
.name = "s3c-ts",},
};
通过"s3c-ts"字符串与dev-ts.c的s3c_device_ts中的name字串匹配,实现注册。
static int __init s3c_ts_probe(struct platform_device *pdev)
{
platform_get_resource(pdev, IORESOURCE_MEM, 0); //获得MEM资源
request_mem_region(res->start, size, pdev->name); //获得MEM资源大小
ioremap(res->start, size); //对MEM资源重新IO
clk_enable(ts_clock); //TS的CLK使能
struct s3c_ts_mach_info *s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev); //获得默认的ts配置数据,如采样率,通道
struct input_dev *input_dev = input_allocate_device();
ts->dev->name = s3c_ts_name;
ts->dev->phys = ts->phys;
ts->dev->id.bustype = BUS_RS232;
ts->dev->id.vendor = 0xDEAD;
ts->dev->id.product = 0xBEEF;
ts->dev->id.version = S3C_TSVERSION; //完善ts的input_dev参数
ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
request_irq(ts_irq->start, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c_updown", ts); //触点中断
ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);、
request_irq(ts_irq->start, stylus_action, IRQF_SAMPLE_RANDOM, "s3c_action", ts); //ADC中断操作
input_register_device(ts->dev); //注册输入设备到input层
ret = misc_register(&s3c_ts_miscdev); //注册字符设备,方便上层调用
}
(2)注册字符设备的作用。
struct file_operations s3c_ts_fops = {
.owner = THIS_MODULE,
.read = s3c_ts_read,
.write = s3c_ts_write,
.open = s3c_ts_open,
.release = s3c_ts_release,
};
#define S3C_TS_MINOR 222
static struct miscdevice s3c_ts_miscdev = {
.minor = S3C_TS_MINOR,
.name = "myts",
.fops = &s3c_ts_fops,
};
为方便上层调用。比如cupcake层的:
char buffer[5] = "OK";
int fd = open("/dev/myts",O_RDWR);
printf("fd: %d/n",fd);
write(fd,buffer,2);
close(fd);
这里的write函数将会直接调用字符设备驱动中的write函数指针,把数据从用户空间传递到内核空间。
static ssize_t s3c_ts_write(struct file *file, const char __user * buffer, size_t size, loff_t * pos)
{
char from_user_to[5];
if (copy_from_user(from_user_to, buffer, 2))//buffer: "OK" or "END"
{
return -EFAULT;
}
if(from_user_to[0]=='O'&&from_user_to[1]=='K')//if =="OK",need calibrate; //OK
{
start_calibrate_flag = 1;
finish_calibrate_flag = 0;
}
else if(from_user_to[0]=='E'&&from_user_to[1]=='N')//calibrate is over //END
{
start_calibrate_flag = 0;
finish_calibrate_flag = 1;
}
else
{
start_calibrate_flag = 0;
finish_calibrate_flag =0;
}
return 0;
}
(3)触摸屏中断的处理。有两个中断,一个是TS按下跟弹起的中断stylus_updown,另一个是ADC的中断stylus_action。这两个函数都会用到touch_timer_fire这个函数。
static int read_one_time = 0; //标记只控制一次
static void touch_timer_fire(unsigned long data)
{
updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));
if (updown) //处于按下状态
{
if(!read_one_time)//read calibrate parameter only once after power on
{
read_one_time = 1; //用完后置1,表示该部分就执行一次
a0 = default_val[0];a1 = default_val[1];a2 = default_val[2];a3 = default_val[3];
a4 = default_val[4];a5 = default_val[5];a6 = default_val[6]; //对七个参数赋初始默认值
if(read_file("/system/etc/pointercal")==0)
{
a0 = calpointer[0];a1 = calpointer[1];a2 = calpointer[2];a3 = calpointer[3];
a4 = calpointer[4];a5 = calpointer[5];a6 = calpointer[6];
} //读出系统中经tslib校验后放在pointercal中的七个参数,作为真正要用的值
calpointer[0] =0;calpointer[1] =0;calpointer[2] =0;calpointer[3] =0;
calpointer[4] =0;calpointer[5] =0;calpointer[6] =0; //用完后清零
}
x=(int) ts->xp;y=(int) ts->yp; //得到之前的ts->xp和ts->yp
if(!start_calibrate_flag) //如果不是重新开始校验,那么接着上面根据公式和新参数计算新坐标值
{
ts->xp=(long) ((a2+(a0*x)+(a1*y))/a6);
ts->yp=(long) ((a5+(a3*x)+(a4*y))/a6);
ts->xp = ts->xp < 0 ? 0:( ts->xp > PANEL_WIDTH ? PANEL_WIDTH : ts->xp );
ts->yp = ts->yp < 0 ? 0:( ts->yp > PANEL_HEIGHT ? PANEL_HEIGHT : ts->yp );
}
else //如果是运行校验程序重新校验的
{
if(finish_calibrate_flag) //而且校验完毕了
{
start_calibrate_flag = 0;finish_calibrate_flag = 0; //清标志
if(read_file("/system/etc/pointercal")==0)
{
a0 = calpointer[0];a1 = calpointer[1];a2 = calpointer[2];a3 = calpointer[3];
a4 = calpointer[4];a5 = calpointer[5];a6 = calpointer[6];
calpointer[0] =0;calpointer[1] =0;calpointer[2] =0;calpointer[3] =0;
calpointer[4] =0;calpointer[5] =0;calpointer[6] =0; //获得新参数及清空
}
}
}
if(ts->xp!=ts->xp_old || ts->yp!=ts->yp_old) //如果坐标值有变更
{
input_report_abs(ts->dev, ABS_X, ts->xp);
input_report_abs(ts->dev, ABS_Y, ts->yp);
input_report_abs(ts->dev, ABS_Z, 0);
input_report_key(ts->dev, BTN_TOUCH, 1);
input_report_abs(ts->dev, ABS_PRESSURE, 1);
input_sync(ts->dev); //将新的坐标值传递给Input层,及android上层
}
ts->xp_old=ts->xp;
ts->yp_old=ts->yp; //保留新值
}
else //处于弹起状态
{
input_report_abs(ts->dev, ABS_X, ts->xp_old);
input_report_abs(ts->dev, ABS_Y, ts->yp_old);
input_report_abs(ts->dev, ABS_Z, 0); //传递绝对坐标值给input层
input_report_key(ts->dev, BTN_TOUCH, 0); //触摸事件
input_report_abs(ts->dev, ABS_PRESSURE, 0); //触摸压力为0,弹起
input_sync(ts->dev); //将input report数据同步更新
}
}