Loading os_if/linux/gpio/inc/wlan_cfg80211_gpio.h 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: wlan_cfg80211_gpio.h * * This Header file provide declaration for cfg80211 command handler API */ #ifndef __WLAN_CFG80211_GPIO_CFG_H__ #define __WLAN_CFG80211_GPIO_CFG_H__ #include <wlan_objmgr_cmn.h> #include <qdf_types.h> #include <net/cfg80211.h> #include <qca_vendor.h> #ifdef WLAN_FEATURE_GPIO_CFG extern const struct nla_policy wlan_cfg80211_gpio_config_policy [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; /** * wlan_cfg80211_start_gpio_config() - set GPIO config * @psoc: pointer to psoc common object * @data: Pointer to the data to be passed via vendor interface * @data_len: Length of the data to be passed * * Return: Return the Success or Failure code */ int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len); #else static inline int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len) { return 0; } #endif /* WLAN_FEATURE_GPIO_CFG */ #endif /* __WLAN_CFG80211_GPIO_CFG_H__ */ os_if/linux/gpio/src/wlan_cfg80211_gpio.c 0 → 100644 +301 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: defines driver functions interfacing with linux kernel */ #include <qdf_list.h> #include <qdf_status.h> #include <linux/wireless.h> #include <linux/netdevice.h> #include <wlan_cfg80211.h> #include <wlan_osif_priv.h> #include <wlan_gpio_ucfg_api.h> #include <wlan_cfg80211_gpio.h> #include "qdf_module.h" const struct nla_policy wlan_cfg80211_gpio_config_policy[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR] = { .type = NLA_U32, .len = sizeof(uint32_t) }, }; /** * convert_vendor_gpio_direction() - Function to convert vendor gpio direction * @dir: pointer to enum qca_gpio_direction * * Convert the vendor gpio direction to wmi unified gpio direction * * Return: wmi unified gpio direction */ static enum gpio_direction convert_vendor_gpio_direction(enum qca_gpio_direction dir) { switch (dir) { case QCA_WLAN_GPIO_INPUT: return WMI_HOST_GPIO_INPUT; case QCA_WLAN_GPIO_OUTPUT: return WMI_HOST_GPIO_OUTPUT; default: return WMI_HOST_GPIO_INPUT; } } /** * convert_vendor_gpio_pull_type() - Function to convert vendor pull type * @pull_type: pointer to enum qca_gpio_pull_type * * Convert the vendor pull type to wmi unified pull type * * Return: wmi unified gpio pull type */ static enum gpio_pull_type convert_vendor_gpio_pull_type(enum qca_gpio_pull_type pull_type) { switch (pull_type) { case QCA_WLAN_GPIO_PULL_NONE: return WMI_HOST_GPIO_PULL_NONE; case QCA_WLAN_GPIO_PULL_UP: return WMI_HOST_GPIO_PULL_UP; case QCA_WLAN_GPIO_PULL_DOWN: return WMI_HOST_GPIO_PULL_DOWN; default: return WMI_HOST_GPIO_PULL_NONE; } } /** * convert_vendor_gpio_interrupt_mode() - Function to convert * vendor interrupt mode * @intr_mode: pointer to enum qca_gpio_interrupt_mode * * Convert the vendor interrupt mode to wmi unified interrupt mode * * Return: wmi unified gpio interrupt mode */ static enum gpio_interrupt_mode convert_vendor_gpio_interrupt_mode(enum qca_gpio_interrupt_mode intr_mode) { switch (intr_mode) { case QCA_WLAN_GPIO_INTMODE_DISABLE: return WMI_HOST_GPIO_INTMODE_DISABLE; case QCA_WLAN_GPIO_INTMODE_RISING_EDGE: return WMI_HOST_GPIO_INTMODE_RISING_EDGE; case QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: return WMI_HOST_GPIO_INTMODE_FALLING_EDGE; case QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: return WMI_HOST_GPIO_INTMODE_BOTH_EDGE; case QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: return WMI_HOST_GPIO_INTMODE_LEVEL_LOW; case QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: return WMI_HOST_GPIO_INTMODE_LEVEL_HIGH; default: return WMI_HOST_GPIO_INTMODE_DISABLE; } } /** * convert_vendor_gpio_output_value() - Function to convert vendor * gpio output value * @value: pointer to enum qca_gpio_value * * Convert the vendor gpio value to wmi unified gpio output value * * Return: wmi unified gpio output value */ static enum gpio_value convert_vendor_gpio_output_value(enum qca_gpio_value value) { switch (value) { case QCA_WLAN_GPIO_LEVEL_LOW: return WMI_HOST_GPIO_LEVEL_LOW; case QCA_WLAN_GPIO_LEVEL_HIGH: return WMI_HOST_GPIO_LEVEL_HIGH; default: return WMI_HOST_GPIO_LEVEL_LOW; } } /** * wlan_set_gpio_config() - set the gpio configuration info * @psoc: the pointer of wlan_objmgr_psoc * @attr: list of attributes * * Return: 0 on success; errno on failure */ static int wlan_set_gpio_config(struct wlan_objmgr_psoc *psoc, struct nlattr **attr) { struct gpio_config_params cfg_param; struct nlattr *gpio_attr; enum qca_gpio_direction pin_dir; enum qca_gpio_pull_type pull_type; enum qca_gpio_interrupt_mode intr_mode; QDF_STATUS status; gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; if (!gpio_attr) { osif_err("attr gpio number failed"); return -EINVAL; } cfg_param.pin_num = nla_get_u32(gpio_attr); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR]; if (!gpio_attr) { osif_err("attr gpio dir failed"); return -EINVAL; } pin_dir = nla_get_u32(gpio_attr); if (pin_dir >= QCA_WLAN_GPIO_DIR_MAX) { osif_err("attr gpio direction invalid"); return -EINVAL; } cfg_param.pin_dir = convert_vendor_gpio_direction(pin_dir); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE]; if (!gpio_attr) { osif_err("attr gpio pull failed"); return -EINVAL; } pull_type = nla_get_u32(gpio_attr); if (pull_type >= QCA_WLAN_GPIO_PULL_MAX) { osif_err("attr gpio pull type invalid"); return -EINVAL; } cfg_param.pin_pull_type = convert_vendor_gpio_pull_type(pull_type); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE]; if (!gpio_attr) { osif_err("attr gpio interrupt mode failed"); return -EINVAL; } intr_mode = nla_get_u32(gpio_attr); if (intr_mode >= QCA_WLAN_GPIO_INTMODE_MAX) { osif_err("attr gpio interrupt mode invalid"); return -EINVAL; } cfg_param.pin_intr_mode = convert_vendor_gpio_interrupt_mode(intr_mode); status = ucfg_set_gpio_config(psoc, &cfg_param); return status; } /** * wlan_set_gpio_output() - set the gpio output info * @psoc: the pointer of wlan_objmgr_psoc * @attr: list of attributes * * Return: 0 on success; errno on failure */ static int wlan_set_gpio_output(struct wlan_objmgr_psoc *psoc, struct nlattr **attr) { struct gpio_output_params out_param; struct nlattr *gpio_attr; enum qca_gpio_value pin_set; QDF_STATUS status; gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; if (!gpio_attr) { osif_err("attr gpio number failed"); return -EINVAL; } out_param.pin_num = nla_get_u32(gpio_attr); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE]; if (!gpio_attr) { osif_err("attr gpio value failed"); return -EINVAL; } pin_set = nla_get_u32(gpio_attr); if (pin_set >= QCA_WLAN_GPIO_LEVEL_MAX) { osif_err("attr gpio level invalid"); return -EINVAL; } out_param.pin_set = convert_vendor_gpio_output_value(pin_set); status = ucfg_set_gpio_output(psoc, &out_param); return status; } /** * wlan_cfg80211_start_gpio_config - Set the gpio configuration * @wiphy: pointer to wiphy * @psoc: the pointer of wlan_objmgr_psoc * @data: pointer to data * @data_len: data length * * __wlan_cfg80211_set_gpio_config will forward the GPIO setting to FW by * WMI_GPIO_CONFIG/OUTPUT_CMDID * * Return: 0 on success; errno on failure */ int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len) { uint32_t command; struct nlattr *attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; int ret; if (wlan_cfg80211_nla_parse(attr, QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX, data, data_len, wlan_cfg80211_gpio_config_policy)) { return -EINVAL; } if (attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]) { command = nla_get_u32( attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]); if (command == QCA_WLAN_VENDOR_GPIO_CONFIG) { ret = wlan_set_gpio_config(psoc, attr); } else if (command == QCA_WLAN_VENDOR_GPIO_OUTPUT) { ret = wlan_set_gpio_output(psoc, attr); } else { osif_err("Invalid command"); return -EINVAL; } } else { osif_err("Invalid command"); return -EINVAL; } return ret; } qdf_export_symbol(wlan_cfg80211_start_gpio_config); Loading
os_if/linux/gpio/inc/wlan_cfg80211_gpio.h 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: wlan_cfg80211_gpio.h * * This Header file provide declaration for cfg80211 command handler API */ #ifndef __WLAN_CFG80211_GPIO_CFG_H__ #define __WLAN_CFG80211_GPIO_CFG_H__ #include <wlan_objmgr_cmn.h> #include <qdf_types.h> #include <net/cfg80211.h> #include <qca_vendor.h> #ifdef WLAN_FEATURE_GPIO_CFG extern const struct nla_policy wlan_cfg80211_gpio_config_policy [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; /** * wlan_cfg80211_start_gpio_config() - set GPIO config * @psoc: pointer to psoc common object * @data: Pointer to the data to be passed via vendor interface * @data_len: Length of the data to be passed * * Return: Return the Success or Failure code */ int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len); #else static inline int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len) { return 0; } #endif /* WLAN_FEATURE_GPIO_CFG */ #endif /* __WLAN_CFG80211_GPIO_CFG_H__ */
os_if/linux/gpio/src/wlan_cfg80211_gpio.c 0 → 100644 +301 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: defines driver functions interfacing with linux kernel */ #include <qdf_list.h> #include <qdf_status.h> #include <linux/wireless.h> #include <linux/netdevice.h> #include <wlan_cfg80211.h> #include <wlan_osif_priv.h> #include <wlan_gpio_ucfg_api.h> #include <wlan_cfg80211_gpio.h> #include "qdf_module.h" const struct nla_policy wlan_cfg80211_gpio_config_policy[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE] = { .type = NLA_U32, .len = sizeof(uint32_t) }, [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR] = { .type = NLA_U32, .len = sizeof(uint32_t) }, }; /** * convert_vendor_gpio_direction() - Function to convert vendor gpio direction * @dir: pointer to enum qca_gpio_direction * * Convert the vendor gpio direction to wmi unified gpio direction * * Return: wmi unified gpio direction */ static enum gpio_direction convert_vendor_gpio_direction(enum qca_gpio_direction dir) { switch (dir) { case QCA_WLAN_GPIO_INPUT: return WMI_HOST_GPIO_INPUT; case QCA_WLAN_GPIO_OUTPUT: return WMI_HOST_GPIO_OUTPUT; default: return WMI_HOST_GPIO_INPUT; } } /** * convert_vendor_gpio_pull_type() - Function to convert vendor pull type * @pull_type: pointer to enum qca_gpio_pull_type * * Convert the vendor pull type to wmi unified pull type * * Return: wmi unified gpio pull type */ static enum gpio_pull_type convert_vendor_gpio_pull_type(enum qca_gpio_pull_type pull_type) { switch (pull_type) { case QCA_WLAN_GPIO_PULL_NONE: return WMI_HOST_GPIO_PULL_NONE; case QCA_WLAN_GPIO_PULL_UP: return WMI_HOST_GPIO_PULL_UP; case QCA_WLAN_GPIO_PULL_DOWN: return WMI_HOST_GPIO_PULL_DOWN; default: return WMI_HOST_GPIO_PULL_NONE; } } /** * convert_vendor_gpio_interrupt_mode() - Function to convert * vendor interrupt mode * @intr_mode: pointer to enum qca_gpio_interrupt_mode * * Convert the vendor interrupt mode to wmi unified interrupt mode * * Return: wmi unified gpio interrupt mode */ static enum gpio_interrupt_mode convert_vendor_gpio_interrupt_mode(enum qca_gpio_interrupt_mode intr_mode) { switch (intr_mode) { case QCA_WLAN_GPIO_INTMODE_DISABLE: return WMI_HOST_GPIO_INTMODE_DISABLE; case QCA_WLAN_GPIO_INTMODE_RISING_EDGE: return WMI_HOST_GPIO_INTMODE_RISING_EDGE; case QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: return WMI_HOST_GPIO_INTMODE_FALLING_EDGE; case QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: return WMI_HOST_GPIO_INTMODE_BOTH_EDGE; case QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: return WMI_HOST_GPIO_INTMODE_LEVEL_LOW; case QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: return WMI_HOST_GPIO_INTMODE_LEVEL_HIGH; default: return WMI_HOST_GPIO_INTMODE_DISABLE; } } /** * convert_vendor_gpio_output_value() - Function to convert vendor * gpio output value * @value: pointer to enum qca_gpio_value * * Convert the vendor gpio value to wmi unified gpio output value * * Return: wmi unified gpio output value */ static enum gpio_value convert_vendor_gpio_output_value(enum qca_gpio_value value) { switch (value) { case QCA_WLAN_GPIO_LEVEL_LOW: return WMI_HOST_GPIO_LEVEL_LOW; case QCA_WLAN_GPIO_LEVEL_HIGH: return WMI_HOST_GPIO_LEVEL_HIGH; default: return WMI_HOST_GPIO_LEVEL_LOW; } } /** * wlan_set_gpio_config() - set the gpio configuration info * @psoc: the pointer of wlan_objmgr_psoc * @attr: list of attributes * * Return: 0 on success; errno on failure */ static int wlan_set_gpio_config(struct wlan_objmgr_psoc *psoc, struct nlattr **attr) { struct gpio_config_params cfg_param; struct nlattr *gpio_attr; enum qca_gpio_direction pin_dir; enum qca_gpio_pull_type pull_type; enum qca_gpio_interrupt_mode intr_mode; QDF_STATUS status; gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; if (!gpio_attr) { osif_err("attr gpio number failed"); return -EINVAL; } cfg_param.pin_num = nla_get_u32(gpio_attr); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR]; if (!gpio_attr) { osif_err("attr gpio dir failed"); return -EINVAL; } pin_dir = nla_get_u32(gpio_attr); if (pin_dir >= QCA_WLAN_GPIO_DIR_MAX) { osif_err("attr gpio direction invalid"); return -EINVAL; } cfg_param.pin_dir = convert_vendor_gpio_direction(pin_dir); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE]; if (!gpio_attr) { osif_err("attr gpio pull failed"); return -EINVAL; } pull_type = nla_get_u32(gpio_attr); if (pull_type >= QCA_WLAN_GPIO_PULL_MAX) { osif_err("attr gpio pull type invalid"); return -EINVAL; } cfg_param.pin_pull_type = convert_vendor_gpio_pull_type(pull_type); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE]; if (!gpio_attr) { osif_err("attr gpio interrupt mode failed"); return -EINVAL; } intr_mode = nla_get_u32(gpio_attr); if (intr_mode >= QCA_WLAN_GPIO_INTMODE_MAX) { osif_err("attr gpio interrupt mode invalid"); return -EINVAL; } cfg_param.pin_intr_mode = convert_vendor_gpio_interrupt_mode(intr_mode); status = ucfg_set_gpio_config(psoc, &cfg_param); return status; } /** * wlan_set_gpio_output() - set the gpio output info * @psoc: the pointer of wlan_objmgr_psoc * @attr: list of attributes * * Return: 0 on success; errno on failure */ static int wlan_set_gpio_output(struct wlan_objmgr_psoc *psoc, struct nlattr **attr) { struct gpio_output_params out_param; struct nlattr *gpio_attr; enum qca_gpio_value pin_set; QDF_STATUS status; gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; if (!gpio_attr) { osif_err("attr gpio number failed"); return -EINVAL; } out_param.pin_num = nla_get_u32(gpio_attr); gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE]; if (!gpio_attr) { osif_err("attr gpio value failed"); return -EINVAL; } pin_set = nla_get_u32(gpio_attr); if (pin_set >= QCA_WLAN_GPIO_LEVEL_MAX) { osif_err("attr gpio level invalid"); return -EINVAL; } out_param.pin_set = convert_vendor_gpio_output_value(pin_set); status = ucfg_set_gpio_output(psoc, &out_param); return status; } /** * wlan_cfg80211_start_gpio_config - Set the gpio configuration * @wiphy: pointer to wiphy * @psoc: the pointer of wlan_objmgr_psoc * @data: pointer to data * @data_len: data length * * __wlan_cfg80211_set_gpio_config will forward the GPIO setting to FW by * WMI_GPIO_CONFIG/OUTPUT_CMDID * * Return: 0 on success; errno on failure */ int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, struct wlan_objmgr_psoc *psoc, const void *data, int data_len) { uint32_t command; struct nlattr *attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; int ret; if (wlan_cfg80211_nla_parse(attr, QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX, data, data_len, wlan_cfg80211_gpio_config_policy)) { return -EINVAL; } if (attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]) { command = nla_get_u32( attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]); if (command == QCA_WLAN_VENDOR_GPIO_CONFIG) { ret = wlan_set_gpio_config(psoc, attr); } else if (command == QCA_WLAN_VENDOR_GPIO_OUTPUT) { ret = wlan_set_gpio_output(psoc, attr); } else { osif_err("Invalid command"); return -EINVAL; } } else { osif_err("Invalid command"); return -EINVAL; } return ret; } qdf_export_symbol(wlan_cfg80211_start_gpio_config);