/****************************************************************************** * file lib/hardware/hwgpio.c * author YuLiang * version 1.0.0 * date 24-Nov-2021 * brief This file provides all the gpio operation functions. * ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2021 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of LandPower nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* 标准C库头文件. */ #include #include #include #include /* 用户代码头文件. */ #include "hwgpio.h" #include "cmd.h" /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static array_t *gpios = NULL; int32_t gpio_dau1_pow_idx; int32_t gpio_dau2_pow_idx; int32_t gpio_cau1_pow_idx; int32_t gpio_485_en1_idx; int32_t gpio_485_en2_idx; int32_t gpio_usb_4g_pwr_idx; int32_t gpio_usb_4g_rst_idx; int32_t gpio_usb_4g_wakeup_idx; int32_t gpio_wdt_idx; int32_t gpio_run_idx; int32_t gpio_sync_idx; int32_t gpio_err1_idx; /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ int32_t _gpio_name_get(uint8_t gpio, char *name) { if (!name) { return E_NULL; } switch (gpio) { case GPIO_RUN: snprintf(name, DEV_NAME_STR_LEN, "run"); break; default: snprintf(name, DEV_NAME_STR_LEN, "default"); break; } return E_NONE; } CMD(gpio_show, gpio_show_cmd, "show gpio", SHOW_STR "Gpios\n") { uint16_t i = 0; char gpio_name[DEV_NAME_STR_LEN] = {0}; gpio_node_t *gpio_node = NULL; vty_out(vty, "GPIO NAME DIR VALUE%s", VTY_NEWLINE); for(i = 0; i < array_active(gpios); i++) { gpio_node = array_lookup(gpios, i); if (!gpio_node) { continue; } if (gpio_node->curr_dir == GPIO_DIR_IN) { gpio_val_get(gpio_node->index, &gpio_node->curr_val); } _gpio_name_get(gpio_node->gpio, gpio_name); vty_out(vty, "%4d %-12s %-03s %d%s", gpio_node->gpio, gpio_name, gpio_node->curr_dir == GPIO_DIR_IN ? "in" : "out", gpio_node->curr_val, VTY_NEWLINE); } return CMD_SUCCESS; } /* Interface functions -------------------------------------------------------*/ /* 根据 gpio 找到对应的结构体, 如果不存在, 返回NULL. */ gpio_node_t *gpio_get_by_gpio(uint16_t gpio) { uint16_t i = 0; gpio_node_t *gpio_node = NULL; for(i = 0; i < array_active(gpios); i++) { gpio_node = array_lookup(gpios, i); if (!gpio_node) { continue; } if (gpio_node->gpio == gpio) { return gpio_node; } } return NULL; } /* 根据数组 index 找到对应的结构体, 如果不存在, 返回 NULL. */ gpio_node_t *gpio_get_by_index(uint16_t index) { return (gpio_node_t*)array_lookup(gpios, index); } /* 设置gpio输出值 */ int32_t gpio_val_set(uint16_t index, uint8_t value) { int32_t fd = 0; char buf[40] = {0}; gpio_node_t *gpio_node = gpio_get_by_index(index); /* 参数检查 */ if (!gpio_node) { DBG(DBG_M_GPIO, "gpio index %d is not found\r\n", index); return E_NOT_FOUND; } /* 只有out方向可以设置值 */ if (gpio_node->curr_dir != GPIO_DIR_OUT) { DBG(DBG_M_GPIO, "gpio %d direction is not out\r\n", gpio_node->gpio); return E_BAD_PARAM; } /* 如果值相等就不需要再操作了 */ if (gpio_node->curr_val == value) { return E_NONE; } /* 打开文件 */ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio_node->gpio); fd = open(buf, O_WRONLY); if (fd <= 0) { DBG(DBG_M_GPIO, "Open %s error", buf); return E_SYS_CALL; } /* 设置值 */ snprintf(buf, sizeof(buf), "%d", (value == 0) ? 0 : 1); if (write(fd, buf, 1) <= 0) { DBG(DBG_M_GPIO, "Write gpio %d value error", gpio_node->gpio); return E_SYS_CALL; } close(fd); gpio_node->curr_val = value; return E_NONE; } /* 设置gpio输出值 */ int32_t gpio_val_get(uint16_t index, uint8_t *value) { int32_t fd = 0; char buf[40] = {0}; gpio_node_t *gpio_node = gpio_get_by_index(index); /* 参数检查 */ if (!gpio_node) { DBG(DBG_M_GPIO, "gpio index %d is not found\r\n", index); return E_NOT_FOUND; } /* out方向直接读取 */ if (GPIO_DIR_OUT == gpio_node->curr_dir) { *value = gpio_node->curr_val; return E_NONE; } /* 打开文件 */ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio_node->gpio); fd = open(buf, O_RDONLY); if (fd <= 0) { DBG(DBG_M_GPIO, "Open %s error", buf); return E_SYS_CALL; } /* 读取值 */ memset(buf, 0, sizeof(buf)); if (read(fd, buf, sizeof(buf) - 1) <= 0) { DBG(DBG_M_GPIO, "Read gpio %d value error", gpio_node->gpio); return E_SYS_CALL; } close(fd); *value = strtol(buf, NULL, 10); return E_NONE; } /* 设置gpio方向 */ int32_t gpio_dir_set(uint16_t index, uint8_t dir) { int32_t fd = 0; char buf[40] = {0}; gpio_node_t *gpio_node = gpio_get_by_index(index); /* 参数检查 */ if (!gpio_node) { DBG(DBG_M_GPIO, "gpio index %d is not found\r\n", index); return E_NOT_FOUND; } /* 如果方向相等,不用继续操作 */ if (gpio_node->curr_dir == dir) { return E_NONE; } /* 打开文件 */ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio_node->gpio); fd = open(buf, O_WRONLY); if (fd <= 0) { DBG(DBG_M_GPIO, "Open %s error", buf); return E_SYS_CALL; } /* 设置方向 */ snprintf(buf, sizeof(buf), "%s", (dir == GPIO_DIR_IN) ? "in" : "out"); if (write(fd, buf, strlen(buf)) <= 0) { DBG(DBG_M_GPIO, "Write gpio %d direction error", gpio_node->gpio); return E_SYS_CALL; } close(fd); gpio_node->curr_dir = dir; return E_NONE; } /* 导出 GPIO, 返回值大于等于 0, 表示加入数组的 index; 小于 0 表示失败. */ int32_t gpio_export(uint16_t gpio) { int32_t fd = 0; char buf[40] = {0}; gpio_node_t *gpio_node = gpio_get_by_gpio(gpio); /* 如果找到表示已经 export. */ if (gpio_node) { return -1; } /* 文件不存在则导出, 存在不做操作. */ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d", gpio); if (access(buf, 0) < 0) { /* 打开文件描述符 */ fd = open("/sys/class/gpio/export", O_WRONLY); if (fd <= 0) { log_err(LOG_GPIO, "Open /sys/class/gpio/export error!"); return -2; } /* 导出gpio */ snprintf(buf, sizeof(buf), "%d", gpio); if (write(fd, buf, strlen(buf)) <= 0) { log_err(LOG_GPIO, "Write /sys/class/gpio/export(%d) error!", gpio); return -3; } close(fd); } /* 添加结构体 */ gpio_node = XMALLOC_Q(MTYPE_GPIO, sizeof(gpio_node_t)); gpio_node->gpio = gpio; /* 默认值是不确定的 */ gpio_node->curr_val = 0xff; gpio_node->is_export = TRUE; gpio_node->index = array_append(gpios, gpio_node, MTYPE_GPIO); return gpio_node->index; } /* 初始化函数 */ int32_t gpio_init(void) { gpios = array_init(ARRAY_MIN_SIZE, MTYPE_GPIO); cmd_install_element(COMMON_NODE, &gpio_show_cmd); gpio_run_idx = gpio_export(GPIO_RUN); if (gpio_run_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_run_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_run_idx, GPIO_DIR_OUT)); gpio_cau1_pow_idx = gpio_export(GPIO_CAU1_POW); if (gpio_cau1_pow_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_cau1_pow_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_cau1_pow_idx, GPIO_DIR_OUT)); gpio_485_en1_idx = gpio_export(GPIO_485_EN_1); if (gpio_485_en1_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_485_en1_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_485_en1_idx, GPIO_DIR_OUT)); gpio_485_en2_idx = gpio_export(GPIO_485_EN_2); if (gpio_485_en2_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_485_en2_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_485_en2_idx, GPIO_DIR_OUT)); gpio_usb_4g_pwr_idx = gpio_export(GPIO_4G_PWR); if (gpio_usb_4g_pwr_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_usb_4g_pwr_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_usb_4g_pwr_idx, GPIO_DIR_OUT)); gpio_usb_4g_rst_idx = gpio_export(GPIO_4G_RST); if (gpio_usb_4g_rst_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_usb_4g_rst_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_usb_4g_rst_idx, GPIO_DIR_OUT)); gpio_usb_4g_wakeup_idx = gpio_export(GPIO_4G_WAKUP); if (gpio_usb_4g_wakeup_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_usb_4g_wakeup_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_usb_4g_wakeup_idx, GPIO_DIR_OUT)); gpio_wdt_idx = gpio_export(GPIO_WDT); if (gpio_wdt_idx < 0) { DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_wdt_idx); return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_wdt_idx, GPIO_DIR_OUT)); return E_NONE; } /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/