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