📄 wmi.c
字号:
wmi_gpio_data_rx(wmip, datap, len);
break;
case (WMIX_GPIO_ACK_EVENTID):
wmi_gpio_ack_rx(wmip, datap, len);
break;
#endif /* CONFIG_HOST_GPIO_SUPPORT */
default:
WMI_DEBUG_PRINTF(ATH_LOG_ERR,
"Host received unknown extended reply/event with id 0x%x\n",
id);
wmip->wmi_stats.cmd_id_err++;
status = A_ERROR;
break;
}
return status;
}
/*
* Control Path
*/
A_STATUS
wmi_control_rx(struct wmi_t *wmip, void *osbuf)
{
WMI_CMD_HDR *cmd;
A_UINT16 id;
A_UINT8 *datap;
A_UINT32 len;
A_STATUS status = A_OK;
AR_DEBUG_ASSERT(osbuf != NULL);
if (a_netbuf_to_len(osbuf) < sizeof(WMI_CMD_HDR)) {
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi event rx: bad packet\n");
wmip->wmi_stats.cmd_len_err++;
return A_ERROR;
}
cmd = (WMI_CMD_HDR *)a_netbuf_to_data(osbuf);
id = cmd->commandId;
if (a_netbuf_pull(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi event rx: bad packet\n");
wmip->wmi_stats.cmd_len_err++;
return A_ERROR;
}
datap = a_netbuf_to_data(osbuf);
len = a_netbuf_to_len(osbuf);
switch (id) {
case (WMI_CREATE_PSTREAM_CMDID):
status = wmi_create_pstream_reply_rx(wmip, datap, len);
break;
case (WMI_DELETE_PSTREAM_CMDID):
status = wmi_delete_pstream_reply_rx(wmip, datap, len);
break;
case (WMI_GET_BITRATE_CMDID):
status = wmi_bitrate_reply_rx(wmip, datap, len);
break;
case (WMI_GET_CHANNEL_LIST_CMDID):
status = wmi_channelList_reply_rx(wmip, datap, len);
break;
case (WMI_GET_TX_PWR_CMDID):
status = wmi_txPwr_reply_rx(wmip, datap, len);
break;
case (WMI_READY_EVENTID):
status = wmi_ready_event_rx(wmip, datap, len);
break;
case (WMI_CONNECT_EVENTID):
status = wmi_connect_event_rx(wmip, datap, len);
break;
case (WMI_DISCONNECT_EVENTID):
status = wmi_disconnect_event_rx(wmip, datap, len);
break;
case (WMI_TKIP_MICERR_EVENTID):
status = wmi_tkip_micerr_event_rx(wmip, datap, len);
break;
case (WMI_BSSINFO_EVENTID):
status = wmi_bssInfo_event_rx(wmip, datap, len);
break;
case (WMI_REGDOMAIN_EVENTID):
status = wmi_regDomain_event_rx(wmip, datap, len);
break;
case (WMI_PSTREAM_TIMEOUT_EVENTID):
status = wmi_pstream_timeout_event_rx(wmip, datap, len);
break;
case (WMI_NEIGHBOR_REPORT_EVENTID):
status = wmi_neighborReport_event_rx(wmip, datap, len);
break;
case (WMI_SCAN_COMPLETE_EVENTID):
status = wmi_scanComplete_rx(wmip, datap, len);
break;
case (WMI_CMDERROR_EVENTID):
status = wmi_errorEvent_rx(wmip, datap, len);
break;
case (WMI_REPORT_STATISTICS_EVENTID):
status = wmi_statsEvent_rx(wmip, datap, len);
break;
case (WMI_RSSI_THRESHOLD_EVENTID):
status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
break;
case (WMI_ERROR_REPORT_EVENTID):
status = wmi_reportErrorEvent_rx(wmip, datap, len);
break;
case (WMI_OPT_RX_FRAME_EVENTID):
status = wmi_opt_frame_event_rx(wmip, datap, len);
break;
case (WMI_EXTENSION_EVENTID):
status = wmi_control_rx_xtnd(wmip, osbuf);
break;
#ifndef AR6K_FIRMWARE_1_0
case (WMI_REPORT_ROAM_TBL_EVENTID):
status = wmi_roam_tbl_event_rx(wmip, datap, len);
break;
case (WMI_CAC_EVENTID):
status = wmi_cac_event_rx(wmip, datap, len);
break;
case (WMI_REPORT_ROAM_DATA_EVENTID):
status = wmi_road_data_event_rx(wmip, datap, len);
break;
#endif
default:
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"Host received unknown reply/event with id 0x%x\n",
id);
wmip->wmi_stats.cmd_id_err++;
status = A_ERROR;
break;
}
return status;
}
static A_STATUS
wmi_create_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_CRE_PRIORITY_STREAM_REPLY *reply;
A_INT8 priNum = 0, i;
A_UINT8 dir;
if (len < sizeof(WMI_CRE_PRIORITY_STREAM_REPLY)) {
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi: create pstream reply too short (%d)!!\n", len);
return A_EINVAL;
}
reply = (WMI_CRE_PRIORITY_STREAM_REPLY *)datap;
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi: create pstream reply: status = %d, tx mbox = %d\n", reply->status, reply->txQueueNumber);
dir = reply->trafficDirection;
if (dir == BIDIR_TRAFFIC) {
wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][reply->trafficClass] = FALSE;
wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][reply->trafficClass] = FALSE;
} else {
wmip->wmi_pstreamCmdInProgress[dir][reply->trafficClass] = FALSE;
}
wmip->wmi_cpstreamCmdInProgress = FALSE;
if (reply->status == A_FAILED_CREATE_REMOVE_PSTREAM_FIRST) {
/* do nothing */
return A_OK;
}
if (reply->status == A_SUCCEEDED) {
if (reply->trafficDirection == DNLINK_TRAFFIC ||
reply->trafficDirection == BIDIR_TRAFFIC) {
wmip->wmi_olderPriRxMbox = wmip->wmi_newerPriRxMbox;
wmip->wmi_newerPriRxMbox = reply->rxQueueNumber;
wmip->wmi_mboxMap[DNLINK_TRAFFIC][reply->rxQueueNumber].trafficClass = reply->trafficClass;
wmip->wmi_mboxMap[DNLINK_TRAFFIC][reply->rxQueueNumber].priorityNum = 0;
wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][reply->trafficClass] = reply->rxQueueNumber;
}
if (reply->trafficDirection == UPLINK_TRAFFIC ||
reply->trafficDirection == BIDIR_TRAFFIC) {
wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][reply->trafficClass] = reply->txQueueNumber;
wmip->wmi_numQoSStream++;
for (i = 0; i < WMI_MAX_NUM_PRI_STREAMS; i++) {
if (!wmip->wmi_priority[i].inUse) {
priNum = i;
wmip->wmi_priority[i].inUse = 1;
wmip->wmi_priority[i].mbox = reply->txQueueNumber;
break;
}
}
wmip->wmi_mboxMap[UPLINK_TRAFFIC][reply->txQueueNumber].trafficClass = reply->trafficClass;
wmip->wmi_mboxMap[UPLINK_TRAFFIC][reply->txQueueNumber].priorityNum = priNum;
ar6000_set_numdataendpts(wmip->wmi_devt, wmip->wmi_numQoSStream+1);
}
}
return reply->status;
}
static A_STATUS
wmi_delete_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_DEL_PRIORITY_STREAM_REPLY *reply;
A_UINT8 dir;
if (len < sizeof(WMI_DEL_PRIORITY_STREAM_REPLY)) {
return A_EINVAL;
}
reply = (WMI_DEL_PRIORITY_STREAM_REPLY *)datap;
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: delete pstream reply: status = %d, rx mbox = %d\n", reply->status, reply->rxQueueNumber);
dir = reply->trafficDirection;
if (dir == BIDIR_TRAFFIC) {
wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][reply->trafficClass] = FALSE;
wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][reply->trafficClass] = FALSE;
} else {
wmip->wmi_pstreamCmdInProgress[dir][reply->trafficClass] = FALSE;
}
if (reply->status == A_OK) {
/* update internal states for Rx Path */
if (reply->trafficDirection == DNLINK_TRAFFIC || reply->trafficDirection == BIDIR_TRAFFIC) {
A_UINT8 qNum = reply->rxQueueNumber;
A_UINT8 class = wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].trafficClass;
wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][class] = WMI_NOT_MAPPED;
wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].priorityNum = WMI_NOT_MAPPED;
wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].trafficClass = WMM_AC_BE;
if (wmip->wmi_newerPriRxMbox == qNum) {
wmip->wmi_newerPriRxMbox = wmip->wmi_olderPriRxMbox;
wmip->wmi_olderPriRxMbox = qNum;
}
}
}
return reply->status;
}
static A_STATUS
wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
if (len < sizeof(WMI_READY_EVENT)) {
return A_EINVAL;
}
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: ready event\n");
wmip->wmi_ready = TRUE;
ar6000_ready_event(wmip->wmi_devt, ev->macaddr, ev->phyCapability);
return A_OK;
}
static A_STATUS
wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_CONNECT_EVENT *ev;
if (len < sizeof(WMI_CONNECT_EVENT)) {
return A_EINVAL;
}
ev = (WMI_CONNECT_EVENT *)datap;
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: connected event at freq %d ", ev->channel);
WMI_DEBUG_PRINTF(ATH_LOG_INF,"with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
ev->bssid[0], ev->bssid[1], ev->bssid[2],
ev->bssid[3], ev->bssid[4], ev->bssid[5]);
A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
#ifndef AR6K_FIRMWARE_1_0
ar6000_connect_event(wmip->wmi_devt, ev->channel, ev->bssid,
ev->listenInterval, ev->assocReqLen, ev->assocRespLen,
ev->assocInfo, ev->beaconIeLen);
#else
ar6000_connect_event(wmip->wmi_devt, ev->channel, ev->bssid,
ev->listenInterval, ev->assocReqLen, ev->assocRespLen,
ev->assocInfo, 0);
#endif
return A_OK;
}
static A_STATUS
wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_REG_DOMAIN_EVENT *ev;
if (len < sizeof(*ev)) {
return A_EINVAL;
}
ev = (WMI_REG_DOMAIN_EVENT *)datap;
ar6000_regDomain_event(wmip->wmi_devt, ev->regDomain);
return A_OK;
}
static A_STATUS
wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_NEIGHBOR_REPORT_EVENT *ev;
int numAps;
if (len < sizeof(*ev)) {
return A_EINVAL;
}
ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
numAps = ev->numberOfAps;
if (len < (A_INT32)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
return A_EINVAL;
}
ar6000_neighborReport_event(wmip->wmi_devt, numAps, ev->neighbor);
return A_OK;
}
static A_STATUS
wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_DISCONNECT_EVENT *ev;
if (len < sizeof(WMI_DISCONNECT_EVENT)) {
return A_EINVAL;
}
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: disconnected event\n");
ev = (WMI_DISCONNECT_EVENT *)datap;
A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
ar6000_disconnect_event(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
ev->assocRespLen, ev->assocInfo);
return A_OK;
}
static A_STATUS
wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
WMI_TKIP_MICERR_EVENT *ev;
if (len < sizeof(*ev)) {
return A_EINVAL;
}
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: tkip micerr event\n");
ev = (WMI_TKIP_MICERR_EVENT *)datap;
ar6000_tkip_micerr_event(wmip->wmi_devt, ev->keyid, ev->ismcast);
return A_OK;
}
static A_STATUS
wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
bss_t *bss;
WMI_BSS_INFO_HDR *bih;
A_UINT8 *buf;
if (len <= sizeof(WMI_BSS_INFO_HDR)) {
return A_EINVAL;
}
bih = (WMI_BSS_INFO_HDR *)datap;
buf = datap + sizeof(WMI_BSS_INFO_HDR);
len -= sizeof(WMI_BSS_INFO_HDR);
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: bssInfo event %2.2x:%2.2x\n",
bih->bssid[4], bih->bssid[5]);
bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
if (bss != NULL) {
/*
* Free up the node. Not the most efficient process given
* we are about to allocate a new node but it is simple and should be
* adequate.
*/
wlan_node_ret_n_remove(&wmip->wmi_scan_table, bss);
}
bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
if (bss == NULL) {
return A_NO_MEMORY;
}
bss->ni_rssi = bih->rssi;
AR_DEBUG_ASSERT(bss->ni_buf != NULL);
A_MEMCPY(bss->ni_buf, buf, len);
if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
wlan_node_free(bss);
return A_EINVAL;
}
/*
* Update the frequency in ie_chan, overwriting of channel number
* which is done in wlan_parse_beacon
*/
bss->ni_cie.ie_chan = bih->channel;
wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
return A_OK;
}
static A_STATUS
wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
bss_t *bss;
WMI_OPT_RX_INFO_HDR *bih;
A_UINT8 *buf;
if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
return A_EINVAL;
}
bih = (WMI_OPT_RX_INFO_HDR *)datap;
buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
len -= sizeof(WMI_OPT_RX_INFO_HDR);
WMI_DEBUG_PRINTF(ATH_LOG_INF,
"wmi: opt frame event %2.2x:%2.2x\n",
bih->bssid[4], bih->bssid[5]);
bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
if (bss != NULL) {
/*
* Free up the node. Not the most efficient process given
* we are about to allocate a new node but it is simple and should be
* adequate.
*/
wlan_node_ret_n_remove(&wmip->wmi_scan_table, bss);
}
bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
if (bss == NULL) {
return A_NO_MEMORY;
}
bss->ni_rssi = bih->rssi;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -