• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "touch_fts.h"
16 #include "cmsis_os2.h"
17 #include "gpio_if.h"
18 #include "i2c_if.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_log.h"
21 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
22 #include "hcs_macro.h"
23 #include "hdf_config_macro.h"
24 #else
25 #include "device_resource_if.h"
26 #endif
27 static int tpd_interrupt_handler(uint16_t gpio, void *arg);
28 
29 struct tpd_priv {
30     struct touch_device *dev;
31     struct i2c_client i2c_client;
32     uint16_t gpio_rst;
33     uint16_t gpio_int;
34 };
35 
36 static struct tpd_priv priv = {
37     .gpio_rst = 5,  // TSP_RST - GPIO05
38     .gpio_int = 23, // TSP_INT - GPIO27
39     .i2c_client = {
40         .id = 1, // TSP_SCL/SDA - I2C1 = GPIO06/GPIO07
41         .addr = 0x38,
42     }};
43 
44 /*****************************************************************************
45  * i2c related
46  *****************************************************************************/
47 #define I2C_RETRY_NUMBER 3
fts_i2c_read(struct i2c_client * client,uint8_t * writebuf,int writelen,uint8_t * readbuf,int readlen)48 static int fts_i2c_read(struct i2c_client *client, uint8_t *writebuf, int writelen, uint8_t *readbuf, int readlen)
49 {
50     int ret = 0;
51     int i = 0;
52 
53     if (client == NULL) {
54         HDF_LOGE("[IIC][%s]i2c_client==NULL!", __func__);
55         return -EINVAL;
56     }
57 
58     if (readlen > 0) {
59         if (writelen > 0) {
60             struct I2cMsg msgs[] = {
61                 {
62                     .addr = client->addr,
63                     .flags = 0,
64                     .len = writelen,
65                     .buf = writebuf,
66                 },
67                 {
68                     .addr = client->addr,
69                     .flags = I2C_FLAG_READ,
70                     .len = readlen,
71                     .buf = readbuf,
72                 },
73             };
74             for (i = 0; i < I2C_RETRY_NUMBER; i++) {
75                 ret = I2cTransfer(client->handle, msgs, 2);
76                 if (ret < 0) {
77                     HDF_LOGE("[IIC]: i2c_transfer(write) error, ret=%d!!", ret);
78                 } else
79                     break;
80             }
81         } else {
82             struct I2cMsg msgs[] = {
83                 {
84                     .addr = client->addr,
85                     .flags = I2C_FLAG_READ,
86                     .len = readlen,
87                     .buf = readbuf,
88                 },
89             };
90             for (i = 0; i < I2C_RETRY_NUMBER; i++) {
91                 ret = I2cTransfer(client->handle, msgs, 1);
92                 if (ret < 0) {
93                     HDF_LOGE("[IIC]: i2c_transfer(read) error, ret=%d!!", ret);
94                 } else
95                     break;
96             }
97         }
98     }
99 
100     return ret;
101 }
102 
fts_i2c_write(struct i2c_client * client,uint8_t * writebuf,int writelen)103 static int fts_i2c_write(struct i2c_client *client, uint8_t *writebuf, int writelen)
104 {
105     int ret = 0;
106     int i = 0;
107 
108     if (client == NULL) {
109         HDF_LOGE("[IIC][%s]i2c_client==NULL!", __func__);
110         return -EINVAL;
111     }
112 
113     if (writelen > 0) {
114         struct I2cMsg msgs[] = {
115             {
116                 .addr = client->addr,
117                 .flags = 0,
118                 .len = writelen,
119                 .buf = writebuf,
120             },
121         };
122         for (i = 0; i < I2C_RETRY_NUMBER; i++) {
123             ret = I2cTransfer(client->handle, msgs, 1);
124             if (ret < 0) {
125                 HDF_LOGE("[IIC]: i2c_transfer(write) error, ret=%d!!", ret);
126             } else
127                 break;
128         }
129     }
130 
131     return ret;
132 }
133 
fts_i2c_write_reg(struct i2c_client * client,uint8_t regaddr,uint8_t regvalue)134 static int fts_i2c_write_reg(struct i2c_client *client, uint8_t regaddr, uint8_t regvalue)
135 {
136     uint8_t buf[2] = {0};
137 
138     buf[0] = regaddr;
139     buf[1] = regvalue;
140     return fts_i2c_write(client, buf, sizeof(buf));
141 }
142 
fts_i2c_read_reg(struct i2c_client * client,uint8_t regaddr,uint8_t * regvalue)143 static int fts_i2c_read_reg(struct i2c_client *client, uint8_t regaddr, uint8_t *regvalue)
144 {
145     return fts_i2c_read(client, &regaddr, 1, regvalue, 1);
146 }
147 
fts_i2c_hid2std(struct i2c_client * client)148 static void fts_i2c_hid2std(struct i2c_client *client)
149 {
150     int ret = 0;
151     uint8_t buf[3] = {0xeb, 0xaa, 0x09};
152 
153     ret = fts_i2c_write(client, buf, 3);
154     if (ret < 0)
155         HDF_LOGE("hid2std cmd write fail");
156     else {
157         osDelay(10);
158         buf[0] = buf[1] = buf[2] = 0;
159         ret = fts_i2c_read(client, NULL, 0, buf, 3);
160         if (ret < 0)
161             HDF_LOGE("hid2std cmd read fail");
162         else if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) {
163             HDF_LOGE("hidi2c change to stdi2c successful");
164         } else {
165             HDF_LOGE("hidi2c change to stdi2c fail");
166         }
167     }
168 }
169 
170 /*****************************************************************************
171  * chip related
172  *****************************************************************************/
173 #define INTERVAL_READ_REG 100 /* interval time per read reg unit:ms */
174 #define TIMEOUT_READ_REG 1000 /* timeout of read reg unit:ms */
175 #define FTS_I2C_SLAVE_ADDR 0x38
176 
177 static struct fts_ts_data *fts_data;
178 
fts_get_chip_types(struct fts_ts_data * ts_data,uint8_t id_h,uint8_t id_l,bool fw_valid)179 static int fts_get_chip_types(struct fts_ts_data *ts_data, uint8_t id_h, uint8_t id_l, bool fw_valid)
180 {
181     int i = 0;
182     struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
183     uint32_t ctype_entries = sizeof(ctype) / sizeof(struct ft_chip_t);
184 
185     if ((0x0 == id_h) || (0x0 == id_l)) {
186         HDF_LOGE("id_h/id_l is 0");
187         return -EINVAL;
188     }
189 
190     HDF_LOGI("verify id:0x%02x%02x", id_h, id_l);
191     for (i = 0; i < ctype_entries; i++) {
192         if (VALID == fw_valid) {
193             if ((id_h == ctype[i].chip_idh) && (id_l == ctype[i].chip_idl))
194                 break;
195         } else {
196             if (((id_h == ctype[i].rom_idh) && (id_l == ctype[i].rom_idl)) || ((id_h == ctype[i].pb_idh) && (id_l == ctype[i].pb_idl)) || ((id_h == ctype[i].bl_idh) && (id_l == ctype[i].bl_idl)))
197                 break;
198         }
199     }
200 
201     if (i >= ctype_entries) {
202         return -ENODATA;
203     }
204 
205     ts_data->ic_info.ids = ctype[i];
206     return 0;
207 }
208 
fts_get_ic_information(struct fts_ts_data * ts_data)209 static int fts_get_ic_information(struct fts_ts_data *ts_data)
210 {
211     int ret = 0;
212     int cnt = 0;
213     uint8_t chip_id[2] = {0};
214     uint8_t id_cmd[4] = {0};
215     uint32_t id_cmd_len = 0;
216     struct i2c_client *client = ts_data->client;
217 
218     ts_data->ic_info.is_incell = FTS_CHIP_IDC;
219     ts_data->ic_info.hid_supported = FTS_HID_SUPPORTTED;
220     do {
221         ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id[0]);
222         ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id[1]);
223         if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) {
224             HDF_LOGD("i2c read invalid, read:0x%02x%02x", chip_id[0], chip_id[1]);
225         } else {
226             ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], VALID);
227             if (!ret)
228                 break;
229             else
230                 HDF_LOGD("TP not ready, read:0x%02x%02x", chip_id[0], chip_id[1]);
231         }
232 
233         cnt++;
234         osDelay(INTERVAL_READ_REG);
235     } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
236 
237     if ((cnt * INTERVAL_READ_REG) >= TIMEOUT_READ_REG) {
238         HDF_LOGI("fw is invalid, need read boot id");
239         if (ts_data->ic_info.hid_supported) {
240             fts_i2c_hid2std(client);
241         }
242 
243         id_cmd[0] = FTS_CMD_START1;
244         id_cmd[1] = FTS_CMD_START2;
245         ret = fts_i2c_write(client, id_cmd, 2);
246         if (ret < 0) {
247             HDF_LOGE("start cmd write fail");
248             return ret;
249         }
250 
251         osDelay(FTS_CMD_START_DELAY);
252         id_cmd[0] = FTS_CMD_READ_ID;
253         id_cmd[1] = id_cmd[2] = id_cmd[3] = 0x00;
254         if (ts_data->ic_info.is_incell)
255             id_cmd_len = FTS_CMD_READ_ID_LEN_INCELL;
256         else
257             id_cmd_len = FTS_CMD_READ_ID_LEN;
258         ret = fts_i2c_read(client, id_cmd, id_cmd_len, chip_id, 2);
259         if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) {
260             HDF_LOGE("read boot id fail");
261             return -EIO;
262         }
263         ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], 0);
264         if (ret < 0) {
265             HDF_LOGE("can't get ic informaton");
266             return ret;
267         }
268     }
269 
270     HDF_LOGI("get ic information, chip id = 0x%02x%02x",
271              ts_data->ic_info.ids.chip_idh, ts_data->ic_info.ids.chip_idl);
272 
273     return 0;
274 }
275 
fts_reset_proc(int hdelayms)276 static int fts_reset_proc(int hdelayms)
277 {
278     GpioWrite(priv.gpio_rst, 0);
279     osDelay(5);
280     GpioWrite(priv.gpio_rst, 1);
281     if (hdelayms) {
282         osDelay(hdelayms);
283     }
284     return 0;
285 }
286 
fts_read_touchdata(struct fts_ts_data * data)287 static int fts_read_touchdata(struct fts_ts_data *data)
288 {
289     int ret = 0;
290     int i = 0;
291     uint8_t pointid;
292     int base;
293     struct ts_event *events = data->events;
294     int max_touch_num = FTS_TOUCH_POINT_NUM;
295     uint8_t *buf = data->point_buf;
296 
297     data->point_num = 0;
298     data->touch_point = 0;
299 
300     memset(buf, 0xFF, data->pnt_buf_size);
301     buf[0] = 0x00;
302 
303     ret = fts_i2c_read(data->client, buf, 1, buf, data->pnt_buf_size);
304     if (ret < 0) {
305         HDF_LOGE("read touchdata failed, ret:%d", ret);
306         return ret;
307     }
308     data->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
309 
310     if (data->ic_info.is_incell) {
311         if ((data->point_num == 0x0F) && (buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF) &&
312             (buf[4] == 0xFF) && (buf[5] == 0xFF) && (buf[6] == 0xFF)) {
313             HDF_LOGI("touch buff is 0xff, need recovery state");
314             return -EIO;
315         }
316     }
317     if (data->point_num > max_touch_num) {
318         HDF_LOGI("invalid point_num(%d)", data->point_num);
319         return -EIO;
320     }
321 
322     for (i = 0; i < max_touch_num; i++) {
323         base = FTS_ONE_TCH_LEN * i;
324 
325         pointid = (buf[FTS_TOUCH_ID_POS + base]) >> 4;
326         if (pointid >= FTS_MAX_ID)
327             break;
328         else if (pointid >= max_touch_num) {
329             HDF_LOGE("ID(%d) beyond max_touch_number", pointid);
330             return -EINVAL;
331         }
332 
333         data->touch_point++;
334 
335         events[i].x = ((buf[FTS_TOUCH_X_H_POS + base] & 0x0F) << 8) +
336                       (buf[FTS_TOUCH_X_L_POS + base] & 0xFF);
337         events[i].y = ((buf[FTS_TOUCH_Y_H_POS + base] & 0x0F) << 8) +
338                       (buf[FTS_TOUCH_Y_L_POS + base] & 0xFF);
339         events[i].flag = buf[FTS_TOUCH_EVENT_POS + base] >> 6;
340         events[i].id = buf[FTS_TOUCH_ID_POS + base] >> 4;
341         events[i].area = buf[FTS_TOUCH_AREA_POS + base] >> 4;
342         events[i].p = buf[FTS_TOUCH_PRE_POS + base];
343 
344         if (EVENT_DOWN(events[i].flag) && (data->point_num == 0)) {
345             HDF_LOGI("abnormal touch data from fw");
346             return -EIO;
347         }
348     }
349     if (data->touch_point == 0) {
350         HDF_LOGI("no touch point information");
351         return -EIO;
352     }
353 
354     return 0;
355 }
356 
tpd_irq_registration(struct fts_ts_data * ts_data)357 static int tpd_irq_registration(struct fts_ts_data *ts_data)
358 {
359     GpioSetDir(priv.gpio_int, GPIO_DIR_IN); // GPIO_DIR_IN_PULLUP
360     GpioSetIrq(priv.gpio_int, GPIO_IRQ_TRIGGER_FALLING, tpd_interrupt_handler, NULL);
361     GpioDisableIrq(priv.gpio_int);
362     HDF_LOGI("IRQ request succussfully, irq:%d", priv.gpio_int);
363     return 0;
364 }
365 
fts_input_init(struct fts_ts_data * ts_data)366 static int fts_input_init(struct fts_ts_data *ts_data)
367 {
368     int point_num = 0;
369     int ret = 0;
370 
371     point_num = FTS_TOUCH_POINT_NUM;
372     ts_data->pnt_buf_size = point_num * FTS_ONE_TCH_LEN + 3;
373     ts_data->point_buf = (uint8_t *)malloc(ts_data->pnt_buf_size);
374     if (!ts_data->point_buf) {
375         HDF_LOGE("failed to alloc memory for point buf!");
376         ret = -ENOMEM;
377         goto err_point_buf;
378     }
379     memset(ts_data->point_buf, 0, ts_data->pnt_buf_size);
380 
381     ts_data->events = (struct ts_event *)malloc(point_num * sizeof(struct ts_event));
382     if (!ts_data->events) {
383         HDF_LOGE("failed to alloc memory for point events!");
384         ret = -ENOMEM;
385         goto err_event_buf;
386     }
387     memset(ts_data->events, 0, point_num * sizeof(struct ts_event));
388 
389     return 0;
390 
391 err_event_buf:
392     free(ts_data->point_buf);
393 
394 err_point_buf:
395     return ret;
396 }
397 
tpd_probe(struct i2c_client * client)398 static int tpd_probe(struct i2c_client *client)
399 {
400     int ret = 0;
401     struct fts_ts_data *ts_data;
402 
403     ts_data = malloc(sizeof(*ts_data));
404     if (!ts_data) {
405         HDF_LOGE("Failed to allocate memory for fts_data");
406         return -ENOMEM;
407     }
408     memset(ts_data, 0, sizeof(*ts_data));
409     fts_data = ts_data;
410     ts_data->client = client;
411 
412     if (client->addr != FTS_I2C_SLAVE_ADDR) {
413         HDF_LOGI("[TPD]Change i2c addr 0x%02x to %x", client->addr, FTS_I2C_SLAVE_ADDR);
414         client->addr = FTS_I2C_SLAVE_ADDR;
415         HDF_LOGI("[TPD]i2c addr=0x%x\n", client->addr);
416     }
417 
418     ret = fts_input_init(ts_data);
419     if (ret) {
420         HDF_LOGE("fts input initialize fail");
421         goto err_input_init;
422     }
423 
424     fts_reset_proc(200);
425     ret = fts_get_ic_information(ts_data);
426     if (ret) {
427         HDF_LOGE("not focal IC, unregister driver");
428         goto err_input_init;
429     }
430 
431     HDF_LOGD("[TPD]Touch Panel Device Probe %s!", (ret < 0) ? "FAIL" : "PASS");
432 
433     /* Configure gpio to irq and request irq */
434     ret = tpd_irq_registration(ts_data);
435     if (ret) {
436         HDF_LOGE("request irq failed");
437         goto err_irq_req;
438     }
439 
440     HDF_LOGD("TPD_RES_Y:%d", (int)TPD_RES_Y);
441     return 0;
442 
443 err_irq_req:
444 err_input_init:
445     free(ts_data->point_buf);
446     free(ts_data->events);
447     free(ts_data);
448 
449     return ret;
450 }
451 
tpd_remove()452 static int tpd_remove()
453 {
454     if (fts_data) {
455         free(fts_data->point_buf);
456         free(fts_data->events);
457         free(fts_data);
458     }
459     return 0;
460 }
461 
462 /*****************************************************************************
463  * interfaces
464  *****************************************************************************/
tpd_get_point(struct touch_device * dev,struct touch_msg * msg)465 static int tpd_get_point(struct touch_device *dev, struct touch_msg *msg)
466 {
467     int ret = fts_read_touchdata(fts_data);
468     if (ret) {
469         return -1;
470     }
471 
472     struct ts_event *events = fts_data->events;
473     msg->x = events[0].x;
474     msg->y = events[0].y;
475     msg->event = EVENT_DOWN(events[0].flag) ? TOUCH_EVENT_DOWN : TOUCH_EVENT_UP;
476     return 0;
477 }
478 
tpd_interrupt_handler(uint16_t gpio,void * arg)479 static int tpd_interrupt_handler(uint16_t gpio, void *arg)
480 {
481     (void)arg;
482     if (gpio != priv.gpio_int)
483         return -1;
484 
485     if (priv.dev && priv.dev->sem)
486         osSemaphoreRelease(priv.dev->sem);
487 
488     return 0;
489 }
490 
tpd_irq_enable(bool enable)491 static void tpd_irq_enable(bool enable)
492 {
493     if (enable) {
494         GpioEnableIrq(priv.gpio_int);
495     } else {
496         GpioDisableIrq(priv.gpio_int);
497     }
498 }
499 
tpd_init(struct touch_device * dev)500 static int tpd_init(struct touch_device *dev)
501 {
502     priv.dev = dev;
503     priv.i2c_client.handle = I2cOpen(priv.i2c_client.id);
504     if (priv.i2c_client.handle == NULL) {
505         return -1;
506     }
507 
508     if (tpd_probe(&priv.i2c_client)) {
509         return -1;
510     }
511 
512     return 0;
513 }
514 
tpd_deinit(void)515 static void tpd_deinit(void)
516 {
517     GpioDisableIrq(priv.gpio_int);
518     I2cClose(priv.i2c_client.handle);
519     tpd_remove(&priv.i2c_client);
520 }
521 
522 struct touch_device g_touch_fts = {
523     .name = "fts_ts",
524     .init = tpd_init,
525     .deinit = tpd_deinit,
526     .read = tpd_get_point,
527     .irq_enable = tpd_irq_enable,
528 };
529 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
530 #define DISPLAY_INPUT_TOUCH HCS_NODE(HCS_NODE(HCS_NODE(HCS_ROOT, input), touch_config), touch_fts)
TouchDeviceGetResource(struct tpd_priv * priv)531 static uint32_t TouchDeviceGetResource(struct tpd_priv *priv)
532 {
533     priv->gpio_rst = HCS_PROP(DISPLAY_INPUT_TOUCH, gpio_rst);
534     priv->gpio_int = HCS_PROP(DISPLAY_INPUT_TOUCH, gpio_int);
535     priv->i2c_client.id = HCS_PROP(DISPLAY_INPUT_TOUCH, i2c_id);
536     priv->i2c_client.addr = HCS_PROP(DISPLAY_INPUT_TOUCH, i2c_addr);
537 
538     HDF_LOGD("%s: gpio_rst=%d, gpio_int=%d, i2c_id=%d, i2c_addr=%d", __func__,
539              priv->gpio_rst, priv->gpio_int, priv->i2c_client.id, priv->i2c_client.addr);
540     return HDF_SUCCESS;
541 }
542 #else
TouchDeviceGetResource(struct tpd_priv * priv,const struct DeviceResourceNode * resourceNode)543 static uint32_t TouchDeviceGetResource(struct tpd_priv *priv, const struct DeviceResourceNode *resourceNode)
544 {
545     struct DeviceResourceIface *res = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
546     if (res == NULL || res->GetUint32 == NULL) {
547         HDF_LOGE("DeviceResourceIface is invalid");
548         return HDF_FAILURE;
549     }
550     if (res->GetUint16(resourceNode, "gpio_rst", &priv->gpio_rst, 0) != HDF_SUCCESS) {
551         HDF_LOGE("%s: failed to get gpio_rst", __func__);
552         return HDF_FAILURE;
553     }
554     if (res->GetUint16(resourceNode, "gpio_int", &priv->gpio_int, 0) != HDF_SUCCESS) {
555         HDF_LOGE("%s: failed to get gpio_int", __func__);
556         return HDF_FAILURE;
557     }
558     if (res->GetUint16(resourceNode, "i2c_id", &priv->i2c_client.id, 0) != HDF_SUCCESS) {
559         HDF_LOGE("%s: failed to get i2c_id", __func__);
560         return HDF_FAILURE;
561     }
562     if (res->GetUint16(resourceNode, "i2c_addr", &priv->i2c_client.addr, 0) != HDF_SUCCESS) {
563         HDF_LOGE("%s: failed to get i2c_addr", __func__);
564         return HDF_FAILURE;
565     }
566     HDF_LOGD("%s: gpio_rst=%d, gpio_int=%d, i2c_id=%d, i2c_addr=%d", __func__,
567              priv->gpio_rst, priv->gpio_int, priv->i2c_client.id, priv->i2c_client.addr);
568     return HDF_SUCCESS;
569 }
570 #endif
TouchDriverInit(struct HdfDeviceObject * object)571 static int32_t TouchDriverInit(struct HdfDeviceObject *object)
572 {
573     if (object == NULL) {
574         return HDF_FAILURE;
575     }
576 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
577     if (TouchDeviceGetResource(&priv) != HDF_SUCCESS) {
578         HDF_LOGE("%s: TouchDeviceGetResource failed", __func__);
579         return HDF_FAILURE;
580     }
581 #else
582     if (object->property) {
583         if (TouchDeviceGetResource(&priv, object->property) != HDF_SUCCESS) {
584             HDF_LOGE("%s: TouchDeviceGetResource failed", __func__);
585             return HDF_FAILURE;
586         }
587     }
588 #endif
589     if (RegisterTouchDevice(&g_touch_fts) != HDF_SUCCESS) {
590         HDF_LOGE("%s: RegisterTouchDevice failed", __func__);
591         return HDF_FAILURE;
592     }
593     return HDF_SUCCESS;
594 }
595 
TouchDriverBind(struct HdfDeviceObject * device)596 static int32_t TouchDriverBind(struct HdfDeviceObject *device)
597 {
598     (void)device;
599     return HDF_SUCCESS;
600 }
601 
TouchDriverRelease(struct HdfDeviceObject * device)602 static void TouchDriverRelease(struct HdfDeviceObject *device)
603 {
604     (void)device;
605 }
606 
607 static struct HdfDriverEntry g_FTSTouchDriverEntry = {
608     .moduleVersion = 1,
609     .moduleName = "HDF_TOUCH_FTS",
610     .Bind = TouchDriverBind,
611     .Init = TouchDriverInit,
612     .Release = TouchDriverRelease,
613 };
614 
615 HDF_INIT(g_FTSTouchDriverEntry);