• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 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 "gpio_test.h"
10 #include "gpio_if.h"
11 #include "hdf_base.h"
12 #include "hdf_io_service_if.h"
13 #include "hdf_log.h"
14 #include "osal_irq.h"
15 #include "osal_time.h"
16 #include "securec.h"
17 
18 #define HDF_LOG_TAG gpio_test
19 
20 #define GPIO_TEST_IRQ_TIMEOUT 1000
21 #define GPIO_TEST_IRQ_DELAY   200
22 
GpioTestGetConfig(struct GpioTestConfig * config)23 static int32_t GpioTestGetConfig(struct GpioTestConfig *config)
24 {
25     int32_t ret;
26     struct HdfSBuf *reply = NULL;
27     struct HdfIoService *service = NULL;
28     const void *buf = NULL;
29     uint32_t len;
30 
31     HDF_LOGD("%s: enter!", __func__);
32     service = HdfIoServiceBind("GPIO_TEST");
33     if (service == NULL) {
34         HDF_LOGE("%s: failed to bind gpio test server", __func__);
35         return HDF_ERR_NOT_SUPPORT;
36     }
37 
38     reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
39     if (reply == NULL) {
40         HDF_LOGE("%s: failed to obtain reply", __func__);
41         return HDF_ERR_MALLOC_FAIL;
42     }
43 
44     ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
45     if (ret != HDF_SUCCESS) {
46         HDF_LOGE("%s: remote dispatch fail:%d", __func__, ret);
47     }
48 
49     if (!HdfSbufReadBuffer(reply, &buf, &len)) {
50         HDF_LOGE("%s: read buf failed", __func__);
51         HdfSbufRecycle(reply);
52         return HDF_ERR_IO;
53     }
54 
55     if (len != sizeof(*config)) {
56         HDF_LOGE("%s: config size:%u, but read size:%u!", __func__, sizeof(*config), len);
57         HdfSbufRecycle(reply);
58         return HDF_ERR_IO;
59     }
60 
61     if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
62         HDF_LOGE("%s: memcpy buf failed", __func__);
63         HdfSbufRecycle(reply);
64         return HDF_ERR_IO;
65     }
66 
67     HdfSbufRecycle(reply);
68     HDF_LOGD("%s: exit", __func__);
69     HdfIoServiceRecycle(service);
70     return HDF_SUCCESS;
71 }
72 
GpioTesterGet(void)73 static struct GpioTester *GpioTesterGet(void)
74 {
75     int32_t ret;
76     static struct GpioTester tester;
77     static struct GpioTester *pTester = NULL;
78 
79     if (pTester != NULL) {
80         return pTester;
81     }
82 
83     ret = GpioTestGetConfig(&tester.cfg);
84     if (ret != HDF_SUCCESS) {
85         HDF_LOGE("%s: get config failed:%d", __func__, ret);
86         return NULL;
87     }
88     HDF_LOGI("%s: test cfg: gpio=%u, gpioIrq=%u, testUserApi=%u", __func__,
89         tester.cfg.gpio, tester.cfg.gpioIrq, tester.cfg.testUserApi);
90 
91     pTester = &tester;
92     return pTester;
93 }
94 
GpioTestSetUp(void)95 static int32_t GpioTestSetUp(void)
96 {
97     int32_t ret;
98     struct GpioTester *tester = NULL;
99 
100     tester = GpioTesterGet();
101     if (tester == NULL) {
102         HDF_LOGE("%s: get tester failed", __func__);
103         return HDF_ERR_INVALID_OBJECT;
104     }
105 
106     ret = GpioGetDir(tester->cfg.gpio, &tester->oldDir);
107     if (ret != HDF_SUCCESS) {
108         HDF_LOGE("%s: get old dir fail! ret:%d", __func__, ret);
109         return ret;
110     }
111     ret = GpioRead(tester->cfg.gpio, &tester->oldVal);
112     if (ret != HDF_SUCCESS) {
113         HDF_LOGE("%s: read old val fail! ret:%d", __func__, ret);
114         return ret;
115     }
116 
117     tester->fails = 0;
118     tester->irqCnt = 0;
119     tester->irqTimeout = GPIO_TEST_IRQ_TIMEOUT;
120     return HDF_SUCCESS;
121 }
122 
GpioTestTearDown(void)123 static int32_t GpioTestTearDown(void)
124 {
125     int ret;
126     struct GpioTester *tester = NULL;
127 
128     tester = GpioTesterGet();
129     if (tester == NULL) {
130         HDF_LOGE("%s: get tester failed", __func__);
131         return HDF_ERR_INVALID_OBJECT;
132     }
133 
134     ret = GpioSetDir(tester->cfg.gpio, tester->oldDir);
135     if (ret != HDF_SUCCESS) {
136         HDF_LOGE("%s: set old dir fail! ret:%d", __func__, ret);
137         return ret;
138     }
139     if (tester->oldDir == GPIO_DIR_IN) {
140         return HDF_SUCCESS;
141     }
142     ret = GpioWrite(tester->cfg.gpio, tester->oldVal);
143     if (ret != HDF_SUCCESS) {
144         HDF_LOGE("%s: write old val fail! ret:%d", __func__, ret);
145         return ret;
146     }
147 
148     return HDF_SUCCESS;
149 }
150 
GpioTestSetGetDir(void)151 static int32_t GpioTestSetGetDir(void)
152 {
153     int32_t ret;
154     uint16_t dirSet;
155     uint16_t dirGet;
156     struct GpioTester *tester = NULL;
157 
158     tester = GpioTesterGet();
159     if (tester == NULL) {
160         HDF_LOGE("%s: get tester failed", __func__);
161         return HDF_ERR_INVALID_OBJECT;
162     }
163 
164     dirSet = GPIO_DIR_OUT;
165     dirGet = GPIO_DIR_IN;
166 
167     ret = GpioSetDir(tester->cfg.gpio, dirSet);
168     if (ret != HDF_SUCCESS) {
169         HDF_LOGE("%s: set dir fail! ret:%d", __func__, ret);
170         return ret;
171     }
172     ret = GpioGetDir(tester->cfg.gpio, &dirGet);
173     if (ret != HDF_SUCCESS) {
174         HDF_LOGE("%s: get dir fail! ret:%d", __func__, ret);
175         return ret;
176     }
177     if (dirSet != dirGet) {
178         HDF_LOGE("%s: set dir:%u, but get:%u", __func__, dirSet, dirGet);
179         return HDF_FAILURE;
180     }
181     /* change the value and test one more time */
182     dirSet = GPIO_DIR_IN;
183     dirGet = GPIO_DIR_OUT;
184     ret = GpioSetDir(tester->cfg.gpio, dirSet);
185     if (ret != HDF_SUCCESS) {
186         HDF_LOGE("%s: set dir fail! ret:%d", __func__, ret);
187         return ret;
188     }
189     ret = GpioGetDir(tester->cfg.gpio, &dirGet);
190     if (ret != HDF_SUCCESS) {
191         HDF_LOGE("%s: get dir fail! ret:%d", __func__, ret);
192         return ret;
193     }
194     if (dirSet != dirGet) {
195         HDF_LOGE("%s: set dir:%u, but get:%u", __func__, dirSet, dirGet);
196         return HDF_FAILURE;
197     }
198     return HDF_SUCCESS;
199 }
200 
GpioTestWriteRead(void)201 static int32_t GpioTestWriteRead(void)
202 {
203     int32_t ret;
204     uint16_t valWrite;
205     uint16_t valRead;
206     struct GpioTester *tester = NULL;
207 
208     tester = GpioTesterGet();
209     if (tester == NULL) {
210         HDF_LOGE("%s: get tester failed", __func__);
211         return HDF_ERR_INVALID_OBJECT;
212     }
213 
214     ret = GpioSetDir(tester->cfg.gpio, GPIO_DIR_OUT);
215     if (ret != HDF_SUCCESS) {
216         HDF_LOGE("%s: set dir fail! ret:%d", __func__, ret);
217         return ret;
218     }
219     valWrite = GPIO_VAL_LOW;
220     valRead = GPIO_VAL_HIGH;
221 
222     ret = GpioWrite(tester->cfg.gpio, valWrite);
223     if (ret != HDF_SUCCESS) {
224         HDF_LOGE("%s: write val:%u fail! ret:%d", __func__, valWrite, ret);
225         return ret;
226     }
227     ret = GpioRead(tester->cfg.gpio, &valRead);
228     if (ret != HDF_SUCCESS) {
229         HDF_LOGE("%s: read fail! ret:%d", __func__, ret);
230         return ret;
231     }
232     if (valWrite != valRead) {
233         HDF_LOGE("%s: write:%u, but get:%u", __func__, valWrite, valRead);
234         return HDF_FAILURE;
235     }
236     /* change the value and test one more time */
237     valWrite = GPIO_VAL_HIGH;
238     valRead = GPIO_VAL_LOW;
239     ret = GpioWrite(tester->cfg.gpio, valWrite);
240     if (ret != HDF_SUCCESS) {
241         HDF_LOGE("%s: write val:%u fail! ret:%d", __func__, valWrite, ret);
242         return ret;
243     }
244     ret = GpioRead(tester->cfg.gpio, &valRead);
245     if (ret != HDF_SUCCESS) {
246         HDF_LOGE("%s: read fail! ret:%d", __func__, ret);
247         return ret;
248     }
249     if (valWrite != valRead) {
250         HDF_LOGE("%s: write:%u, but get:%u", __func__, valWrite, valRead);
251         return HDF_FAILURE;
252     }
253     return HDF_SUCCESS;
254 }
255 
GpioTestIrqHandler(uint16_t gpio,void * data)256 static int32_t GpioTestIrqHandler(uint16_t gpio, void *data)
257 {
258     struct GpioTester *tester = (struct GpioTester *)data;
259 
260     HDF_LOGE("%s: >>>>>>>>>>>>>>>>>>>>>enter gpio:%u<<<<<<<<<<<<<<<<<<<<<<", __func__, gpio);
261     if (tester != NULL) {
262         tester->irqCnt++;
263         return GpioDisableIrq(gpio);
264     }
265     return HDF_FAILURE;
266 }
267 
GpioTestHelperInversePin(uint16_t gpio,uint16_t mode)268 static inline void GpioTestHelperInversePin(uint16_t gpio, uint16_t mode)
269 {
270     uint16_t dir = 0;
271     uint16_t valRead = 0;
272 
273     (void)GpioRead(gpio, &valRead);
274     (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
275     (void)GpioRead(gpio, &valRead);
276     (void)GpioGetDir(gpio, &dir);
277     HDF_LOGE("%s, gpio:%u, val:%u, dir:%u, mode:%x", __func__, gpio, valRead, dir, mode);
278 }
279 
GpioTestIrqSharedFunc(struct GpioTester * tester,uint16_t mode,bool inverse)280 static int32_t GpioTestIrqSharedFunc(struct GpioTester *tester, uint16_t mode, bool inverse)
281 {
282     int32_t ret;
283     uint32_t timeout;
284 
285     HDF_LOGE("%s: mark gona set irq ...", __func__);
286     ret = GpioSetIrq(tester->cfg.gpioIrq, mode, GpioTestIrqHandler, (void *)tester);
287     if (ret != HDF_SUCCESS) {
288         HDF_LOGE("%s: set irq fail! ret:%d", __func__, ret);
289         return ret;
290     }
291     HDF_LOGE("%s: mark gona enable irq ...", __func__);
292     ret = GpioEnableIrq(tester->cfg.gpioIrq);
293     if (ret != HDF_SUCCESS) {
294         HDF_LOGE("%s: enable irq fail! ret:%d", __func__, ret);
295         (void)GpioUnsetIrq(tester->cfg.gpioIrq, tester);
296         return ret;
297     }
298 
299     HDF_LOGE("%s: mark gona inverse irq ...", __func__);
300     for (timeout = 0; tester->irqCnt <= 0 && timeout <= tester->irqTimeout;
301         timeout += GPIO_TEST_IRQ_DELAY) {
302         if (inverse) {
303             // maybe can make a inverse ...
304             GpioTestHelperInversePin(tester->cfg.gpioIrq, mode);
305         }
306         OsalMSleep(GPIO_TEST_IRQ_DELAY);
307     }
308     (void)GpioUnsetIrq(tester->cfg.gpioIrq, tester);
309 
310 #if defined(_LINUX_USER_) || defined(__KERNEL__)
311     if (inverse) {
312         HDF_LOGI("%s: do not judge edge trigger!", __func__);
313         return HDF_SUCCESS;
314     }
315 #endif
316     if (tester->irqCnt <= 0) {
317         HDF_LOGE("%s: set mode:%x on %u failed", __func__, mode, tester->cfg.gpioIrq);
318         return HDF_FAILURE;
319     }
320     return HDF_SUCCESS;
321 }
322 
GpioTestIrqLevel(void)323 static int32_t GpioTestIrqLevel(void)
324 {
325     return HDF_SUCCESS;
326 }
327 
GpioTestIrqEdge(void)328 static int32_t GpioTestIrqEdge(void)
329 {
330 #if defined(_LINUX_USER_) || defined(__USER__)
331     (void)GpioTestIrqSharedFunc;
332     return HDF_SUCCESS;
333 #else
334     uint16_t mode;
335     struct GpioTester *tester = NULL;
336 
337     tester = GpioTesterGet();
338     if (tester == NULL) {
339         HDF_LOGE("%s: get tester failed", __func__);
340         return HDF_ERR_INVALID_OBJECT;
341     }
342 
343     /* set dir to out for self trigger on liteos */
344 #if defined(_LINUX_USER_) || defined(__KERNEL__)
345     (void)GpioSetDir(tester->cfg.gpioIrq, GPIO_DIR_IN);
346 #else
347     (void)GpioSetDir(tester->cfg.gpioIrq, GPIO_DIR_OUT);
348 #endif
349     mode = GPIO_IRQ_TRIGGER_FALLING | GPIO_IRQ_TRIGGER_RISING;
350     return GpioTestIrqSharedFunc(tester, mode, true);
351 #endif
352 }
353 
GpioTestIrqThread(void)354 int32_t GpioTestIrqThread(void)
355 {
356 #if defined(_LINUX_USER_) || defined(__USER__)
357     return HDF_SUCCESS;
358 #else
359     uint16_t mode;
360     struct GpioTester *tester = NULL;
361 
362     tester = GpioTesterGet();
363     if (tester == NULL) {
364         HDF_LOGE("%s: get tester failed", __func__);
365         return HDF_ERR_INVALID_OBJECT;
366     }
367 
368     /* set dir to out for self trigger on liteos */
369 #if defined(_LINUX_USER_) || defined(__KERNEL__)
370     (void)GpioSetDir(tester->cfg.gpioIrq, GPIO_DIR_IN);
371 #else
372     (void)GpioSetDir(tester->cfg.gpioIrq, GPIO_DIR_OUT);
373 #endif
374     mode = GPIO_IRQ_TRIGGER_FALLING | GPIO_IRQ_TRIGGER_RISING | GPIO_IRQ_USING_THREAD;
375     return GpioTestIrqSharedFunc(tester, mode, true);
376 #endif
377 }
378 
GpioTestReliability(void)379 static int32_t GpioTestReliability(void)
380 {
381     uint16_t val = 0;
382     struct GpioTester *tester = NULL;
383 
384     tester = GpioTesterGet();
385     if (tester == NULL) {
386         HDF_LOGE("%s: get tester failed", __func__);
387         return HDF_ERR_INVALID_OBJECT;
388     }
389 
390     (void)GpioWrite(-1, val);              /* invalid gpio number */
391     (void)GpioWrite(tester->cfg.gpio, -1);     /* invalid gpio value */
392 
393     (void)GpioRead(-1, &val);              /* invalid gpio number */
394     (void)GpioRead(tester->cfg.gpio, NULL);    /* invalid pointer */
395 
396     (void)GpioSetDir(-1, val);             /* invalid gpio number */
397     (void)GpioSetDir(tester->cfg.gpio, -1);    /* invalid value */
398 
399     (void)GpioGetDir(-1, &val);            /* invalid gpio number */
400     (void)GpioGetDir(tester->cfg.gpio, NULL);  /* invalid pointer */
401 
402     /* invalid gpio number */
403     (void)GpioSetIrq(-1, OSAL_IRQF_TRIGGER_RISING, GpioTestIrqHandler, (void *)tester);
404     /* invalid irq handler */
405     (void)GpioSetIrq(tester->cfg.gpioIrq, OSAL_IRQF_TRIGGER_RISING, NULL, (void *)tester);
406 
407     (void)GpioUnsetIrq(-1, NULL);          /* invalid gpio number */
408 
409     (void)GpioEnableIrq(-1);               /* invalid gpio number */
410 
411     (void)GpioDisableIrq(-1);              /* invalid gpio number */
412 
413     return HDF_SUCCESS;
414 }
415 
GpioIfPerformanceTest(void)416 static int32_t GpioIfPerformanceTest(void)
417 {
418 #ifdef __LITEOS__
419     return HDF_SUCCESS;
420 #endif
421     uint16_t val;
422     uint64_t startMs;
423     uint64_t endMs;
424     uint64_t useTime;    // ms
425     struct GpioTester *tester = NULL;
426 
427     tester = GpioTesterGet();
428     if (tester == NULL) {
429         HDF_LOGE("%s: get tester failed", __func__);
430         return HDF_ERR_INVALID_OBJECT;
431     }
432 
433     startMs = OsalGetSysTimeMs();
434     GpioRead(tester->cfg.gpio, &val);
435     endMs = OsalGetSysTimeMs();
436 
437     useTime = endMs - startMs;
438     HDF_LOGI("----->interface performance test:[start:%lld(ms) - end:%lld(ms) = %lld (ms)] < 1ms[%d]\r\n",
439         startMs, endMs, useTime, useTime < 1 ? true : false);
440     return HDF_SUCCESS;
441 }
442 
443 struct GpioTestEntry {
444     int cmd;
445     int32_t (*func)(void);
446     const char *name;
447 };
448 
449 static struct GpioTestEntry g_entry[] = {
450     { GPIO_TEST_SET_GET_DIR, GpioTestSetGetDir, "GpioTestSetGetDir" },
451     { GPIO_TEST_WRITE_READ, GpioTestWriteRead, "GpioTestWriteRead" },
452     { GPIO_TEST_IRQ_LEVEL, GpioTestIrqLevel, "GpioTestIrqLevel" },
453     { GPIO_TEST_IRQ_EDGE, GpioTestIrqEdge, "GpioTestIrqEdge" },
454     { GPIO_TEST_IRQ_THREAD, GpioTestIrqThread, "GpioTestIrqThread" },
455     { GPIO_TEST_RELIABILITY, GpioTestReliability, "GpioTestReliability" },
456     { GPIO_TEST_PERFORMANCE, GpioIfPerformanceTest, "GpioIfPerformanceTest" },
457 };
458 
GpioTestExecute(int cmd)459 int32_t GpioTestExecute(int cmd)
460 {
461     uint32_t i;
462     int32_t ret = HDF_ERR_NOT_SUPPORT;
463 
464 #if defined(_LINUX_USER_) || defined(__USER__)
465     struct GpioTester *tester = GpioTesterGet();
466     if (tester == NULL) {
467         HDF_LOGI("%s: tester is null", __func__);
468         return HDF_SUCCESS;
469     }
470     if (tester->cfg.testUserApi == 0) {
471         HDF_LOGI("%s: do not test user api", __func__);
472         return HDF_SUCCESS;
473     }
474 #endif
475 
476     for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
477         if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
478             continue;
479         }
480         ret = GpioTestSetUp();
481         if (ret != HDF_SUCCESS) {
482             HDF_LOGE("%s: setup failed", __func__);
483             return ret;
484         }
485 
486         ret = g_entry[i].func();
487 
488         (void)GpioTestTearDown();
489         break;
490     }
491 
492     if (ret == HDF_ERR_NOT_SUPPORT) {
493         HDF_LOGE("%s: cmd:%d not supportted", __func__, cmd);
494     }
495 
496     HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
497     return ret;
498 }
499 
GpioTestExecuteAll(void)500 void GpioTestExecuteAll(void)
501 {
502     int32_t i;
503     int32_t ret;
504     int32_t fails = 0;
505 
506     for (i = 0; i < GPIO_TEST_MAX; i++) {
507         ret = GpioTestExecute(i);
508         fails += (ret != HDF_SUCCESS) ? 1 : 0;
509     }
510 
511     HDF_LOGE("%s: **********PASS:%d  FAIL:%d************\n\n",
512         __func__, GPIO_TEST_MAX - fails, fails);
513 }
514