input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);
write_input_event_to_file(jiffies, EV_ABS, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);
input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);
write_input_event_to_file(jiffies, EV_ABS, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);
input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);
write_input_event_to_file(jiffies, EV_ABS, ABS_PRESSURE, 1);
input_report_key(s3c_ts_dev, BTN_TOUCH, 1);
write_input_event_to_file(jiffies, EV_KEY, BTN_TOUCH, 1);
input_sync(s3c_ts_dev);
write_input_event_to_file(jiffies, EV_SYN, SYN_REPORT, 0);
}
cnt = 0;
enter_wait_pen_up_mode();
// 启动定时器处理长按/滑动的情况 //
mod_timer(&ts_timer, jiffies + HZ/100);
}
else
{
enter_measure_xy_mode();
start_adc();
}
}
return IRQ_HANDLED;
}
static int s3c_ts_init(void)
{
struct clk* clk;
replay_buf = kmalloc(MYLOG_BUF_LEN, GFP_KERNEL);
if (!replay_buf)
{
printk("cant alloc for mylog_buf\n");
return -EIO;
}
// 1. 分配一个input_dev结构体 //
s3c_ts_dev = input_allocate_device();
// 2. 设置 //
// 2.1 能产生哪类事件 //
set_bit(EV_KEY, s3c_ts_dev-"evbit);
set_bit(EV_ABS, s3c_ts_dev-"evbit);
// 2.2 能产生这类事件里的哪些事件 //
set_bit(BTN_TOUCH, s3c_ts_dev-"keybit);
input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
// 3. 注册 //
input_register_device(s3c_ts_dev);
// 4. 硬件相关的操作 //
// 4.1 使能时钟(CLKCON[15]) //
clk = clk_get(NULL, "adc");
clk_enable(clk);
// 4.2 设置S3C2440的ADC/TS寄存器 //
s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));
// bit[14] : 1-A/D converter prescaler enable
* bit[13:6]: A/D converter prescaler value,
* 49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz
* bit[0]: A/D conversion starts by enable. 先设为0
//
s3c_ts_regs-"adccon = (1""14)|(49""6);
request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);
// 优化措施1:
* 设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断
//
s3c_ts_regs-"adcdly = 0xffff;
// 优化措施5: 使用定时器处理长按,滑动的情况
*
//
init_timer(&ts_timer);
ts_timer.function = s3c_ts_timer_function;
add_timer(&ts_timer);
enter_wait_pen_down_mode();
major = register_chrdev(0, "input_replay", &replay_fops);
cls = class_create(THIS_MODULE, "input_replay");
device_create(cls, NULL, MKDEV(major, 0), "input_emu"); // /dev/input_emu //
init_timer(&replay_timer);
replay_timer.function = input_replay_timer_func;
//add_timer(&replay_timer);
return 0;
}
static void s3c_ts_exit(void)
{
//del_timer(&replay_timer);
kfree(replay_buf);
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, "input_replay");
free_irq(IRQ_TC, NULL);
free_irq(IRQ_ADC, NULL);
iounmap(s3c_ts_regs);
input_unregister_device(s3c_ts_dev);
input_free_device(s3c_ts_dev);
del_timer(&ts_timer);
}
module_init(s3c_ts_init);
module_exit(s3c_ts_exit);
MODULE_LICENSE("GPL");
==================================================================
测试程序:
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdio.h"
#include "poll.h"
#include "signal.h"
#include "sys/types.h"
#include "unistd.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#define INPUT_REPLAY 0
#define INPUT_TAG 1
// Usage:
//./input_replay write "file"
// ./input_replay replay
// ./input_repaly tag "string"
//
void print_usage(char *file)
{
printf("Usage:\n");
printf("%s write "file"\n", file);
printf("%s replay\n", file);
printf("%s tag "string"\n", file);