common_library: gettid is multiple declaration in cl_error
[staging/basesystem.git] / video_in_hal / usb_hal / src / usb_hal.cpp
1 /*
2  * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Information.
19  * This source code is a sample source code .
20  * Implementation of the function must be performed by the vendor.
21  */
22
23 #include "usb_hal.h"
24 #include "usb_hal_internal.h"
25 #include "usb_hal_debug.h"
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <stdio.h>
33
34 /**
35  * USB role switch information table
36  */
37 const UsbRoleSwitchInfo kUsbRoleSwitchTable = {USB_ROLE_FILE, USB_HOST_STRING, USB_FUNCTION_STRING};
38
39 /**
40  * Read content of USB role switch file, then determine HOST/FUNCTION role
41  * according to the specified HOST/FUNCTION value.
42  */
43 static EFrameworkunifiedStatus GetUsbRoleType(const char* file_path, const char* usb_host_value, const char* usb_function_value,
44                                  UsbRoleType* usb_role) {
45   if (!file_path || !usb_host_value || !usb_function_value || !usb_role) {
46     USB_ERROR_LOG("parameter is NULL.");
47     return eFrameworkunifiedStatusFail;
48   }
49
50   // 1. open role switch file
51   int fd = open(file_path, O_RDONLY);
52   if (-1 == fd) {
53     USB_ERROR_LOG("open [%s] failed.(%d, %s)", file_path, errno, strerror(errno));
54     return eFrameworkunifiedStatusFail;
55   }
56
57   // 2. read file content
58   char file_content[FILE_CONTENT_LENGTH];
59   memset(file_content, 0, sizeof(file_content));
60   ssize_t ret = read(fd, file_content, sizeof(file_content) - 1);
61   int read_error = errno;
62
63   // 3. close file
64   close(fd);
65
66   if (-1 == ret) {
67     USB_ERROR_LOG("read failed.(%d, %s)", read_error, strerror(read_error));
68     return eFrameworkunifiedStatusFail;
69   }
70
71   // 4. compare file content to HOST/FUNCTION value
72   if (!strcmp(usb_host_value, file_content)) {
73     *usb_role = USB_ROLE_HOST;
74   } else if (!strcmp(usb_function_value, file_content)) {
75     *usb_role = USB_ROLE_FUNCTION;
76   } else {
77     USB_ERROR_LOG("content error.[%s]", file_content);
78     return eFrameworkunifiedStatusFail;
79   }
80
81   return eFrameworkunifiedStatusOK;
82 }
83
84 /**
85  * Write the specified role value to USB role switch file.
86  */
87 static EFrameworkunifiedStatus SetUsbRoleValue(const char* file_path, const char* role_value) {
88   if (!file_path || !role_value) {
89     USB_ERROR_LOG("parameter is NULL.");
90     return eFrameworkunifiedStatusFail;
91   }
92
93   // 1. open role switch file
94   int fd = open(file_path, O_WRONLY | O_TRUNC);
95   if (-1 == fd) {
96     USB_ERROR_LOG("open [%s] failed.(%d, %s)", file_path, errno, strerror(errno));
97     return eFrameworkunifiedStatusFail;
98   }
99
100   // 2. write role file
101   ssize_t ret = write(fd, role_value, strlen(role_value));
102   int write_error = errno;
103
104   // 3. close file
105   close(fd);
106
107   // 4. check write result
108   if (static_cast<ssize_t>(strlen(role_value)) != ret) {
109     USB_ERROR_LOG("write [%s] failed, ret=%zd.(%d, %s)", role_value, ret, write_error, strerror(write_error));
110     return eFrameworkunifiedStatusFail;
111   } else {
112     return eFrameworkunifiedStatusOK;
113   }
114 }
115
116 /**
117  * Check whether the specified USB port supports power control.
118  */
119 static bool CheckSupportPowerControl(UsbPortNumber usb_port_no) {
120   if (USB_PORT_NUMBER_MAX <= usb_port_no) {
121     return false;
122   }
123
124   return true;
125 }
126
127 /**
128  * Check whether the specified gpio port is available.
129  */
130 static bool CheckGpioPortAvailable(UsbGpioPort gpio_port) {
131   if (USB_GPIO_PORT_MAX <= gpio_port) {
132     USB_ERROR_LOG("port %d is invalid.", gpio_port);
133     return false;
134   }
135
136   if (!kUsbGpioInfo[gpio_port].port_name || (0 == strlen(kUsbGpioInfo[gpio_port].port_name))) {
137     USB_ERROR_LOG("port %d is not available.", gpio_port);
138     return false;
139   }
140
141   return true;
142 }
143
144 /**
145  * Open gpio export file.
146  */
147 static int OpenExportFile() {
148   return open(kUsbGpioExportFile, O_WRONLY);
149 }
150
151 /**
152  * Open the direction file of the specified gpio port.
153  */
154 static int OpenDirectionFile(const char* port_name) {
155   if (!port_name || (0 == strlen(port_name))) {
156     USB_ERROR_LOG("port name is invalid.");
157     return -1;
158   }
159
160   char dir_file[FILE_PATH_LENGTH];
161   // /sys/class/gpio/gpio123/direction
162   snprintf(dir_file, sizeof(dir_file), "%s%s%s", kUsbGpioFilePrefix, port_name, kUsbGpioDirectionFile);
163   return open(dir_file, O_RDWR);
164 }
165
166 /**
167  * Open the value file of the specified gpio port.
168  */
169 static int OpenValueFile(const char* port_name, bool ro) {
170   if (!port_name || (0 == strlen(port_name))) {
171     USB_ERROR_LOG("port name is invalid.");
172     return -1;
173   }
174
175   char value_file[FILE_PATH_LENGTH];
176   // /sys/class/gpio/gpio123/value
177   snprintf(value_file, sizeof(value_file), "%s%s%s", kUsbGpioFilePrefix, port_name, kUsbGpioValueFile);
178   return open(value_file, ro ? O_RDONLY : O_RDWR);
179 }
180
181 /**
182  * Initialize gpio port value.
183  */
184 static EFrameworkunifiedStatus InitializeGpioPort(UsbGpioPort gpio_port) {
185   if (!CheckGpioPortAvailable(gpio_port)) {
186     return eFrameworkunifiedStatusFail;
187   }
188
189   char port_file[FILE_PATH_LENGTH];
190   snprintf(port_file, sizeof(port_file), "%s%s", kUsbGpioFilePrefix, kUsbGpioInfo[gpio_port].port_name);
191
192   // check if port is exported already
193   if (0 == access(port_file, F_OK)) {
194     return eFrameworkunifiedStatusOK;
195   }
196
197   // open the export file
198   int export_fd = OpenExportFile();
199   if (-1 == export_fd) {
200     USB_ERROR_LOG("open [%s] failed.(%d, %s)", "export", errno, strerror(errno));
201     return eFrameworkunifiedStatusFail;
202   }
203
204   // do export by writing the export file
205   ssize_t ret = write(export_fd, kUsbGpioInfo[gpio_port].port_name, strlen(kUsbGpioInfo[gpio_port].port_name));
206   int write_error = errno;
207
208   // close the export file
209   close(export_fd);
210
211   // check write result
212   if (static_cast<ssize_t>(strlen(kUsbGpioInfo[gpio_port].port_name)) != ret) {
213     USB_ERROR_LOG("write [%s] failed, ret=%zd.(%d, %s)", kUsbGpioInfo[gpio_port].port_name, ret, write_error,
214                   strerror(write_error));
215     return eFrameworkunifiedStatusFail;
216   }
217
218   // open the direction file
219   int direction_fd = OpenDirectionFile(kUsbGpioInfo[gpio_port].port_name);
220   if (-1 == direction_fd) {
221     USB_ERROR_LOG("open direction file failed.(%d, %s)", errno, strerror(errno));
222     return eFrameworkunifiedStatusFail;
223   }
224
225   // set direction
226   const char* direction_value;
227   if (!kUsbGpioInfo[gpio_port].is_output) {
228     // for input port, set direction as "in"
229     direction_value = kUsbGpioDirectionIn;
230   } else {
231     if (kUsbGpioHighValue == kUsbGpioInfo[gpio_port].default_value) {
232       // for output port, if default value is high, set direction as "high"
233       direction_value = kUsbGpioDirectionHigh;
234     } else if (kUsbGpioLowValue == kUsbGpioInfo[gpio_port].default_value) {
235       // for output port, if default value is low, set direction as "low"
236       direction_value = kUsbGpioDirectionLow;
237     } else {
238       USB_ERROR_LOG("unknown default value[%c]", kUsbGpioInfo[gpio_port].default_value);
239       return eFrameworkunifiedStatusFail;
240     }
241   }
242
243   ret = write(direction_fd, direction_value, strlen(direction_value));
244   write_error = errno;
245   close(direction_fd);
246   if (static_cast<ssize_t>(strlen(direction_value)) != ret) {
247     USB_ERROR_LOG("write direction %s failed, ret=%zd.(%d, %s)", direction_value, ret, write_error,
248                   strerror(write_error));
249     return eFrameworkunifiedStatusFail;
250   }
251
252   return eFrameworkunifiedStatusOK;
253 }
254
255 /**
256  * Get gpio port value.
257  */
258 static EFrameworkunifiedStatus GetGpioPortValue(UsbGpioPort port_name, bool* port_value) {
259   if ((USB_GPIO_PORT_MAX <= port_name) || !port_value) {
260     USB_ERROR_LOG("parameter is invalid.");
261     return eFrameworkunifiedStatusFail;
262   }
263
264   // initialize gpio port
265   EFrameworkunifiedStatus result = InitializeGpioPort(port_name);
266   if (eFrameworkunifiedStatusOK != result) {
267     return result;
268   }
269
270   // open port value file
271   int fd = OpenValueFile(kUsbGpioInfo[port_name].port_name, true);
272   if (-1 == fd) {
273     USB_ERROR_LOG("open value file failed.(%d, %s)", errno, strerror(errno));
274     return eFrameworkunifiedStatusFail;
275   }
276
277   // read file content
278   char file_content = '\0';
279   ssize_t ret = read(fd, &file_content, sizeof(file_content));
280   int read_error = errno;
281
282   // close file
283   close(fd);
284
285   if (sizeof(file_content) != ret) {
286     USB_ERROR_LOG("read failed.(%d, %s)", read_error, strerror(read_error));
287     return eFrameworkunifiedStatusFail;
288   }
289
290   // compare file content to high/low value
291   if (kUsbGpioHighValue == file_content) {
292     *port_value = (kUsbGpioInfo[port_name].active_low ? false : true);
293   } else if (kUsbGpioLowValue == file_content) {
294     *port_value = (kUsbGpioInfo[port_name].active_low ? true : false);
295   } else {
296     USB_ERROR_LOG("content error.[%c]", file_content);
297     return eFrameworkunifiedStatusFail;
298   }
299
300   return eFrameworkunifiedStatusOK;
301 }
302
303 /**
304  * Set gpio port value.
305  */
306 static EFrameworkunifiedStatus SetGpioPortValue(UsbGpioPort port_name, GpioPortValue port_value) {
307   if (USB_GPIO_PORT_MAX <= port_name) {
308     USB_ERROR_LOG("parameter is invalid.");
309     return eFrameworkunifiedStatusFail;
310   }
311
312   // initialize gpio port
313   EFrameworkunifiedStatus result = InitializeGpioPort(port_name);
314   if (eFrameworkunifiedStatusOK != result) {
315     return result;
316   }
317
318   // check direction is output
319   if (!kUsbGpioInfo[port_name].is_output) {
320     USB_ERROR_LOG("%d not an output port.", port_name);
321     return eFrameworkunifiedStatusFail;
322   }
323
324   // open port value file
325   int fd = OpenValueFile(kUsbGpioInfo[port_name].port_name, false);
326   if (-1 == fd) {
327     USB_ERROR_LOG("open value file failed.(%d, %s)", errno, strerror(errno));
328     return eFrameworkunifiedStatusFail;
329   }
330
331   // write value
332   bool port_active = (GPIO_PORT_ON == port_value ? true : false);
333   bool write_low = (kUsbGpioInfo[port_name].active_low ? port_active : !port_active);
334   char write_value = (write_low ? kUsbGpioLowValue : kUsbGpioHighValue);
335   ssize_t ret = write(fd, &write_value, sizeof(write_value));
336   int write_error = errno;
337
338   // close file
339   close(fd);
340
341   // check write result
342   if (sizeof(write_value) != ret) {
343     USB_ERROR_LOG("write [%c] failed, ret=%zd.(%d, %s)", write_value, ret, write_error, strerror(write_error));
344     return eFrameworkunifiedStatusFail;
345   } else {
346     return eFrameworkunifiedStatusOK;
347   }
348 }
349
350 /**
351  * Check overcurrent.
352  */
353 static EFrameworkunifiedStatus CheckUsbOvercurrent(UsbPortNumber usb_port_no, bool* is_ovc) {
354   if ((USB_PORT_NUMBER_MAX <= usb_port_no) || !is_ovc) {
355     return eFrameworkunifiedStatusFail;
356   }
357
358   return GetGpioPortValue(kUsbOvercurrentGpio[usb_port_no], is_ovc);
359 }
360
361 EFrameworkunifiedStatus GetUsbRoleSwitch(UsbRoleType* usb_role) {
362   // check NULL pointer
363   if (!usb_role) {
364     USB_ERROR_LOG("parameter is NULL.");
365     return eFrameworkunifiedStatusNullPointer;
366   }
367
368   return GetUsbRoleType(kUsbRoleSwitchTable.file_path, kUsbRoleSwitchTable.usb_host_value,
369                         kUsbRoleSwitchTable.usb_function_value, usb_role);
370 }
371
372 EFrameworkunifiedStatus SetUsbRoleSwitch(UsbRoleType usb_role) {
373   if ((USB_ROLE_HOST != usb_role) && (USB_ROLE_FUNCTION != usb_role)) {
374     USB_ERROR_LOG("parameter error.[%d]", usb_role);
375     return eFrameworkunifiedStatusInvldParam;
376   }
377
378   // check current usb role:
379   // allow to switch only when usb_role is different from current usb role.
380   UsbRoleType current_role;
381   if (eFrameworkunifiedStatusOK != GetUsbRoleSwitch(&current_role)) {
382     return eFrameworkunifiedStatusFail;
383   }
384
385   if (current_role == usb_role) {
386     return eFrameworkunifiedStatusOK;
387   }
388
389   // check usb role type
390   //  - HOST: write HOST value to role file
391   //  - FUNCTION: write FUNCTION value to role file
392   return SetUsbRoleValue(kUsbRoleSwitchTable.file_path, (USB_ROLE_HOST == usb_role)
393                                                             ? kUsbRoleSwitchTable.usb_host_value
394                                                             : kUsbRoleSwitchTable.usb_function_value);
395 }
396
397 EFrameworkunifiedStatus CheckUsbAuthenticationError(UsbAuthenticationError* usb_auth_error) {
398   // check NULL pointer
399   if (!usb_auth_error) {
400     USB_ERROR_LOG("parameter is NULL.");
401     return eFrameworkunifiedStatusNullPointer;
402   }
403
404   // Empty Stub implementations
405   *usb_auth_error = USB_AUTHENTICATION_ERROR_NONE;
406   return eFrameworkunifiedStatusOK;
407 }
408
409 EFrameworkunifiedStatus ResetUsbVbus(UsbPortNumber usb_port_no) {
410   // check support power control
411   if (!CheckSupportPowerControl(usb_port_no)) {
412     return eFrameworkunifiedStatusInvldParam;
413   }
414
415   // step 1: power off USB port
416   EFrameworkunifiedStatus result = SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_OFF);
417   if (eFrameworkunifiedStatusOK != result) {
418     USB_ERROR_LOG("power off USB%d failed.", usb_port_no);
419     return result;
420   }
421
422   // step 2: sleep 1.1 sec
423   usleep(1100 * 1000);
424
425   // step 3: power on USB port
426   result = SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_ON);
427   if (eFrameworkunifiedStatusOK != result) {
428     USB_ERROR_LOG("power on USB%d failed.", usb_port_no);
429   }
430   return result;
431 }
432
433 EFrameworkunifiedStatus IsUsbPortPowered(UsbPortNumber usb_port_no, bool* is_powered) {
434   if (!is_powered) {
435     return eFrameworkunifiedStatusNullPointer;
436   }
437
438   // check support power control
439   if (!CheckSupportPowerControl(usb_port_no)) {
440     return eFrameworkunifiedStatusInvldParam;
441   }
442
443   return GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], is_powered);
444 }
445
446 EFrameworkunifiedStatus PowerOnUsbPort(UsbPortNumber usb_port_no) {
447   // check support power control
448   if (!CheckSupportPowerControl(usb_port_no)) {
449     return eFrameworkunifiedStatusInvldParam;
450   }
451   bool current_power = false;
452   if (eFrameworkunifiedStatusOK != GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], &current_power)) {
453     return eFrameworkunifiedStatusFail;
454   }
455
456   if (current_power) {
457     return eFrameworkunifiedStatusOK;
458   }
459   return SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_ON);
460 }
461
462 EFrameworkunifiedStatus PowerOffUsbPort(UsbPortNumber usb_port_no) {
463   // check support power control
464   if (!CheckSupportPowerControl(usb_port_no)) {
465     return eFrameworkunifiedStatusInvldParam;
466   }
467   bool current_power = false;
468   if (eFrameworkunifiedStatusOK != GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], &current_power)) {
469     return eFrameworkunifiedStatusFail;
470   }
471
472   if (!current_power) {
473     return eFrameworkunifiedStatusOK;
474   }
475
476   return SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_OFF);
477 }
478
479 EFrameworkunifiedStatus CheckUsbAbnormalStatus(UsbPortNumber usb_port_no, UsbAbnormalStatus* usb_abnormal_status) {
480   if (USB_PORT_NUMBER_MAX <= usb_port_no) {
481     return eFrameworkunifiedStatusInvldParam;
482   }
483
484   // check NULL pointer
485   if (!usb_abnormal_status) {
486     return eFrameworkunifiedStatusNullPointer;
487   }
488
489   // check overcurrent
490   bool is_ovc = false;
491   EFrameworkunifiedStatus result = CheckUsbOvercurrent(usb_port_no, &is_ovc);
492   if (eFrameworkunifiedStatusOK == result) {
493     if (is_ovc) {
494       *usb_abnormal_status = USB_ABNORMAL_STATUS_OVERCURRENT;
495     } else {
496       *usb_abnormal_status = USB_ABNORMAL_STATUS_NONE;
497     }
498   }
499   return result;
500 }