From 17cf21bcf8a2e29d2cbcf0a313474d2a4ee44f5d Mon Sep 17 00:00:00 2001 From: Tadao Tanikawa Date: Fri, 20 Nov 2020 23:36:23 +0900 Subject: Re-organized sub-directory by category Since all the sub-directories were placed in the first level, created sub-directories, "hal", "module", and "service" for classification and relocated each component. Signed-off-by: Tadao Tanikawa Change-Id: Ifdf743ac0d1893bd8e445455cf0d2c199a011d5c --- hal/usb_hal/src/usb_hal.cpp | 500 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100755 hal/usb_hal/src/usb_hal.cpp (limited to 'hal/usb_hal/src/usb_hal.cpp') diff --git a/hal/usb_hal/src/usb_hal.cpp b/hal/usb_hal/src/usb_hal.cpp new file mode 100755 index 0000000..7e09ad4 --- /dev/null +++ b/hal/usb_hal/src/usb_hal.cpp @@ -0,0 +1,500 @@ +/* + * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Information. + * This source code is a sample source code . + * Implementation of the function must be performed by the vendor. + */ + +#include "usb_hal.h" +#include "usb_hal_internal.h" +#include "usb_hal_debug.h" +#include +#include +#include +#include +#include +#include +#include + +/** + * USB role switch information table + */ +const UsbRoleSwitchInfo kUsbRoleSwitchTable = {USB_ROLE_FILE, USB_HOST_STRING, USB_FUNCTION_STRING}; + +/** + * Read content of USB role switch file, then determine HOST/FUNCTION role + * according to the specified HOST/FUNCTION value. + */ +static EFrameworkunifiedStatus GetUsbRoleType(const char* file_path, const char* usb_host_value, const char* usb_function_value, + UsbRoleType* usb_role) { + if (!file_path || !usb_host_value || !usb_function_value || !usb_role) { + USB_ERROR_LOG("parameter is NULL."); + return eFrameworkunifiedStatusFail; + } + + // 1. open role switch file + int fd = open(file_path, O_RDONLY); + if (-1 == fd) { + USB_ERROR_LOG("open [%s] failed.(%d, %s)", file_path, errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // 2. read file content + char file_content[FILE_CONTENT_LENGTH]; + memset(file_content, 0, sizeof(file_content)); + ssize_t ret = read(fd, file_content, sizeof(file_content) - 1); + int read_error = errno; + + // 3. close file + close(fd); + + if (-1 == ret) { + USB_ERROR_LOG("read failed.(%d, %s)", read_error, strerror(read_error)); + return eFrameworkunifiedStatusFail; + } + + // 4. compare file content to HOST/FUNCTION value + if (!strcmp(usb_host_value, file_content)) { + *usb_role = USB_ROLE_HOST; + } else if (!strcmp(usb_function_value, file_content)) { + *usb_role = USB_ROLE_FUNCTION; + } else { + USB_ERROR_LOG("content error.[%s]", file_content); + return eFrameworkunifiedStatusFail; + } + + return eFrameworkunifiedStatusOK; +} + +/** + * Write the specified role value to USB role switch file. + */ +static EFrameworkunifiedStatus SetUsbRoleValue(const char* file_path, const char* role_value) { + if (!file_path || !role_value) { + USB_ERROR_LOG("parameter is NULL."); + return eFrameworkunifiedStatusFail; + } + + // 1. open role switch file + int fd = open(file_path, O_WRONLY | O_TRUNC); + if (-1 == fd) { + USB_ERROR_LOG("open [%s] failed.(%d, %s)", file_path, errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // 2. write role file + ssize_t ret = write(fd, role_value, strlen(role_value)); + int write_error = errno; + + // 3. close file + close(fd); + + // 4. check write result + if (static_cast(strlen(role_value)) != ret) { + USB_ERROR_LOG("write [%s] failed, ret=%zd.(%d, %s)", role_value, ret, write_error, strerror(write_error)); + return eFrameworkunifiedStatusFail; + } else { + return eFrameworkunifiedStatusOK; + } +} + +/** + * Check whether the specified USB port supports power control. + */ +static bool CheckSupportPowerControl(UsbPortNumber usb_port_no) { + if (USB_PORT_NUMBER_MAX <= usb_port_no) { + return false; + } + + return true; +} + +/** + * Check whether the specified gpio port is available. + */ +static bool CheckGpioPortAvailable(UsbGpioPort gpio_port) { + if (USB_GPIO_PORT_MAX <= gpio_port) { + USB_ERROR_LOG("port %d is invalid.", gpio_port); + return false; + } + + if (!kUsbGpioInfo[gpio_port].port_name || (0 == strlen(kUsbGpioInfo[gpio_port].port_name))) { + USB_ERROR_LOG("port %d is not available.", gpio_port); + return false; + } + + return true; +} + +/** + * Open gpio export file. + */ +static int OpenExportFile() { + return open(kUsbGpioExportFile, O_WRONLY); +} + +/** + * Open the direction file of the specified gpio port. + */ +static int OpenDirectionFile(const char* port_name) { + if (!port_name || (0 == strlen(port_name))) { + USB_ERROR_LOG("port name is invalid."); + return -1; + } + + char dir_file[FILE_PATH_LENGTH]; + // /sys/class/gpio/gpio123/direction + snprintf(dir_file, sizeof(dir_file), "%s%s%s", kUsbGpioFilePrefix, port_name, kUsbGpioDirectionFile); + return open(dir_file, O_RDWR); +} + +/** + * Open the value file of the specified gpio port. + */ +static int OpenValueFile(const char* port_name, bool ro) { + if (!port_name || (0 == strlen(port_name))) { + USB_ERROR_LOG("port name is invalid."); + return -1; + } + + char value_file[FILE_PATH_LENGTH]; + // /sys/class/gpio/gpio123/value + snprintf(value_file, sizeof(value_file), "%s%s%s", kUsbGpioFilePrefix, port_name, kUsbGpioValueFile); + return open(value_file, ro ? O_RDONLY : O_RDWR); +} + +/** + * Initialize gpio port value. + */ +static EFrameworkunifiedStatus InitializeGpioPort(UsbGpioPort gpio_port) { + if (!CheckGpioPortAvailable(gpio_port)) { + return eFrameworkunifiedStatusFail; + } + + char port_file[FILE_PATH_LENGTH]; + snprintf(port_file, sizeof(port_file), "%s%s", kUsbGpioFilePrefix, kUsbGpioInfo[gpio_port].port_name); + + // check if port is exported already + if (0 == access(port_file, F_OK)) { + return eFrameworkunifiedStatusOK; + } + + // open the export file + int export_fd = OpenExportFile(); + if (-1 == export_fd) { + USB_ERROR_LOG("open [%s] failed.(%d, %s)", "export", errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // do export by writing the export file + ssize_t ret = write(export_fd, kUsbGpioInfo[gpio_port].port_name, strlen(kUsbGpioInfo[gpio_port].port_name)); + int write_error = errno; + + // close the export file + close(export_fd); + + // check write result + if (static_cast(strlen(kUsbGpioInfo[gpio_port].port_name)) != ret) { + USB_ERROR_LOG("write [%s] failed, ret=%zd.(%d, %s)", kUsbGpioInfo[gpio_port].port_name, ret, write_error, + strerror(write_error)); + return eFrameworkunifiedStatusFail; + } + + // open the direction file + int direction_fd = OpenDirectionFile(kUsbGpioInfo[gpio_port].port_name); + if (-1 == direction_fd) { + USB_ERROR_LOG("open direction file failed.(%d, %s)", errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // set direction + const char* direction_value; + if (!kUsbGpioInfo[gpio_port].is_output) { + // for input port, set direction as "in" + direction_value = kUsbGpioDirectionIn; + } else { + if (kUsbGpioHighValue == kUsbGpioInfo[gpio_port].default_value) { + // for output port, if default value is high, set direction as "high" + direction_value = kUsbGpioDirectionHigh; + } else if (kUsbGpioLowValue == kUsbGpioInfo[gpio_port].default_value) { + // for output port, if default value is low, set direction as "low" + direction_value = kUsbGpioDirectionLow; + } else { + USB_ERROR_LOG("unknown default value[%c]", kUsbGpioInfo[gpio_port].default_value); + return eFrameworkunifiedStatusFail; + } + } + + ret = write(direction_fd, direction_value, strlen(direction_value)); + write_error = errno; + close(direction_fd); + if (static_cast(strlen(direction_value)) != ret) { + USB_ERROR_LOG("write direction %s failed, ret=%zd.(%d, %s)", direction_value, ret, write_error, + strerror(write_error)); + return eFrameworkunifiedStatusFail; + } + + return eFrameworkunifiedStatusOK; +} + +/** + * Get gpio port value. + */ +static EFrameworkunifiedStatus GetGpioPortValue(UsbGpioPort port_name, bool* port_value) { + if ((USB_GPIO_PORT_MAX <= port_name) || !port_value) { + USB_ERROR_LOG("parameter is invalid."); + return eFrameworkunifiedStatusFail; + } + + // initialize gpio port + EFrameworkunifiedStatus result = InitializeGpioPort(port_name); + if (eFrameworkunifiedStatusOK != result) { + return result; + } + + // open port value file + int fd = OpenValueFile(kUsbGpioInfo[port_name].port_name, true); + if (-1 == fd) { + USB_ERROR_LOG("open value file failed.(%d, %s)", errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // read file content + char file_content = '\0'; + ssize_t ret = read(fd, &file_content, sizeof(file_content)); + int read_error = errno; + + // close file + close(fd); + + if (sizeof(file_content) != ret) { + USB_ERROR_LOG("read failed.(%d, %s)", read_error, strerror(read_error)); + return eFrameworkunifiedStatusFail; + } + + // compare file content to high/low value + if (kUsbGpioHighValue == file_content) { + *port_value = (kUsbGpioInfo[port_name].active_low ? false : true); + } else if (kUsbGpioLowValue == file_content) { + *port_value = (kUsbGpioInfo[port_name].active_low ? true : false); + } else { + USB_ERROR_LOG("content error.[%c]", file_content); + return eFrameworkunifiedStatusFail; + } + + return eFrameworkunifiedStatusOK; +} + +/** + * Set gpio port value. + */ +static EFrameworkunifiedStatus SetGpioPortValue(UsbGpioPort port_name, GpioPortValue port_value) { + if (USB_GPIO_PORT_MAX <= port_name) { + USB_ERROR_LOG("parameter is invalid."); + return eFrameworkunifiedStatusFail; + } + + // initialize gpio port + EFrameworkunifiedStatus result = InitializeGpioPort(port_name); + if (eFrameworkunifiedStatusOK != result) { + return result; + } + + // check direction is output + if (!kUsbGpioInfo[port_name].is_output) { + USB_ERROR_LOG("%d not an output port.", port_name); + return eFrameworkunifiedStatusFail; + } + + // open port value file + int fd = OpenValueFile(kUsbGpioInfo[port_name].port_name, false); + if (-1 == fd) { + USB_ERROR_LOG("open value file failed.(%d, %s)", errno, strerror(errno)); + return eFrameworkunifiedStatusFail; + } + + // write value + bool port_active = (GPIO_PORT_ON == port_value ? true : false); + bool write_low = (kUsbGpioInfo[port_name].active_low ? port_active : !port_active); + char write_value = (write_low ? kUsbGpioLowValue : kUsbGpioHighValue); + ssize_t ret = write(fd, &write_value, sizeof(write_value)); + int write_error = errno; + + // close file + close(fd); + + // check write result + if (sizeof(write_value) != ret) { + USB_ERROR_LOG("write [%c] failed, ret=%zd.(%d, %s)", write_value, ret, write_error, strerror(write_error)); + return eFrameworkunifiedStatusFail; + } else { + return eFrameworkunifiedStatusOK; + } +} + +/** + * Check overcurrent. + */ +static EFrameworkunifiedStatus CheckUsbOvercurrent(UsbPortNumber usb_port_no, bool* is_ovc) { + if ((USB_PORT_NUMBER_MAX <= usb_port_no) || !is_ovc) { + return eFrameworkunifiedStatusFail; + } + + return GetGpioPortValue(kUsbOvercurrentGpio[usb_port_no], is_ovc); +} + +EFrameworkunifiedStatus GetUsbRoleSwitch(UsbRoleType* usb_role) { + // check NULL pointer + if (!usb_role) { + USB_ERROR_LOG("parameter is NULL."); + return eFrameworkunifiedStatusNullPointer; + } + + return GetUsbRoleType(kUsbRoleSwitchTable.file_path, kUsbRoleSwitchTable.usb_host_value, + kUsbRoleSwitchTable.usb_function_value, usb_role); +} + +EFrameworkunifiedStatus SetUsbRoleSwitch(UsbRoleType usb_role) { + if ((USB_ROLE_HOST != usb_role) && (USB_ROLE_FUNCTION != usb_role)) { + USB_ERROR_LOG("parameter error.[%d]", usb_role); + return eFrameworkunifiedStatusInvldParam; + } + + // check current usb role: + // allow to switch only when usb_role is different from current usb role. + UsbRoleType current_role; + if (eFrameworkunifiedStatusOK != GetUsbRoleSwitch(¤t_role)) { + return eFrameworkunifiedStatusFail; + } + + if (current_role == usb_role) { + return eFrameworkunifiedStatusOK; + } + + // check usb role type + // - HOST: write HOST value to role file + // - FUNCTION: write FUNCTION value to role file + return SetUsbRoleValue(kUsbRoleSwitchTable.file_path, (USB_ROLE_HOST == usb_role) + ? kUsbRoleSwitchTable.usb_host_value + : kUsbRoleSwitchTable.usb_function_value); +} + +EFrameworkunifiedStatus CheckUsbAuthenticationError(UsbAuthenticationError* usb_auth_error) { + // check NULL pointer + if (!usb_auth_error) { + USB_ERROR_LOG("parameter is NULL."); + return eFrameworkunifiedStatusNullPointer; + } + + // Empty Stub implementations + *usb_auth_error = USB_AUTHENTICATION_ERROR_NONE; + return eFrameworkunifiedStatusOK; +} + +EFrameworkunifiedStatus ResetUsbVbus(UsbPortNumber usb_port_no) { + // check support power control + if (!CheckSupportPowerControl(usb_port_no)) { + return eFrameworkunifiedStatusInvldParam; + } + + // step 1: power off USB port + EFrameworkunifiedStatus result = SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_OFF); + if (eFrameworkunifiedStatusOK != result) { + USB_ERROR_LOG("power off USB%d failed.", usb_port_no); + return result; + } + + // step 2: sleep 1.1 sec + usleep(1100 * 1000); + + // step 3: power on USB port + result = SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_ON); + if (eFrameworkunifiedStatusOK != result) { + USB_ERROR_LOG("power on USB%d failed.", usb_port_no); + } + return result; +} + +EFrameworkunifiedStatus IsUsbPortPowered(UsbPortNumber usb_port_no, bool* is_powered) { + if (!is_powered) { + return eFrameworkunifiedStatusNullPointer; + } + + // check support power control + if (!CheckSupportPowerControl(usb_port_no)) { + return eFrameworkunifiedStatusInvldParam; + } + + return GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], is_powered); +} + +EFrameworkunifiedStatus PowerOnUsbPort(UsbPortNumber usb_port_no) { + // check support power control + if (!CheckSupportPowerControl(usb_port_no)) { + return eFrameworkunifiedStatusInvldParam; + } + bool current_power = false; + if (eFrameworkunifiedStatusOK != GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], ¤t_power)) { + return eFrameworkunifiedStatusFail; + } + + if (current_power) { + return eFrameworkunifiedStatusOK; + } + return SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_ON); +} + +EFrameworkunifiedStatus PowerOffUsbPort(UsbPortNumber usb_port_no) { + // check support power control + if (!CheckSupportPowerControl(usb_port_no)) { + return eFrameworkunifiedStatusInvldParam; + } + bool current_power = false; + if (eFrameworkunifiedStatusOK != GetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], ¤t_power)) { + return eFrameworkunifiedStatusFail; + } + + if (!current_power) { + return eFrameworkunifiedStatusOK; + } + + return SetGpioPortValue(kUsbPowerEnableGpio[usb_port_no], GPIO_PORT_OFF); +} + +EFrameworkunifiedStatus CheckUsbAbnormalStatus(UsbPortNumber usb_port_no, UsbAbnormalStatus* usb_abnormal_status) { + if (USB_PORT_NUMBER_MAX <= usb_port_no) { + return eFrameworkunifiedStatusInvldParam; + } + + // check NULL pointer + if (!usb_abnormal_status) { + return eFrameworkunifiedStatusNullPointer; + } + + // check overcurrent + bool is_ovc = false; + EFrameworkunifiedStatus result = CheckUsbOvercurrent(usb_port_no, &is_ovc); + if (eFrameworkunifiedStatusOK == result) { + if (is_ovc) { + *usb_abnormal_status = USB_ABNORMAL_STATUS_OVERCURRENT; + } else { + *usb_abnormal_status = USB_ABNORMAL_STATUS_NONE; + } + } + return result; +} -- cgit 1.2.3-korg