1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <securec.h>
10 #include "osal_mem.h"
11 #include "osal_io.h"
12 #include "hdf_device_desc.h"
13 #include "hdf_log.h"
14 #include "hdf_touch.h"
15 #include "event_hub.h"
16 #include "input_i2c_ops.h"
17 #include "touch_ft5406.h"
18
19 static FT5406TouchData *g_touchData = NULL;
20
ChipInit(ChipDevice * device)21 static int32_t ChipInit(ChipDevice *device)
22 {
23 (void)device;
24 return HDF_SUCCESS;
25 }
26
ChipResume(ChipDevice * device)27 static int32_t ChipResume(ChipDevice *device)
28 {
29 (void)device;
30 return HDF_SUCCESS;
31 }
32
ChipSuspend(ChipDevice * device)33 static int32_t ChipSuspend(ChipDevice *device)
34 {
35 (void)device;
36 return HDF_SUCCESS;
37 }
38
ChipDetect(ChipDevice * device)39 static int32_t ChipDetect(ChipDevice *device)
40 {
41 uint8_t regAddr;
42 uint8_t regValue[FTS_REG_IDX_MAX] = {0};
43 int32_t ret;
44 InputI2cClient *i2cClient = &device->driver->i2cClient;
45 const int idx0 = 0;
46 const int idx1 = 1;
47 const int idx2 = 2;
48
49 regAddr = FTS_REG_FW_VER;
50 ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value[idx0], 1);
51 CHIP_CHECK_RETURN(ret);
52
53 regAddr = FTS_REG_FW_MIN_VER;
54 ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value[idx1], 1);
55 CHIP_CHECK_RETURN(ret);
56
57 regAddr = FTS_REG_FW_SUB_MIN_VER;
58 ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value[idx2], 1);
59 CHIP_CHECK_RETURN(ret);
60
61 HDF_LOGI("%s: Firmware version = %d.%d.%d", __func__, regValue[idx0], \
62 regValue[idx1], regValue[idx2]);
63
64 (void)ChipInit(device);
65 (void)ChipResume(device);
66 (void)ChipSuspend(device);
67
68 return HDF_SUCCESS;
69 }
70
ParsePointData(ChipDevice * device,FrameData * frame,uint8_t pointNum)71 static int32_t ParsePointData(ChipDevice *device, FrameData *frame, uint8_t pointNum)
72 {
73 int32_t i;
74 int32_t ret;
75 uint8_t regAddr;
76 uint8_t touchId;
77 short fingersX;
78 short fingersY;
79 uint8_t buf[POINT_BUFFER_LEN] = { 0 };
80 InputI2cClient *i2cClient = &device->driver->i2cClient;
81
82 for (i = 0; i < pointNum; i++) {
83 regAddr = FTS_REG_X_H + (i * FT_POINT_SIZE);
84 ret = InputI2cRead(i2cClient, ®Addr, 1, buf, POINT_BUFFER_LEN);
85 if (ret != HDF_SUCCESS) {
86 HDF_LOGE("Unable to fetch data, error: %d\n", ret);
87 return ret;
88 }
89
90 touchId = (buf[FT_POINT_NUM_POS]) >> HALF_BYTE_OFFSET;
91 if (touchId >= MAX_SUPPORT_POINT) {
92 break;
93 }
94
95 fingersX = (short) (buf[FT_X_H_POS] & 0x0F) << ONE_BYTE_OFFSET;
96 frame->fingers[i].x = fingersX | (short) buf[FT_X_L_POS];
97 fingersY = (short) (buf[FT_Y_H_POS] & 0x0F) << ONE_BYTE_OFFSET;
98 frame->fingers[i].y = fingersY | (short) buf[FT_Y_L_POS];
99 frame->fingers[i].x = device->boardCfg->attr.resolutionX - frame->fingers[i].x - 1;
100 frame->fingers[i].y = device->boardCfg->attr.resolutionY - frame->fingers[i].y - 1;
101 frame->fingers[i].trackId = touchId;
102 frame->fingers[i].status = buf[FT_EVENT_POS] >> SIX_BIT_OFFSET;
103 frame->fingers[i].valid = true;
104 frame->definedEvent = frame->fingers[i].status;
105
106 if ((frame->fingers[i].status == TOUCH_DOWN || frame->fingers[i].status == TOUCH_CONTACT) && (pointNum == 0)) {
107 HDF_LOGE("%s: abnormal event data from driver chip", __func__);
108 return HDF_FAILURE;
109 }
110 }
111
112 return HDF_SUCCESS;
113 }
114
ChipDataHandle(ChipDevice * device)115 static int32_t ChipDataHandle(ChipDevice *device)
116 {
117 uint8_t reg = FTS_REG_STATUS;
118 uint8_t touchStatus = 0;
119 static uint8_t lastTouchStatus = 0;
120 uint8_t pointNum = 0;
121 int32_t ret = HDF_SUCCESS;
122 InputI2cClient *i2cClient = &device->driver->i2cClient;
123 FrameData *frame = &device->driver->frameData;
124
125 ret = InputI2cRead(i2cClient, ®, 1, &touchStatus, 1);
126 CHECK_RETURN_VALUE(ret);
127
128 OsalMutexLock(&device->driver->mutex);
129 (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData));
130
131 pointNum = touchStatus & HALF_BYTE_MASK;
132 if (pointNum == 0) {
133 if (lastTouchStatus == 1) {
134 lastTouchStatus = 0;
135 frame->realPointNum = 0;
136 frame->definedEvent = TOUCH_UP;
137 ret = HDF_SUCCESS;
138 } else {
139 ret = HDF_FAILURE;
140 }
141
142 OsalMutexUnlock(&device->driver->mutex);
143 return ret;
144 }
145
146 if (lastTouchStatus != touchStatus) {
147 lastTouchStatus = touchStatus;
148 }
149
150 frame->realPointNum = pointNum;
151 frame->definedEvent = TOUCH_DOWN;
152
153 ret = ParsePointData(device, frame, pointNum);
154 if (ret != HDF_SUCCESS) {
155 HDF_LOGE("%s: ParsePointData fail", __func__);
156 OsalMutexUnlock(&device->driver->mutex);
157 return ret;
158 }
159
160 OsalMutexUnlock(&device->driver->mutex);
161 return ret;
162 }
163
UpdateFirmware(ChipDevice * device)164 static int32_t UpdateFirmware(ChipDevice *device)
165 {
166 return HDF_SUCCESS;
167 }
168
SetAbility(ChipDevice * device)169 static void SetAbility(ChipDevice *device)
170 {
171 device->driver->inputDev->abilitySet.devProp[0] = SET_BIT(INPUT_PROP_DIRECT);
172 device->driver->inputDev->abilitySet.eventType[0] = SET_BIT(EV_SYN) |
173 SET_BIT(EV_KEY) | SET_BIT(EV_ABS);
174 device->driver->inputDev->abilitySet.absCode[0] = SET_BIT(ABS_X) | SET_BIT(ABS_Y);
175 device->driver->inputDev->abilitySet.absCode[1] = SET_BIT(ABS_MT_POSITION_X) |
176 SET_BIT(ABS_MT_POSITION_Y) | SET_BIT(ABS_MT_TRACKING_ID);
177 device->driver->inputDev->abilitySet.keyCode[KEY_CODE_4TH] = SET_BIT(KEY_UP) | SET_BIT(KEY_DOWN);
178 device->driver->inputDev->attrSet.axisInfo[ABS_X].min = 0;
179 device->driver->inputDev->attrSet.axisInfo[ABS_X].max = device->boardCfg->attr.resolutionX - 1;
180 device->driver->inputDev->attrSet.axisInfo[ABS_X].range = 0;
181 device->driver->inputDev->attrSet.axisInfo[ABS_Y].min = 0;
182 device->driver->inputDev->attrSet.axisInfo[ABS_Y].max = device->boardCfg->attr.resolutionY - 1;
183 device->driver->inputDev->attrSet.axisInfo[ABS_Y].range = 0;
184 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].min = 0;
185 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].max = device->boardCfg->attr.resolutionX - 1;
186 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].range = 0;
187 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].min = 0;
188 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].max = device->boardCfg->attr.resolutionY - 1;
189 device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].range = 0;
190 device->driver->inputDev->attrSet.axisInfo[ABS_MT_TRACKING_ID].max = MAX_SUPPORT_POINT;
191 }
192
193 static struct TouchChipOps g_ft5406ChipOps = {
194 .Init = ChipInit,
195 .Detect = ChipDetect,
196 .Resume = ChipResume,
197 .Suspend = ChipSuspend,
198 .DataHandle = ChipDataHandle,
199 .UpdateFirmware = UpdateFirmware,
200 .SetAbility = SetAbility,
201 };
202
ChipTimer(struct timer_list * t)203 static void ChipTimer(struct timer_list *t)
204 {
205 FT5406TouchData *touchData = from_timer(touchData, t, timer);
206
207 schedule_work(&touchData->work_poll);
208 mod_timer(&touchData->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
209 }
210
ChipWorkPoll(struct work_struct * work)211 static void ChipWorkPoll(struct work_struct *work)
212 {
213 FT5406TouchData *touchData = container_of(work, FT5406TouchData, work_poll);
214 TouchDriver *driver = (TouchDriver *)touchData->data;
215 InputDevice *dev = driver->inputDev;
216 FrameData *frame = &driver->frameData;
217 int32_t ret;
218 int32_t i;
219
220 ret = ChipDataHandle(driver->device);
221 if (ret == HDF_SUCCESS) {
222 OsalMutexLock(&driver->mutex);
223 for (i = 0; i < MAX_FINGERS_NUM; i++) {
224 if (frame->fingers[i].valid) {
225 input_report_abs(dev, ABS_MT_POSITION_X, frame->fingers[i].x);
226 input_report_abs(dev, ABS_MT_POSITION_Y, frame->fingers[i].y);
227 input_report_abs(dev, ABS_MT_TRACKING_ID, frame->fingers[i].trackId);
228 input_mt_sync(dev);
229 }
230 }
231
232 if ((frame->definedEvent == TOUCH_DOWN) || (frame->definedEvent == TOUCH_CONTACT)) {
233 input_report_key(dev, BTN_TOUCH, 1); // BTN_TOUCH DOWN
234 } else {
235 input_report_key(dev, BTN_TOUCH, 0); // BTN_TOUCH UP
236 }
237 OsalMutexUnlock(&driver->mutex);
238 input_sync(dev);
239 }
240 }
241
FreeChipConfig(TouchChipCfg * config)242 static void FreeChipConfig(TouchChipCfg *config)
243 {
244 if (config->pwrSeq.pwrOn.buf != NULL) {
245 OsalMemFree(config->pwrSeq.pwrOn.buf);
246 }
247
248 if (config->pwrSeq.pwrOff.buf != NULL) {
249 OsalMemFree(config->pwrSeq.pwrOff.buf);
250 }
251
252 if (config->pwrSeq.resume.buf != NULL) {
253 OsalMemFree(config->pwrSeq.resume.buf);
254 }
255
256 if (config->pwrSeq.suspend.buf != NULL) {
257 OsalMemFree(config->pwrSeq.suspend.buf);
258 }
259
260 OsalMemFree(config);
261 }
262
ChipConfigInstance(struct HdfDeviceObject * device)263 static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device)
264 {
265 TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg));
266 if (chipCfg == NULL) {
267 HDF_LOGE("%s: instance chip config failed", __func__);
268 return NULL;
269 }
270 (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg));
271
272 if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) {
273 HDF_LOGE("%s: parse chip config failed", __func__);
274 OsalMemFree(chipCfg);
275 chipCfg = NULL;
276 }
277 return chipCfg;
278 }
279
ChipDeviceInstance(void)280 static ChipDevice *ChipDeviceInstance(void)
281 {
282 ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice));
283 if (chipDev == NULL) {
284 HDF_LOGE("%s: instance chip device failed", __func__);
285 return NULL;
286 }
287 (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice));
288 return chipDev;
289 }
290
HdfFocalChipInit(struct HdfDeviceObject * device)291 static int32_t HdfFocalChipInit(struct HdfDeviceObject *device)
292 {
293 TouchChipCfg *chipCfg = NULL;
294 ChipDevice *chipDev = NULL;
295
296 if (device == NULL) {
297 HDF_LOGE("%s: device is NULL", __func__);
298 return HDF_ERR_INVALID_PARAM;
299 }
300
301 chipCfg = ChipConfigInstance(device);
302 if (chipCfg == NULL) {
303 HDF_LOGE("%s: ChipConfigInstance is NULL", __func__);
304 return HDF_ERR_MALLOC_FAIL;
305 }
306
307 chipDev = ChipDeviceInstance();
308 if (chipDev == NULL) {
309 HDF_LOGE("%s: ChipDeviceInstance fail", __func__);
310 FreeChipConfig(chipCfg);
311 return HDF_FAILURE;
312 }
313
314 chipDev->chipCfg = chipCfg;
315 chipDev->ops = &g_ft5406ChipOps;
316 chipDev->chipName = chipCfg->chipName;
317 chipDev->vendorName = chipCfg->vendorName;
318 device->priv = (void *)chipDev;
319
320 if (RegisterTouchChipDevice(chipDev) != HDF_SUCCESS) {
321 HDF_LOGE("%s: RegisterTouchChipDevice fail", __func__);
322 OsalMemFree(chipDev);
323 FreeChipConfig(chipCfg);
324 return HDF_FAILURE;
325 }
326
327 g_touchData = (FT5406TouchData *)OsalMemAlloc(sizeof(FT5406TouchData));
328 if (g_touchData == NULL) {
329 HDF_LOGE("OsalMemAlloc touchData failed!");
330 OsalMemFree(chipDev);
331 FreeChipConfig(chipCfg);
332 return HDF_FAILURE;
333 }
334
335 (void)memset_s(g_touchData, sizeof(FT5406TouchData), 0, sizeof(FT5406TouchData));
336
337 if (chipDev->driver != NULL) {
338 g_touchData->data = chipDev->driver;
339 }
340
341 INIT_WORK(&g_touchData->work_poll, ChipWorkPoll);
342 timer_setup(&g_touchData->timer, ChipTimer, 0);
343 g_touchData->timer.expires = jiffies + msecs_to_jiffies(POLL_INTERVAL_MS);
344 add_timer(&g_touchData->timer);
345
346 HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName);
347 return HDF_SUCCESS;
348 }
349
HdfFocalChipRelease(struct HdfDeviceObject * device)350 static void HdfFocalChipRelease(struct HdfDeviceObject *device)
351 {
352 HDF_LOGI("HdfFocalChipRelease enter.");
353
354 if (device == NULL || device->priv == NULL || g_touchData == NULL) {
355 HDF_LOGE("%s: param is null", __func__);
356 return;
357 }
358
359 del_timer_sync(&g_touchData->timer);
360 cancel_work_sync(&g_touchData->work_poll);
361
362 OsalMemFree(g_touchData);
363 g_touchData = NULL;
364
365 return;
366 }
367
368 struct HdfDriverEntry g_touchFocalChipEntry = {
369 .moduleVersion = 1,
370 .moduleName = "HDF_TOUCH_FT5406",
371 .Init = HdfFocalChipInit,
372 .Release = HdfFocalChipRelease,
373 };
374
375 HDF_INIT(g_touchFocalChipEntry);
376