在目錄下amp\a53_linux\drv\extdrv\touchpad\ft6236
下可以看到ft6236.c的文件
1. init函數
static int __init ft_init(void)
{
int ret = 0;
hi_gpio_groupbit_info stIntInfo;
hi_gpio_groupbit_info stRstInfo;
stIntInfo.group_num = INT_GPIO_CHIP;
stIntInfo.bit_num = INT_GPIO_OFFSET;
stIntInfo.value = 0;
stRstInfo.group_num = RST_GPIO_CHIP;
stRstInfo.bit_num = RST_GPIO_OFFSET;
stRstInfo.value = 1;
ret = i2cdev_init();
if (ret)
{
dev_err(NULL, " i2cdev_init fail!\n");
goto error_end;
}
hi_gpio_set_dir(&stIntInfo);
hi_gpio_set_dir(&stRstInfo);
ret = ft_reset(&stRstInfo);
if (ret)
{
dev_err(NULL, " ft_reset fail!\n");
goto error_end;
}
ret = devinput_init();
if (ret)
{
dev_err(NULL, " devinput_init fail!\n");
goto error_end;
}
return 0;
error_end:
return -1;
}
INT_GPIO_CHIP
和INT_GPIO_OFFSET
都是在宏定義
#elif (defined(BOARD_DEMB) && (defined(HI3556AV100) || defined(HI3519AV100)))
下定義的
#define RST_GPIO_CHIP (2)
#define RST_GPIO_OFFSET (6)
#define INT_GPIO_CHIP (2)
#define INT_GPIO_OFFSET (5)
這些管腳可以在這里《Hi3556AV100 Demo 單板使用指南.pdf》中看到,分別得出觸摸屏的中斷和復位管腳
1.1 對觸摸屏進行復位
static int ft_reset(hi_gpio_groupbit_info* pstRstInfo)
{
pstRstInfo->value = 1;
hi_gpio_write_bit(pstRstInfo);
pstRstInfo->value = 0;
hi_gpio_write_bit(pstRstInfo);
msleep(5);
pstRstInfo->value = 1;
hi_gpio_write_bit(pstRstInfo);
return 0;
}
對觸摸屏進行復位;
1.2 input系統初始化
static int devinput_init(void)
{
int error = 0;
/* 1. distribution a "input_dev" structure */
ft_ts_dev = input_allocate_device();
if (ft_ts_dev == NULL)
{
printk(" func:%s line:%d \r\n", __FUNCTION__, __LINE__);
return -1;
}
ft_ts_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
set_bit(EV_SYN, ft_ts_dev->evbit);
set_bit(EV_KEY, ft_ts_dev->evbit);
set_bit(EV_ABS, ft_ts_dev->evbit);
set_bit(INPUT_PROP_DIRECT, ft_ts_dev->propbit);
input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_X, 0 , FT_SCREEN_WIDTH_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_Y, 0, FT_SCREEN_HEIGHT_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TOUCH_MAJOR,
0, 0xff, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_PRESSURE,
0, 0xff, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TRACKING_ID,
0, 0xff, 0, 0);
error = input_mt_init_slots(ft_ts_dev, FT_MAX_TOUCH_POINTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error)
{ return error; }
ft_ts_dev->name = "ft";
ft_ts_dev->id.bustype = BUS_I2C;
error = input_register_device(ft_ts_dev);
if (error)
{
dev_err(NULL, "failed to register input device: %d\n", error);
return error;
}
/**request_threaded_irq(unsigned int irq,irq_handler_t handler,irq_handler_t thread_fn,unsigned long irqflags,const char * devname,void * dev_id)*/
error = fts_irq_register();
if(error)
{
dev_err(NULL, "failed to register input device: %d\n", error);
return error;
}
/**Clear INT*/
touch_set_reg(0x045f241C, 0x20);
return 0;
}
- set_bit()告訴input輸入子系統支持哪些按鍵
evbit:
事件類型(包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)
propbit:
set_bit(INPUT_PROP_DIRECT,dev->propbit);//表明設備的坐標直接和屏幕坐標向對應
- input_set_abs_params
給設備的input_dev結構體初始化,這些input_dev如果想被當成多點屏處理的話,只需要給input_dev額外增加以下幾個參數:
input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_X, 0 , FT_SCREEN_WIDTH_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_Y, 0, FT_SCREEN_HEIGHT_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TOUCH_MAJOR,
0, 0xff, 0, 0);
//相當於單點屏的ABX_PRESSURE
input_set_abs_params(ft_ts_dev, ABS_MT_PRESSURE,
0, 0xff, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TRACKING_ID,
0, 0xff, 0, 0);
//確定第幾手指來上報的數據
input_set_abs_params(idev, ABS_X, -64, 64, 4, 0);
對於X軸范圍是-64到+64,數據誤差是-4到+4,中心平滑位置是0
- input_mt_init_slots
報告最大支持的點數
- input_register_device
注冊input子系統
- 通過注冊中斷管腳
fts_irq_register注冊中斷
2. 中斷函數處理
static irqreturn_t ftint_irq(int irq, void *data)
{
int i;
bool act;
struct input_dev* input = ft_ts_dev;
ts_event event;
int ret = touch_event_handler(&event);
if(ret)
printk( "\n buffer_read failed \n");
if(event.point_num != 0)
{
for(i = 0; i < event.touch_point; i++)
{
input_mt_slot(input, i);
act = (event.au8_touch_event[i] == FT_EVENT_PRESS_DOWN || event.au8_touch_event[i] == FT_EVENT_CONTACT);
input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
if (!act)
continue;
input_report_abs(input, ABS_MT_POSITION_X, event.au16_x[i]);
input_report_abs(input, ABS_MT_POSITION_Y, event.au16_y[i]);
}
}
input_mt_sync_frame(input);
input_sync(input);
return IRQ_HANDLED;
}
- touch_event_handler函數
ret = hi_i2c_read(0x0, buf, FT_MAX_BUFUSED_NUM);
在這里,使用了hi_i2c_read,在文件i2cdev.c
中,注意i2c_board_info的一般是8位從地址;
一般來說,觸摸屏有固件的,然后每一個固件都代表類似的協議,由於我們沒有相應的協議,所以按照下面的來看:
for (i = 0; i < FT_MAX_TOUCH_POINTS; i++)
{
event->touch_point++;
/**Notice the array bound !!*/
/* 獲取x坐標 */
event->au16_x[i] =
(s16) (buf[FT_TOUCH_X_H_POS + 6 * i] & 0x0F) << 8 | (s16) buf[FT_TOUCH_X_L_POS + 6 * i];
/* 獲取y坐標 */
event->au16_y[i] =
(s16) (buf[FT_TOUCH_Y_H_POS + 6 * i] & 0x0F) << 8 | (s16) buf[FT_TOUCH_Y_L_POS + 6 * i];
/* 按下,松開,觸摸 */
event->au8_touch_event[i] =
buf[FT_TOUCH_EVENT_POS + 6 * i] >> 6;
event->au8_finger_id[i] =
(buf[FT_TOUCH_FINGER_POS + 6 * i]) >> 4;
/**pressure and area not used !!*/
#if 0
event->area[i] =
(buf[FT_TOUCH_AREA_POS + 6 * i]) >> 4;
event->pressure[i] =
(s16) buf[FTS_TOUCH_PRE_POS + 6 * i];
if (0 == event->area[i])
event->area[i] = 0x09;
if (0 == event->pressure[i])
event->pressure[i] = 0x3f;
#endif
if ((event->au8_touch_event[i]==0 || event->au8_touch_event[i]==2)&&(event->point_num==0))
{
printk("abnormal touch data from fw");
return -1;
}
}
- 中斷函數:
static irqreturn_t ftint_irq(int irq, void *data)
{
int i;
bool act;
struct input_dev* input = ft_ts_dev;
ts_event event;
int ret = touch_event_handler(&event);
if(ret)
printk( "\n buffer_read failed \n");
if(event.point_num != 0)
{
for(i = 0; i < event.touch_point; i++)
{
input_mt_slot(input, i);
act = (event.au8_touch_event[i] == FT_EVENT_PRESS_DOWN || event.au8_touch_event[i] == FT_EVENT_CONTACT);
input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
if (!act)
continue;
input_report_abs(input, ABS_MT_POSITION_X, event.au16_x[i]);
input_report_abs(input, ABS_MT_POSITION_Y, event.au16_y[i]);
}
}
input_mt_sync_frame(input);
input_sync(input);
return IRQ_HANDLED;
}