status=0xC023002C, STATUS_NDIS_UNSUPPORTED_REVISION

 MSDN描述:The revision number specified in the structure is not supported.

触发错误的代码:

NDIS_STATUS
OidHandle_GetAdapterCapabilities(
	_In_ TLV_CONTEXT* pTlvContext,
	_In_ PNDIS_OID_REQUEST OidRequest
) {
    WDI_GET_ADAPTER_CAPABILITIES_PARAMETERS	adapterCap;
    
    status = Generate(&adapterCap, sizeof(WDI_MESSAGE_HEADER), pTlvContext, &length, &pOutput);

    return status;
}

Generate这里返回这个status,是因为pTlvContext里的成员设置不对。

参考MSDN: WDI TLV 版本控制 - Windows drivers | Microsoft Learn

这是注册WDI驱动时代码:

wdiChar.WdiVersion = WDI_VERSION_LATEST;

为了解决上述问题,需要补充的代码:

TlvContext.PeerVersion = WDI_VERSION_LATEST;

这个PeerVersion要和WdiVersion一致。

/* ======================================================================== Routine Description: API for MLME to transmit management frame to AP (BSS Mode) or station (IBSS Mode) Arguments: pAd Pointer to our adapter pData Pointer to the outgoing 802.11 frame Length Size of outgoing management frame Return Value: NDIS_STATUS_FAILURE NDIS_STATUS_PENDING NDIS_STATUS_SUCCESS IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL Note: ======================================================================== */ NDIS_STATUS MiniportMMRequest(RTMP_ADAPTER *pAd, UCHAR QueIdx, UCHAR *pData, UINT Length) { PNDIS_PACKET pkt; NDIS_STATUS Status; BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE; HEADER_802_11 *pHead = (HEADER_802_11 *)pData; struct wifi_dev *wdev = NULL; struct wifi_dev_ops *ops = NULL; INT hw_len; UCHAR hw_hdr[40]; struct tr_counter *tr_cnt = &pAd->tr_ctl.tr_cnt; struct _RTMP_CHIP_CAP *cap = hc_get_chip_cap(pAd->hdev_ctrl); #ifdef WF_RESET_SUPPORT if (pAd->wf_reset_in_progress == TRUE) return NDIS_STATUS_SUCCESS; #endif hw_len = cap->tx_hw_hdr_len; ASSERT((sizeof(hw_hdr) > hw_len)); NdisZeroMemory(&hw_hdr, hw_len); ASSERT(Length <= MAX_MGMT_PKT_LEN); Status = RTMPAllocateNdisPacket(pAd, &pkt, (UCHAR *)&hw_hdr[0], hw_len, pData, Length); if (Status != NDIS_STATUS_SUCCESS) { MTWF_DBG(pAd, DBG_CAT_TX, DBG_SUBCAT_ALL, DBG_LVL_ERROR, "MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"); return NDIS_STATUS_FAILURE; } wdev = wdev_search_by_address(pAd, pHead->Addr2); if (wdev) { ops = wdev->wdev_ops; } else { RELEASE_NDIS_PACKET(pAd, pkt, NDIS_STATUS_FAILURE); tr_cnt->tx_invalid_wdev++; return NDIS_STATUS_FAILURE; } if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) { bUseDataQ = TRUE; QueIdx &= (~MGMT_USE_QUEUE_FLAG); } if (bUseDataQ) FlgDataQForce = TRUE; #ifdef WIFI_DIAG diag_miniport_mm_request(pAd, pData, Length); #endif #if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) if (wdev->wdev_type == WDEV_TYPE_STA) RTMPWakeUpWdev(pAd, wdev); #endif /* CONFIG_STA_SUPPORT || APCLI_SUPPORT */ RTMP_SET_PACKET_TYPE(pkt, TX_MGMT); Status = send_mlme_pkt(pAd, pkt, wdev, QueIdx, bUseDataQ); return Status; }解析该函数
10-08
<think>我们正在分析`MiniportMMRequest`函数,该函数用于MLME(MAC子层管理实体)向AP(BSS模式)或站点(IBSS模式)传输管理帧。根据描述,我们需要解析其功能、参数、返回值以及执行流程。 函数原型通常如下(根据上下文推测,具体名称可能略有不同,但参数和返回值是给定的): ```c NDIS_STATUS MiniportMMRequest( IN NDIS_HANDLE MiniportAdapterContext, // 通常对应pAd IN UINT QueIdx, // 队列索引 IN PVOID pData, // 指向管理帧数据的指针 IN UINT Length // 管理帧长度 ); ``` ### 1. 函数功能 `MiniportMMRequest`的主要功能是处理MLME发送管理帧的请求。在无线网络驱动中,管理帧用于连接、认证、扫描等控制目的。该函数根据当前设备的工作模式(BSS模式即AP,或IBSS模式即Ad-hoc站点)将管理帧发送到指定的目标。 ### 2. 参数解析 - **pAd (MiniportAdapterContext)**: 指向驱动适配器上下文的指针,通常包含设备状态、配置信息、硬件寄存器映射等。 - **QueIdx**: 指定发送队列的索引。不同的队列可能用于不同优先级或类型的帧。 - **pData**: 指向要发送的管理帧数据的指针。管理帧结构通常符合802.11标准。 - **Length**: 管理帧数据的长度(以字节为单位)。 ### 3. 返回值 - **NDIS_STATUS_FAILURE**: 表示发送请求失败(如资源不足、设备状态异常等)。 - **NDIS_STATUS_PENDING**: 表示请求已被异步处理,完成状态稍后通知。 - **NDIS_STATUS_SUCCESS**: 表示发送请求已成功完成(注意:这通常仅表示请求被正确提交,并不保证对方收到)。 ### 4. 执行流程分析(典型实现) 以下是基于无线驱动典型实现的逻辑流程: #### (1) 参数校验 首先检查输入参数的有效性: ```c if (pAd == NULL || pData == NULL || Length == 0) { return NDIS_STATUS_FAILURE; } ``` #### (2) 设备状态检查 确保网卡处于可发送状态(如未处于关闭状态): ```c if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF)) { return NDIS_STATUS_FAILURE; } ``` #### (3) 管理帧构造 管理帧通常需要添加802.11 MAC头。此处可能直接使用传入的帧数据(假设已包含完整头部),或根据参数动态构建头部: ```c PHEADER_802_11 pHeader = (PHEADER_802_11)pData; // 检查帧类型是否为管理帧(Type=00, Subtype需在管理帧范围内) if ((pHeader->FC.Type != BTYPE_MGMT)) { return NDIS_STATUS_FAILURE; } ``` #### (4) 队列选择 根据`QueIdx`选择发送队列(通常管理帧使用高优先级队列): ```c QUEUE_ENTRY *pQueue; if (QueIdx >= NUM_OF_TX_QUEUE) { return NDIS_STATUS_FAILURE; } pQueue = &pAd->TxRing[QueIdx].Queue; ``` #### (5) 资源预留 分配硬件描述符和缓冲区资源: ```c PTXD_STRUC pTxD; PVOID buf = AllocateTxBuffer(pAd, Length); if (buf == NULL) { return NDIS_STATUS_RESOURCES; } ``` #### (6) 数据复制与描述符填充 将管理帧数据复制到DMA缓冲区,并配置发送描述符: ```c NdisMoveMemory(buf, pData, Length); // 复制帧数据 pTxD = GetFreeTxDescriptor(pAd, QueIdx); if (pTxD == NULL) { FreeTxBuffer(buf); return NDIS_STATUS_RESOURCES; } SetupTxDescForMgmtFrame(pTxD, buf, Length); // 设置描述符字段 ``` #### (7) 提交到硬件队列 将描述符加入硬件发送队列并触发发送: ```c if (RTMP_SEM_LOCK(&pAd->TxRingLock)) { InsertTailQueue(pQueue, &pTxD->QueueEntry); // 加入软件队列 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); // 通知硬件 RTMP_SEM_UNLOCK(&pAd->TxRingLock); return NDIS_STATUS_PENDING; // 异步处理中 } else { FreeTxDescriptor(pAd, pTxD); FreeTxBuffer(buf); return NDIS_STATUS_FAILURE; } ``` ### 5. 关键点说明 - **异步处理**:大部分驱动采用异步发送方式,因此返回`NDIS_STATUS_PENDING`表示操作已提交。 - **资源管理**:发送失败时需释放已分配的描述符和缓冲区。 - **硬件交互**:通过写寄存器通知硬件有新描述符待处理。 ### 6. 性能与可靠性 - **重试机制**:管理帧通常需要重传(如Probe Request),由硬件或驱动上层实现。 - **速率选择**:管理帧默认使用基础速率发送(由`pAd->CommonCfg.BasicRate`决定)[^1]。 --- §§相关问题§§ 1. 管理帧的速率选择策略如何影响网络性能? 2. 在多队列系统中,如何为管理帧选择最优队列? 3. 如何处理管理帧发送失败的场景? 4. 异步发送模式下,如何通知上层发送结果? </think>### `MiniportMMRequest` 函数深度解析 `MiniportMMRequest` 是无线网络驱动中的核心管理帧传输接口,用于 MLME(MAC 子层管理实体)向 AP(BSS 模式)或站点(IBSS 模式)发送管理帧(如信标帧、认证帧等)。其实现涉及底层硬件交互和协议栈协同,具体分析如下: --- #### **1. 函数原型与参数** ```c NDIS_STATUS MiniportMMRequest( IN NDIS_HANDLE pAd, // 适配器上下文指针(设备状态、寄存器映射等) IN UCHAR QueIdx, // 发送队列索引(区分优先级/帧类型) IN PVOID pData, // 管理帧数据缓冲区指针 IN ULONG Length // 管理帧长度 ); ``` --- #### **2. 返回值含义** | 返回值 | 含义 | |------------------------|----------------------------------------------------------------------| | `NDIS_STATUS_FAILURE` | 发送失败(硬件异常/参数无效/资源不足) | | `NDIS_STATUS_PENDING` | 请求已提交硬件异步处理,结果通过回调通知 | | `NDIS_STATUS_SUCCESS` | 发送成功(仅表示请求被硬件接收,不保证对端收到) | --- #### **3. 执行流程解析** ##### **3.1 参数校验与状态检查** ```c /* 步骤1:检查设备状态 */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { return NDIS_STATUS_FAILURE; // 设备正在停止[^1] } /* 步骤2:验证帧长度合法性 */ if (Length > MAX_MGMT_FRAME_SIZE) { DBGPRINT(RT_DEBUG_ERROR, ("Frame too long!\n")); return NDIS_STATUS_FAILURE; } ``` ##### **3.2 管理帧封装** 根据设备模式(BSS/IBSS)构建帧头: ```c // BSS模式(AP):目标地址=广播地址 if (OP_MODE(pAd) == OPMODE_AP) { BUILD_HEADER_802_11(pData, SUBTYPE_BEACON, BROADCAST_ADDR, pAd->CurrentAddress); } // IBSS模式(站点):目标地址=特定站点MAC else { BUILD_HEADER_802_11(pData, SUBTYPE_PROBE_REQ, TargetSTA_MAC, pAd->CurrentAddress); } ``` *注:帧类型由 MLME 通过 `pData` 预定义,此处补充地址信息[^2]*。 ##### **3.3 资源分配与DMA映射** ```c /* 步骤3:申请发送描述符 */ PTX_DESC pTxD = RTMP_AllocateTxDesc(pAd, QueIdx); if (!pTxD) { return NDIS_STATUS_RESOURCES; // 描述符不足 } /* 步骤4:DMA缓冲区映射 */ NDIS_STATUS status = NdisMAllocateSharedMemory(pAd->AdapterHandle, Length, &pDmaBuf); if (status != NDIS_STATUS_SUCCESS) { RTMP_FreeTxDesc(pAd, pTxD); return NDIS_STATUS_FAILURE; } /* 步骤5:数据复制到DMA区域 */ NdisMoveMemory(pDmaBuf->VirtualAddress, pData, Length); ``` ##### **3.4 硬件队列提交** ```c /* 步骤6:填充硬件描述符字段 */ pTxD->BufferAddress = pDmaBuf->PhysicalAddress; // 设置DMA物理地址 pTxD->FrameLength = Length; // 设置帧长度 pTxD->TxRate = pAd->CommonCfg.BasicRate; // 使用基础速率发送[^3] /* 步骤7:激活硬件发送 */ RTMP_IO_WRITE32(pAd, TX_QUEUE_CTRL, QueIdx | TX_QUEUE_KICK); return NDIS_STATUS_PENDING; // 异步处理中 ``` ##### **3.5 异步回调处理** 硬件发送完成后触发中断,在中断服务例程 (ISR) 中: ```c void MgmtFrameTxDoneISR(PADAPTER pAd, PTX_DESC pTxD) { /* 释放DMA资源 */ NdisMFreeSharedMemory(pAd->AdapterHandle, pTxD->DmaBuf); /* 通知MLME发送结果 */ MlmeTxDoneIndication(pAd, pTxD->Status); // STATUS_SUCCESS 或错误码 } ``` --- #### **4. 关键设计要点** 1. **速率选择策略** 管理帧默认使用基础速率 $R_{\text{base}}$ 发送: $$ R_{\text{base}} = \min \{ R_i \mid R_i \in \text{SupportedRates} \} $$ 确保所有站点可解码[^3]。 2. **队列优先级机制** - `QueIdx = 0`:高优先级队列(AC_VO),用于信标帧 - `QueIdx = 1`:普通队列(AC_BE),用于探测请求 *避免管理帧被数据帧阻塞*。 3. **异步发送保障** - 采用 `NDIS_STATUS_PENDING` 避免阻塞 MLME - 通过 DMA 和描述符环实现零拷贝传输[^4]。 --- #### **5. 典型调用场景** ```mermaid sequenceDiagram MLME->>MiniportMMRequest: 发送探测请求帧(QueIdx=1) MiniportMMRequest->>Hardware: 提交到发送队列 Hardware-->>MLME: 返回NDIS_STATUS_PENDING Hardware->>Air: 实际发送帧 Air-->>Hardware: 发送完成中断 Hardware->>MLME: 触发TxDone回调 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值