📄 wmi.c
字号:
break; case (WMIX_GPIO_ACK_EVENTID): wmi_gpio_ack_rx(wmip, datap, len); break;#endif /* CONFIG_HOST_GPIO_SUPPORT */ default: WMI_DEBUG_PRINTF("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_STATUSwmi_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; A_ASSERT(osbuf != NULL); if (a_netbuf_to_len(osbuf) < sizeof(WMI_CMD_HDR)) { WMI_DEBUG_PRINTF("wmi event rx: bad packet\n"); wmip->wmi_stats.cmd_len_err++; a_netbuf_free(osbuf); 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("wmi event rx: bad packet\n"); wmip->wmi_stats.cmd_len_err++; a_netbuf_free(osbuf); 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_REPORT_ROAM_TBL_EVENTID): status = wmi_roam_tbl_event_rx(wmip, datap, len); break; case (WMI_EXTENSION_EVENTID): status = wmi_control_rx_xtnd(wmip, osbuf); break; case (WMI_CAC_EVENTID): status = wmi_cac_event_rx(wmip, datap, len); break; case (WMI_REPORT_ROAM_DATA_EVENTID): status = wmi_roam_data_event_rx(wmip, datap, len); break; default: WMI_DEBUG_PRINTF("Host received unknown reply/event with id 0x%x\n", id); wmip->wmi_stats.cmd_id_err++; status = A_ERROR; break; } a_netbuf_free(osbuf); return status;}static A_STATUSwmi_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 ("wmi: create pstream reply too short (%d)!!\n", len); return A_EINVAL; } reply = (WMI_CRE_PRIORITY_STREAM_REPLY *)datap; WMI_DEBUG_PRINTF("wmi: create pstream reply: status = %d, tx mbox = %d rx mbox %d\n", reply->status, reply->txQueueNumber, 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; } 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; /* In case of 3rd pstreams being created, target automatically deletes the old pstream * and accomodates the this one. Though, the host does not know of this implicit * deletion, */ if (wmip->wmi_numQoSStream < WMI_MAX_NUM_PRI_STREAMS) 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_STATUSwmi_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("wmi: delete pstream reply: status = %d, rx mbox = %d tx mbox = %d\n", reply->status, reply->rxQueueNumber, 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; } 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_STATUSwmi_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("wmi: ready event\n"); wmip->wmi_ready = TRUE; ar6000_ready_event(wmip->wmi_devt, ev->macaddr, ev->phyCapability); return A_OK;}static A_STATUSwmi_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;#ifdef DEBUG WMI_DEBUG_PRINTF("wmi: connected event at freq %d ", ev->channel); WMI_DEBUG_PRINTF("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]);#endif /* DEBUG */ A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); ar6000_connect_event(wmip->wmi_devt, ev->channel, ev->bssid, ev->listenInterval, ev->beaconIeLen, ev->assocReqLen, ev->assocRespLen, ev->assocInfo); return A_OK;}static A_STATUSwmi_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_STATUSwmi_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 < (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_STATUSwmi_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("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_STATUSwmi_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("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_STATUSwmi_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_PRINTF2("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_reclaim(&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; A_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_STATUSwmi_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_PRINTF2("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_reclaim(&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; bss->ni_cie.ie_chan = bih->channel; A_ASSERT(bss->ni_buf != NULL); A_MEMCPY(bss->ni_buf, buf, len); wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); return A_OK;}static A_STATUSwmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len){ WMI_PSTREAM_TIMEOUT_EVENT *ev; if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { return A_EINVAL; } WMI_DEBUG_PRINTF("wmi: pstream timeout event\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -