• ft6236 触摸屏驱动


    在目录下ampa53_linuxdrvextdrv ouchpadft6236下可以看到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!
    ");
            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!
    ");
            goto error_end;
        }
        ret = devinput_init();
        if (ret)
        {
            dev_err(NULL, " devinput_init fail!
    ");
            goto error_end;
        }
    
        return 0;
    error_end:
        return -1;
    }
    

    INT_GPIO_CHIPINT_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 
    ", __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
    ", 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
    ", error);
            return error;
        }
        /**Clear INT*/
        touch_set_reg(0x045f241C, 0x20);
        return 0;
    }
    
    1. set_bit()告诉input输入子系统支持哪些按键

    evbit:

    事件类型(包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)

    propbit:

    set_bit(INPUT_PROP_DIRECT,dev->propbit);//表明设备的坐标直接和屏幕坐标向对应

    1. 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

    1. input_mt_init_slots

    报告最大支持的点数

    1. input_register_device

    注册input子系统

    1. 通过注册中断管脚

    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( "
     buffer_read failed 
    ");
        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;
    }
    
    1. 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;
            }
        }
    
    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( "
     buffer_read failed 
    ");
        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;
    }
    
  • 相关阅读:
    (转)轻松应对IDC机房带宽突然暴涨问题
    (转)老男孩:Linux企业运维人员最常用150个命令汇总
    (转)cut命令详解
    (转)Awk使用案例总结(运维必会)
    (转)Nmap命令的29个实用范例
    BigPipe学习研究
    js正则大扫除
    ffff表单提交的那点事
    高并发订单操作处理方法
    订单号的处理
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/11046511.html
Copyright © 2020-2023  润新知