mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 01:21:26 +08:00
photon: add basic wlan scan function
This commit is contained in:
@@ -41,6 +41,7 @@ ifeq ($(CONFIG_DRIVERS_IEEE80211),y)
|
|||||||
# Include IEEE 802.11 drivers into the build
|
# Include IEEE 802.11 drivers into the build
|
||||||
|
|
||||||
ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO),y)
|
ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO),y)
|
||||||
|
CSRCS += bcmf_driver.c
|
||||||
CSRCS += bcmf_sdio.c
|
CSRCS += bcmf_sdio.c
|
||||||
CSRCS += bcmf_core.c
|
CSRCS += bcmf_core.c
|
||||||
CSRCS += bcmf_sdpcm.c
|
CSRCS += bcmf_sdpcm.c
|
||||||
|
|||||||
@@ -0,0 +1,346 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* drivers/wireless/ieee80211/bcmf_driver.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Simon Piriou <spiriou31@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 NuttX 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 OWNER 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/compiler.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
|
||||||
|
#include "bcmf_driver.h"
|
||||||
|
#include "bcmf_sdpcm.h"
|
||||||
|
#include "bcmf_sdio_core.h"
|
||||||
|
#include "bcmf_ioctl.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// TODO move elsewhere
|
||||||
|
#define DOT11_BSSTYPE_ANY 2
|
||||||
|
#define WL_SCAN_CHANNEL_TIME 40
|
||||||
|
#define WL_SCAN_UNASSOC_TIME 40
|
||||||
|
#define WL_SCAN_PASSIVE_TIME 120
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int bcmf_run_escan(FAR struct bcmf_dev_s *priv);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, uint8_t *addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len = 6;
|
||||||
|
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
IOVAR_STR_CUR_ETHERADDR, addr,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("MAC address updated %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
addr[0], addr[1], addr[2],
|
||||||
|
addr[3], addr[4], addr[5]);
|
||||||
|
memcpy(priv->mac_addr, addr, 6);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len;
|
||||||
|
|
||||||
|
/* TODO chek device state */
|
||||||
|
|
||||||
|
out_len = 0;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
enable ? WLC_UP : WLC_DOWN, NULL, &out_len);
|
||||||
|
|
||||||
|
if (ret == OK)
|
||||||
|
{
|
||||||
|
/* TODO update device state */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_dongle_scantime(FAR struct bcmf_dev_s *priv, int32_t scan_assoc_time,
|
||||||
|
int32_t scan_unassoc_time, int32_t scan_passive_time)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len, value;
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = scan_assoc_time;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_SCAN_CHANNEL_TIME, (uint8_t*)&value,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = scan_unassoc_time;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_SCAN_UNASSOC_TIME, (uint8_t*)&value,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = scan_passive_time;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_SCAN_PASSIVE_TIME, (uint8_t*)&value,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_dongle_initialize(FAR struct bcmf_dev_s *priv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
ret = bcmf_wl_enable(priv, true);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bcmf_dongle_scantime(priv, WL_SCAN_CHANNEL_TIME,
|
||||||
|
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME disable power save mode */
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = 0;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_PM, (uint8_t*)&value, &out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the GMode */
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = GMODE_AUTO;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_GMODE, (uint8_t*)&value, &out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO configure roaming if needed. Disable for now */
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
value = 1;
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
IOVAR_STR_ROAM_OFF, (uint8_t*)&value,
|
||||||
|
&out_len);
|
||||||
|
|
||||||
|
// FIXME remove
|
||||||
|
|
||||||
|
/* Try scan */
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
out_len = 4;
|
||||||
|
ret = bcmf_sdpcm_ioctl(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
WLC_SET_PASSIVE_SCAN, (uint8_t*)&value, &out_len);
|
||||||
|
bcmf_run_escan(priv);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_run_escan(FAR struct bcmf_dev_s *priv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len;
|
||||||
|
|
||||||
|
/* Default request structure */
|
||||||
|
|
||||||
|
struct wl_escan_params *params =
|
||||||
|
(struct wl_escan_params*)kmm_malloc(sizeof(*params));
|
||||||
|
if (!params)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(params, 0, sizeof(*params));
|
||||||
|
|
||||||
|
params->version = ESCAN_REQ_VERSION;
|
||||||
|
params->action = WL_SCAN_ACTION_START;
|
||||||
|
params->sync_id = 0x1234;
|
||||||
|
|
||||||
|
|
||||||
|
memset(¶ms->params.bssid, 0xFF, sizeof(params->params.bssid));
|
||||||
|
params->params.bss_type = DOT11_BSSTYPE_ANY;
|
||||||
|
params->params.scan_type = 0; /* Active scan */
|
||||||
|
params->params.nprobes = -1;
|
||||||
|
params->params.active_time = -1;
|
||||||
|
params->params.passive_time = -1;
|
||||||
|
params->params.home_time = -1;
|
||||||
|
|
||||||
|
params->params.channel_num = 0;
|
||||||
|
|
||||||
|
_info("start scan\n");
|
||||||
|
|
||||||
|
out_len = sizeof(*params);
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
IOVAR_STR_ESCAN, (uint8_t*)params,
|
||||||
|
&out_len);
|
||||||
|
|
||||||
|
free(params);
|
||||||
|
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int bcmf_wl_initialize(FAR struct bcmf_dev_s *priv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t out_len;
|
||||||
|
uint8_t tmp_buf[64];
|
||||||
|
|
||||||
|
/* Disable TX Gloming feature */
|
||||||
|
|
||||||
|
out_len = 4;
|
||||||
|
*(uint32_t*)tmp_buf = 0;
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
||||||
|
IOVAR_STR_TX_GLOM, tmp_buf,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query MAC address */
|
||||||
|
|
||||||
|
out_len = 6;
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
||||||
|
IOVAR_STR_CUR_ETHERADDR, tmp_buf,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(priv->mac_addr, tmp_buf, 6);
|
||||||
|
|
||||||
|
_info("MAC address is %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
tmp_buf[0], tmp_buf[1], tmp_buf[2],
|
||||||
|
tmp_buf[3], tmp_buf[4], tmp_buf[5]);
|
||||||
|
|
||||||
|
/* Query firmware version string */
|
||||||
|
|
||||||
|
out_len = sizeof(tmp_buf);
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
||||||
|
IOVAR_STR_VERSION, tmp_buf,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove line feed */
|
||||||
|
out_len = strlen((char*)tmp_buf);
|
||||||
|
if (out_len > 0 && tmp_buf[out_len-1] == '\n')
|
||||||
|
{
|
||||||
|
tmp_buf[out_len-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("fw version <%s>\n", tmp_buf);
|
||||||
|
|
||||||
|
/* FIXME Configure event mask to enable all asynchronous events */
|
||||||
|
|
||||||
|
uint8_t event_mask[16];
|
||||||
|
memset(event_mask, 0xff, sizeof(event_mask));
|
||||||
|
|
||||||
|
out_len = sizeof(event_mask);
|
||||||
|
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||||
|
IOVAR_STR_EVENT_MSGS, event_mask,
|
||||||
|
&out_len);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
// TODO Create a wlan device name and register network driver
|
||||||
|
|
||||||
|
return bcmf_dongle_initialize(priv);
|
||||||
|
}
|
||||||
@@ -73,10 +73,13 @@ struct bcmf_dev_s
|
|||||||
sem_t control_timeout; /* Semaphore to wait for control frame rsp */
|
sem_t control_timeout; /* Semaphore to wait for control frame rsp */
|
||||||
uint16_t control_reqid; /* Current control request id */
|
uint16_t control_reqid; /* Current control request id */
|
||||||
uint8_t *control_rxframe; /* Received control frame response */
|
uint8_t *control_rxframe; /* Received control frame response */
|
||||||
|
uint32_t control_status; /* Last received frame status */
|
||||||
|
|
||||||
// FIXME use mutex instead of semaphore
|
// FIXME use mutex instead of semaphore
|
||||||
sem_t tx_queue_mutex; /* Lock for transmit queue */
|
sem_t tx_queue_mutex; /* Lock for transmit queue */
|
||||||
dq_queue_t tx_queue; /* Queue of frames to tramsmit */
|
dq_queue_t tx_queue; /* Queue of frames to tramsmit */
|
||||||
|
|
||||||
|
uint8_t mac_addr[6]; /* Current mac address */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_DRIVER_H */
|
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_DRIVER_H */
|
||||||
|
|||||||
@@ -673,31 +673,14 @@ int bcmf_sdio_initialize(int minor, FAR struct sdio_dev_s *dev)
|
|||||||
goto exit_uninit_hw;
|
goto exit_uninit_hw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device is up and running
|
/* sdio bus is ready, init driver */
|
||||||
TODO Create a wlan device name and register network driver here */
|
|
||||||
|
|
||||||
// TODO remove: basic iovar test
|
ret = bcmf_wl_initialize(priv);
|
||||||
up_mdelay(1000);
|
if (ret != OK)
|
||||||
char fw_version[64];
|
|
||||||
uint32_t out_len = sizeof(fw_version);
|
|
||||||
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
|
||||||
IOVAR_STR_VERSION, fw_version,
|
|
||||||
&out_len);
|
|
||||||
if (ret == OK)
|
|
||||||
{
|
{
|
||||||
_info("fw version %d <%s>\n", out_len, fw_version);
|
_err("Cannot init wlan driver %d\n", ret);
|
||||||
}
|
ret = -EIO;
|
||||||
|
goto exit_uninit_hw;
|
||||||
up_mdelay(100);
|
|
||||||
out_len = 6;
|
|
||||||
ret = bcmf_sdpcm_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
|
||||||
IOVAR_STR_CUR_ETHERADDR, fw_version,
|
|
||||||
&out_len);
|
|
||||||
if (ret == OK)
|
|
||||||
{
|
|
||||||
_info("MAC address %d %02X:%02X:%02X:%02X:%02X:%02X\n", out_len,
|
|
||||||
fw_version[0], fw_version[1], fw_version[2],
|
|
||||||
fw_version[3], fw_version[4], fw_version[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -793,14 +776,14 @@ int bcmf_sdio_thread(int argc, char **argv)
|
|||||||
bcmf_write_sbregw(priv,
|
bcmf_write_sbregw(priv,
|
||||||
CORE_BUS_REG(priv->get_core_base_address(SDIOD_CORE_ID),
|
CORE_BUS_REG(priv->get_core_base_address(SDIOD_CORE_ID),
|
||||||
intstatus), priv->intstatus);
|
intstatus), priv->intstatus);
|
||||||
_info("intstatus %x\n", priv->intstatus);
|
// _info("intstatus %x\n", priv->intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On frame indication, read available frames */
|
/* On frame indication, read available frames */
|
||||||
|
|
||||||
if (priv->intstatus & I_HMB_FRAME_IND)
|
if (priv->intstatus & I_HMB_FRAME_IND)
|
||||||
{
|
{
|
||||||
_info("Frames available\n");
|
// _info("Frames available\n");
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -825,7 +808,7 @@ int bcmf_sdio_thread(int argc, char **argv)
|
|||||||
/* If we're done for now, turn off clock request. */
|
/* If we're done for now, turn off clock request. */
|
||||||
|
|
||||||
// TODO add wakelock
|
// TODO add wakelock
|
||||||
bcmf_sdio_bus_sleep(priv, true);
|
// bcmf_sdio_bus_sleep(priv, true);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,8 @@ int bcmf_sdpcm_process_header(FAR struct bcmf_dev_s *priv,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
// FIXME remove
|
// FIXME remove
|
||||||
uint8_t tmp_buffer[512];
|
uint8_t tmp_buffer[1024];
|
||||||
|
uint8_t tmp_buffer_ctl[1024];
|
||||||
int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -241,7 +242,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME define for size
|
// FIXME define for size
|
||||||
if (len > 512)
|
if (len > sizeof(tmp_buffer))
|
||||||
{
|
{
|
||||||
_err("Frame is too large, cancel %d\n", len);
|
_err("Frame is too large, cancel %d\n", len);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
@@ -258,8 +259,8 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
goto exit_free_abort;
|
goto exit_free_abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
_info("Receive frame\n");
|
// _info("Receive frame\n");
|
||||||
bcmf_hexdump((uint8_t*)header, len, (unsigned int)header);
|
// bcmf_hexdump((uint8_t*)header, len, (unsigned int)header);
|
||||||
|
|
||||||
/* Process and validate header */
|
/* Process and validate header */
|
||||||
|
|
||||||
@@ -276,7 +277,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
switch (header->channel & 0x0f)
|
switch (header->channel & 0x0f)
|
||||||
{
|
{
|
||||||
case SDPCM_CONTROL_CHANNEL:
|
case SDPCM_CONTROL_CHANNEL:
|
||||||
_info("Control message\n");
|
// _info("Control message\n");
|
||||||
|
|
||||||
/* Check frame */
|
/* Check frame */
|
||||||
|
|
||||||
@@ -295,7 +296,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
if (header->size < sizeof(struct bcmf_sdpcm_header) +
|
if (header->size < sizeof(struct bcmf_sdpcm_header) +
|
||||||
sizeof(struct bcmf_sdpcm_cdc_header) +
|
sizeof(struct bcmf_sdpcm_cdc_header) +
|
||||||
cdc_header->len ||
|
cdc_header->len ||
|
||||||
cdc_header->len > 512 -
|
cdc_header->len > sizeof(tmp_buffer) -
|
||||||
sizeof(struct bcmf_sdpcm_header) -
|
sizeof(struct bcmf_sdpcm_header) -
|
||||||
sizeof(struct bcmf_sdpcm_cdc_header))
|
sizeof(struct bcmf_sdpcm_cdc_header))
|
||||||
{
|
{
|
||||||
@@ -310,7 +311,10 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
{
|
{
|
||||||
/* Expected frame received, send it back to user */
|
/* Expected frame received, send it back to user */
|
||||||
|
|
||||||
priv->control_rxframe = (uint8_t*)header;
|
// TODO allocate real buffer
|
||||||
|
memcpy(tmp_buffer_ctl, tmp_buffer, header->size);
|
||||||
|
priv->control_rxframe = tmp_buffer_ctl;
|
||||||
|
// priv->control_rxframe = (uint8_t*)header;
|
||||||
|
|
||||||
sem_post(&priv->control_timeout);
|
sem_post(&priv->control_timeout);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -325,6 +329,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
|
|||||||
|
|
||||||
case SDPCM_EVENT_CHANNEL:
|
case SDPCM_EVENT_CHANNEL:
|
||||||
_info("Event message\n");
|
_info("Event message\n");
|
||||||
|
bcmf_hexdump((uint8_t*)header, header->size, (unsigned long)header);
|
||||||
ret = OK;
|
ret = OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -380,9 +385,9 @@ int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
|
|||||||
|
|
||||||
frame->header.sequence = priv->tx_seq++;
|
frame->header.sequence = priv->tx_seq++;
|
||||||
|
|
||||||
_info("Send frame\n");
|
// _info("Send frame\n");
|
||||||
bcmf_hexdump((uint8_t*)&frame->header, frame->header.size,
|
// bcmf_hexdump((uint8_t*)&frame->header, frame->header.size,
|
||||||
(unsigned int)&frame->header);
|
// (unsigned int)&frame->header);
|
||||||
|
|
||||||
ret = bcmf_transfer_bytes(priv, true, 2, 0, (uint8_t*)&frame->header,
|
ret = bcmf_transfer_bytes(priv, true, 2, 0, (uint8_t*)&frame->header,
|
||||||
frame->header.size);
|
frame->header.size);
|
||||||
@@ -423,29 +428,39 @@ exit_post_sem:
|
|||||||
// FIXME remove
|
// FIXME remove
|
||||||
uint8_t tmp_buffer2[512];
|
uint8_t tmp_buffer2[512];
|
||||||
uint8_t* bcmf_sdpcm_allocate_iovar(FAR struct bcmf_dev_s *priv, char *name,
|
uint8_t* bcmf_sdpcm_allocate_iovar(FAR struct bcmf_dev_s *priv, char *name,
|
||||||
char *data, uint32_t *len)
|
uint8_t *data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint32_t data_len;
|
uint32_t data_len;
|
||||||
uint16_t name_len = strlen(name) + 1;
|
uint16_t name_len;
|
||||||
|
|
||||||
if (!data)
|
if (name)
|
||||||
|
{
|
||||||
|
name_len = strlen(name) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
data_len = *len;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
data_len = 0;
|
data_len = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
*len = 0;
|
||||||
data_len = *len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME allocate buffer and use max_size instead of 512
|
// FIXME allocate buffer and use max_size instead of 512
|
||||||
if (data_len > 512-sizeof(struct bcmf_sdpcm_cdc_frame) ||
|
if (data_len > 512-sizeof(struct bcmf_sdpcm_cdc_frame) ||
|
||||||
(data_len + name_len) > 512-sizeof(struct bcmf_sdpcm_cdc_frame))
|
(data_len + name_len) > 512-sizeof(struct bcmf_sdpcm_cdc_frame))
|
||||||
{
|
{
|
||||||
*len = 0;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO allocate buffer
|
// TODO allocate buffer len + sizeof(struct bcmf_sdpcm_cdc_frame)
|
||||||
|
|
||||||
/* Copy name string and data */
|
/* Copy name string and data */
|
||||||
|
|
||||||
@@ -532,12 +547,13 @@ int bcmf_sdpcm_send_cdc_frame(FAR struct bcmf_dev_s *priv, uint32_t cmd,
|
|||||||
return bcmf_sdpcm_queue_frame(priv, SDPCM_CONTROL_CHANNEL, data, len);
|
return bcmf_sdpcm_queue_frame(priv, SDPCM_CONTROL_CHANNEL, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
int bcmf_sdpcm_control_request(FAR struct bcmf_dev_s *priv,
|
||||||
uint32_t ifidx, bool set, char *name,
|
uint32_t ifidx, bool set, uint32_t cmd,
|
||||||
char *data, uint32_t *len)
|
char *name, uint8_t *data, uint32_t *len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t *iovar_buf;
|
uint8_t *iovar_buf;
|
||||||
|
uint32_t out_len = *len;
|
||||||
uint32_t iovar_buf_len = *len;
|
uint32_t iovar_buf_len = *len;
|
||||||
|
|
||||||
*len = 0;
|
*len = 0;
|
||||||
@@ -559,13 +575,14 @@ int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
|||||||
goto exit_sem_post;
|
goto exit_sem_post;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send control frame. Frame buffer is freed when sent */
|
/* Send control frame. iovar buffer is freed when sent */
|
||||||
|
|
||||||
ret = bcmf_sdpcm_send_cdc_frame(priv, set ? WLC_SET_VAR : WLC_GET_VAR,
|
ret = bcmf_sdpcm_send_cdc_frame(priv, cmd,
|
||||||
ifidx, set, iovar_buf, iovar_buf_len);
|
ifidx, set, iovar_buf, iovar_buf_len);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
goto exit_free_iovar;
|
// TODO free allocated iovar buffer here
|
||||||
|
goto exit_sem_post;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for response */
|
/* Wait for response */
|
||||||
@@ -579,25 +596,58 @@ int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
|||||||
goto exit_sem_post;
|
goto exit_sem_post;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check frame status */
|
||||||
|
|
||||||
|
struct bcmf_sdpcm_cdc_dcmd *rxframe =
|
||||||
|
(struct bcmf_sdpcm_cdc_dcmd*)priv->control_rxframe;
|
||||||
|
|
||||||
|
priv->control_status = rxframe->cdc_header.status;
|
||||||
|
|
||||||
|
if (priv->control_status != 0)
|
||||||
|
{
|
||||||
|
_err("Invalid cdc status 0x%x\n", priv->control_status);
|
||||||
|
ret = -EIO;
|
||||||
|
goto exit_free_rx_frame;
|
||||||
|
}
|
||||||
|
|
||||||
if (!set)
|
if (!set)
|
||||||
{
|
{
|
||||||
/* Request sent, copy received data back */
|
/* Request sent, copy received data back */
|
||||||
|
|
||||||
struct bcmf_sdpcm_cdc_dcmd *rxframe =
|
if (rxframe->cdc_header.len > out_len)
|
||||||
(struct bcmf_sdpcm_cdc_dcmd*)priv->control_rxframe;
|
{
|
||||||
|
_err("RX frame too big %d %d\n", rxframe->cdc_header.len, out_len);
|
||||||
memcpy(data, rxframe->data, rxframe->cdc_header.len);
|
memcpy(data, rxframe->data, out_len);
|
||||||
|
*len = out_len;
|
||||||
*len = rxframe->cdc_header.len;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(data, rxframe->data, rxframe->cdc_header.len);
|
||||||
|
*len = rxframe->cdc_header.len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit_free_rx_frame:
|
||||||
// TODO free rxframe buffer */
|
// TODO free rxframe buffer */
|
||||||
|
priv->control_rxframe = NULL;
|
||||||
|
|
||||||
goto exit_sem_post;
|
|
||||||
|
|
||||||
exit_free_iovar:
|
|
||||||
// TODO free allocated buffer here
|
|
||||||
exit_sem_post:
|
exit_sem_post:
|
||||||
sem_post(&priv->control_mutex);
|
sem_post(&priv->control_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
||||||
|
uint32_t ifidx, bool set, char *name,
|
||||||
|
uint8_t *data, uint32_t *len)
|
||||||
|
{
|
||||||
|
return bcmf_sdpcm_control_request(priv, ifidx, set,
|
||||||
|
set ? WLC_SET_VAR : WLC_GET_VAR, name,
|
||||||
|
data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmf_sdpcm_ioctl(FAR struct bcmf_dev_s *priv,
|
||||||
|
uint32_t ifidx, bool set, uint32_t cmd,
|
||||||
|
uint8_t *data, uint32_t *len)
|
||||||
|
{
|
||||||
|
return bcmf_sdpcm_control_request(priv, ifidx, set, cmd, NULL, data, len);
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,10 @@ int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv);
|
|||||||
|
|
||||||
int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
int bcmf_sdpcm_iovar_request(FAR struct bcmf_dev_s *priv,
|
||||||
uint32_t ifidx, bool set, char *name,
|
uint32_t ifidx, bool set, char *name,
|
||||||
char *data, uint32_t *len);
|
uint8_t *data, uint32_t *len);
|
||||||
|
|
||||||
|
int bcmf_sdpcm_ioctl(FAR struct bcmf_dev_s *priv,
|
||||||
|
uint32_t ifidx, bool set, uint32_t cmd,
|
||||||
|
uint8_t *data, uint32_t *len);
|
||||||
|
|
||||||
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDPCM_H */
|
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDPCM_H */
|
||||||
Reference in New Issue
Block a user