# 适配器件私有驱动<a name="ZH-CN_TOPIC_0000001158361505"></a>

Input模型由三层驱动组成，开发者适配一款全新触摸屏驱动只需要适配器件驱动层即可，重点实现差异化接口，本小节以代码示例的形式展示开发者需要重点完成的工作。

1.  触摸屏器件差异化接口适配

    示例代码路径：./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c

    ```
    static struct TouchChipOps g_gt911ChipOps = {                                  // 器件IC接口
        .Init = ChipInit,                                                          // 初始化
        .Detect = ChipDetect,                                                      // 器件检测
        .Resume = ChipResume,                                                      // 唤醒
        .Suspend = ChipSuspend,                                                    // 休眠
        .DataHandle = ChipDataHandle,                                              // 器件数据读取
        .UpdateFirmware = UpdateFirmware,                                          // 固件升级
    };
    
    /* 不同触摸屏厂家使用的IC不一样，对应的寄存器操作也不一样，因此器件驱动层代码重点适配差异化接口部分，如下示例代码展示了GT911的数据解析*/
    
    static int32_t ChipDataHandle(ChipDevice *device)
    {
        ...
        /*  GT911获取坐标之前需先读取状态寄存器  */
        reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; 
        reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK;
        ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1);
        if (ret < 0 || touchStatus == GT_EVENT_INVALID) {
            return HDF_FAILURE;
        }
        ...
        /* 根据状态寄存器的值读取数据寄存器数据 */
        reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK;
        reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK;
        pointNum = touchStatus & GT_FINGER_NUM_MASK;
        if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) {
            HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum);
            (void)ChipCleanBuffer(i2cClient);
            OsalMutexUnlock(&device->driver->mutex);
            return HDF_FAILURE;
        }
        frame->realPointNum = pointNum;
        frame->definedEvent = TOUCH_DOWN;
        (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum);
        /* 对获取的数据进行解析 */
        ParsePointData(device, frame, buf, pointNum);
        ...
    }
    static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum)
    {
        ...
        /* 每个坐标值由两个字节组成，对获取的单字节数据进行拼接得到最终的坐标值 */
        for (i = 0; i < pointNum; i++) {
                frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID];
                frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) |
                                      ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET);
                frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) |
                                      ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET);
                /* 对解析出来的坐标值进行打印 */
                HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y);
         }
    }
    ```

2.  器件层驱动初始化及注册驱动至HDF框架

    示例代码路径：./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c

    ```
    static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device)
    {
        ...
        /* 器件配置结构体内存申请、配置信息解析及挂载 */
        chipCfg = ChipConfigInstance(device);
        ...
        /* 器件实例化 */
        chipDev = ChipDeviceInstance();
        ...
        /* 器件信息挂载及器件私有操作挂载 */
        chipDev->chipCfg = chipCfg;
        chipDev->ops = &g_gt911ChipOps;
        ...
        /* 注册器件驱动至平台驱动 */
        RegisterChipDevice(chipDev);
        ...
    }
    struct HdfDriverEntry g_touchGoodixChipEntry = {
        .moduleVersion = 1,
        .moduleName = "HDF_TOUCH_GT911",   // 该moduleName与device_info.hcs文件中器件驱动层的moduleName信息相匹配
        .Init = HdfGoodixChipInit,         // 器件驱动初始化函数
    };
    HDF_INIT(g_touchGoodixChipEntry);      // 注册器件驱动至HDF框架
    ```

    器件私有驱动层主要实现了各器件厂商差异较大的部分，如器件休眠唤醒、数据解析以及固件升级等。

    至此，基于HDF框架及Input模型的触摸屏驱动适配完成。


