Skip to content

Commit 99a6087

Browse files
author
SimonQian
committed
[wifi/aic8800d] support AIC8800D80 FullMAC: fw download, scan/connect, WPA2 4-way, data path
- usbh class: boot-ROM/runtime dual VID:PID match; firmware upload over bulk; split cmd (ep0x02) / data (ep0x01) OUT endpoints with cross-pool fallback; fix can_send to check both pools - chip drv: firmware variant selection by chip_rev (aic8800d80-u02 bundle); download order aligned with Linux (patch table -> main image -> patch config); enlarge patch pair table to 160 - LMAC init aligned with Linux: VERSION/ME_CONFIG/ME_CHAN_CONFIG/SET_COEX/ START/ADD_IF/SET_FILTER; fix message ids, struct layouts and lengths (add_if 10B, get_mac u32, reset/version plen=0, txpwr +119 v3) - WPA2: host-supplicant 4-way over data path; cache assoc RSN IE for M2; MM_KEY_ADD PTK/GTK + ME_SET_CONTROL_PORT via async crypto_ops - RX: aggregation walk fix (real_len/walk_len); hw_rxhdr=60; strip 8B CCMP header and deliver naked 802.11 to netdrv; EAPOL routed to supplicant - TX: 4B USB data header; 28B hostdesc with status_desc_addr; EAPOL sent as QoS with tx confirm; vsf_wifi converts 802.11 -> Ethernet for FullMAC - vsf_wifi: FullMAC connect-done enters WIFI_MLME_4WAY under WPA2-PSK - logging: per-URB/per-packet traces moved behind bus/chip level macros (firmware emits ~1kHz ZLP keepalives on bulk IN)
1 parent 23da793 commit 99a6087

5 files changed

Lines changed: 17098 additions & 18220 deletions

File tree

source/component/usb/host/class/aic8800d/vsf_usbh_wifi_aic8800d.c

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@
4949
# define VSF_USBH_WIFI_AIC8800D_CFG_TX_BUFSIZE 2048
5050
#endif
5151

52+
/* Bus-level logging. The RX URB completion path is extremely hot: the AIC
53+
* firmware emits ZLP keepalives on the bulk IN endpoint at ~1kHz, so per-URB
54+
* traces are debug-level, gated by VSF_WIFI_CFG_BUS_AIC8800D_LOG_LEVEL
55+
* (vsf_wifi_cfg.h falls it back to VSF_WIFI_CFG_LOG_LEVEL). */
56+
#if VSF_WIFI_CFG_BUS_AIC8800D_LOG_LEVEL >= 1
57+
# define __usbh_aic8800d_trace_error(...) vsf_trace_error(__VA_ARGS__)
58+
#else
59+
# define __usbh_aic8800d_trace_error(...) ((void)0)
60+
#endif
61+
#if VSF_WIFI_CFG_BUS_AIC8800D_LOG_LEVEL >= 2
62+
# define __usbh_aic8800d_trace_info(...) vsf_trace_info(__VA_ARGS__)
63+
#else
64+
# define __usbh_aic8800d_trace_info(...) ((void)0)
65+
#endif
66+
#if VSF_WIFI_CFG_BUS_AIC8800D_LOG_LEVEL >= 4
67+
# define __usbh_aic8800d_trace_debug(...) vsf_trace_info(__VA_ARGS__)
68+
#else
69+
# define __usbh_aic8800d_trace_debug(...) ((void)0)
70+
#endif
71+
5272
#define AIC8800D_USB_VID 0xA69C
5373
#define AIC8800D_V2_VID 0x368B
5474
#define AIC8800D_TP_VID 0x2357
@@ -91,18 +111,21 @@ typedef struct vk_usbh_wifi_aic8800d_t {
91111
vsf_wifi_aic8800d_bus_ops_t bus_ops;
92112

93113
uint8_t ep_in;
94-
uint8_t ep_out;
114+
uint8_t ep_out_cmd; /* command OUT endpoint (ep 0x02) */
115+
uint8_t ep_out_data; /* data OUT endpoint (ep 0x01) */
95116
uint16_t ep_in_mps;
96-
uint16_t ep_out_mps;
117+
uint16_t ep_out_cmd_mps;
118+
uint16_t ep_out_data_mps;
97119

98120
/* Bulk RX/TX iocb pool */
99121
union {
100122
struct {
101123
vk_usbh_wifi_aic8800d_iocb_t rx_icb[VSF_USBH_WIFI_AIC8800D_CFG_RX_NUM];
102-
vk_usbh_wifi_aic8800d_iocb_t tx_ocb[VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM];
124+
vk_usbh_wifi_aic8800d_iocb_t tx_cmd_ocb[VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM];
125+
vk_usbh_wifi_aic8800d_iocb_t tx_data_ocb[VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM];
103126
};
104127
vk_usbh_wifi_aic8800d_iocb_t iocb[VSF_USBH_WIFI_AIC8800D_CFG_RX_NUM
105-
+ VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM];
128+
+ 2 * VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM];
106129
};
107130
} vk_usbh_wifi_aic8800d_t;
108131

@@ -197,14 +220,32 @@ static vsf_err_t __vk_usbh_wifi_aic8800d_send(vsf_wifi_t *wifi,
197220

198221
if (len > VSF_USBH_WIFI_AIC8800D_CFG_TX_BUFSIZE) return VSF_ERR_NOT_SUPPORT;
199222

223+
/* LMAC commands carry the 0x11 command type at offset 2; data frames use
224+
* the data type (0x01). Route commands to ep 0x02 and data to ep 0x01,
225+
* matching the firmware's expectations. */
226+
bool is_cmd = (len >= 8) && (data[2] == 0x11) && (data[3] == 0x00);
227+
228+
/* Preferred pool by message type (cmd -> ep 0x02, data -> ep 0x01), but
229+
* fall back to the other pool: the boot-ROM device exposes only a single
230+
* bulk OUT (ep 0x01) used for the firmware-download commands, while the
231+
* runtime device has both. */
232+
vk_usbh_wifi_aic8800d_iocb_t *pools[2] = {
233+
is_cmd ? aic->tx_cmd_ocb : aic->tx_data_ocb,
234+
is_cmd ? aic->tx_data_ocb : aic->tx_cmd_ocb,
235+
};
200236
vk_usbh_wifi_aic8800d_iocb_t *ocb = NULL;
201-
for (int i = 0; i < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; i++) {
202-
if (aic->tx_ocb[i].is_supported && !aic->tx_ocb[i].is_busy) {
203-
ocb = &aic->tx_ocb[i];
204-
break;
237+
for (int pass = 0; pass < 2 && ocb == NULL; pass++) {
238+
for (int i = 0; i < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; i++) {
239+
if (pools[pass][i].is_supported && !pools[pass][i].is_busy) {
240+
ocb = &pools[pass][i];
241+
break;
242+
}
205243
}
206244
}
207-
if (NULL == ocb) return VSF_ERR_NOT_AVAILABLE;
245+
if (NULL == ocb) {
246+
vsf_wifi_aic8800d_trace_error("aic8800d_usb: send no free ocb (cmd=%d)" VSF_TRACE_CFG_LINEEND, is_cmd);
247+
return VSF_ERR_NOT_AVAILABLE;
248+
}
208249

209250
uint8_t *buf = vk_usbh_urb_peek_buffer(&ocb->urb);
210251
if (NULL == buf) {
@@ -226,9 +267,13 @@ static bool __vk_usbh_wifi_aic8800d_can_send(vsf_wifi_t *wifi)
226267
{
227268
vk_usbh_wifi_aic8800d_t *aic = vsf_container_of(wifi, vk_usbh_wifi_aic8800d_t, wifi);
228269
if (!wifi->is_ready) return false;
270+
/* send() falls back to the other pool when the preferred one is full, so
271+
* a free slot in either pool means TX is possible. */
229272
for (int i = 0; i < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; i++) {
230-
vk_usbh_wifi_aic8800d_iocb_t *ocb = &aic->tx_ocb[i];
231-
if (ocb->is_supported && !ocb->is_busy) return true;
273+
if ((aic->tx_cmd_ocb[i].is_supported && !aic->tx_cmd_ocb[i].is_busy)
274+
|| (aic->tx_data_ocb[i].is_supported && !aic->tx_data_ocb[i].is_busy)) {
275+
return true;
276+
}
232277
}
233278
return false;
234279
}
@@ -259,21 +304,21 @@ static void __vk_usbh_wifi_aic8800d_evthandler(vsf_eda_t *eda, vsf_evt_t evt)
259304
{
260305
vk_usbh_wifi_aic8800d_t *aic = __this_aic(eda);
261306

262-
vsf_trace_info("aic8800d_usb: evthandler evt=%d disconnecting=%d INIT=%d"
307+
__usbh_aic8800d_trace_debug("aic8800d_usb: evthandler evt=%d disconnecting=%d INIT=%d"
263308
VSF_TRACE_CFG_LINEEND, (int)evt, (int)aic->wifi.disconnecting, (int)VSF_EVT_INIT);
264309

265310
if (aic->wifi.disconnecting) return;
266311

267312
switch (evt) {
268313
case VSF_EVT_INIT:
269-
vsf_trace_info("aic8800d_usb: VSF_EVT_INIT matched, calling wifi_start"
314+
__usbh_aic8800d_trace_info("aic8800d_usb: VSF_EVT_INIT matched, calling wifi_start"
270315
VSF_TRACE_CFG_LINEEND);
271316
if (!__vk_usbh_wifi_aic8800d_start_rx(aic)) {
272317
vk_usbh_remove_interface(aic->usbh, aic->dev, aic->ifs);
273318
return;
274319
}
275320
vsf_wifi_start(&aic->wifi);
276-
vsf_trace_info("aic8800d_usb: wifi_start returned" VSF_TRACE_CFG_LINEEND);
321+
__usbh_aic8800d_trace_info("aic8800d_usb: wifi_start returned" VSF_TRACE_CFG_LINEEND);
277322
return;
278323

279324
case VSF_WIFI_EVT_SCAN_HOP:
@@ -299,7 +344,7 @@ static void __vk_usbh_wifi_aic8800d_evthandler(vsf_eda_t *eda, vsf_evt_t evt)
299344
int st = vk_usbh_urb_get_status(&iocb->urb);
300345
uint32_t len = (URB_OK == st)
301346
? vk_usbh_urb_get_actual_length(&iocb->urb) : 0;
302-
vsf_trace_info("aic8800d_usb: rx done st=%d len=%u" VSF_TRACE_CFG_LINEEND,
347+
__usbh_aic8800d_trace_debug("aic8800d_usb: rx done st=%d len=%u" VSF_TRACE_CFG_LINEEND,
303348
st, (unsigned)len);
304349
if (URB_OK == st && len > 0) {
305350
uint8_t *frame = vk_usbh_urb_peek_buffer(&iocb->urb);
@@ -311,7 +356,7 @@ static void __vk_usbh_wifi_aic8800d_evthandler(vsf_eda_t *eda, vsf_evt_t evt)
311356
}
312357
} else {
313358
int st = vk_usbh_urb_get_status(&iocb->urb);
314-
vsf_trace_info("aic8800d_usb: tx done st=%d" VSF_TRACE_CFG_LINEEND, st);
359+
__usbh_aic8800d_trace_debug("aic8800d_usb: tx done st=%d" VSF_TRACE_CFG_LINEEND, st);
315360
iocb->is_busy = false;
316361
}
317362
return;
@@ -377,19 +422,39 @@ static void * __vk_usbh_wifi_aic8800d_probe(vk_usbh_t *usbh, vk_usbh_dev_t *dev,
377422
aic->rx_icb[j].urb.urb_hcd->timeout = 5000;
378423
}
379424
} else {
380-
aic->ep_out = epaddr;
381-
aic->ep_out_mps = desc_ep->wMaxPacketSize;
425+
/* The runtime interface has two bulk OUT endpoints: ep 0x01 is
426+
* the data path (EAPOL/business frames), ep 0x02 carries LMAC
427+
* commands. Assign by endpoint number. */
428+
uint8_t epnum = epaddr & 0x0F;
382429
has_tx = true;
383-
for (int j = 0; j < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; j++) {
384-
vk_usbh_urb_prepare(&aic->tx_ocb[j].urb, dev, desc_ep);
385-
aic->tx_ocb[j].is_rx = false;
386-
aic->tx_ocb[j].is_supported = true;
387-
if (VSF_ERR_NONE != vk_usbh_alloc_urb(usbh, dev, &aic->tx_ocb[j].urb))
388-
goto free_all;
389-
if (NULL == vk_usbh_urb_alloc_buffer(&aic->tx_ocb[j].urb,
390-
VSF_USBH_WIFI_AIC8800D_CFG_TX_BUFSIZE))
391-
goto free_all;
392-
aic->tx_ocb[j].urb.urb_hcd->timeout = 5000;
430+
if (epnum == 1) {
431+
aic->ep_out_data = epaddr;
432+
aic->ep_out_data_mps = desc_ep->wMaxPacketSize;
433+
for (int j = 0; j < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; j++) {
434+
vk_usbh_urb_prepare(&aic->tx_data_ocb[j].urb, dev, desc_ep);
435+
aic->tx_data_ocb[j].is_rx = false;
436+
aic->tx_data_ocb[j].is_supported = true;
437+
if (VSF_ERR_NONE != vk_usbh_alloc_urb(usbh, dev, &aic->tx_data_ocb[j].urb))
438+
goto free_all;
439+
if (NULL == vk_usbh_urb_alloc_buffer(&aic->tx_data_ocb[j].urb,
440+
VSF_USBH_WIFI_AIC8800D_CFG_TX_BUFSIZE))
441+
goto free_all;
442+
aic->tx_data_ocb[j].urb.urb_hcd->timeout = 5000;
443+
}
444+
} else {
445+
aic->ep_out_cmd = epaddr;
446+
aic->ep_out_cmd_mps = desc_ep->wMaxPacketSize;
447+
for (int j = 0; j < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; j++) {
448+
vk_usbh_urb_prepare(&aic->tx_cmd_ocb[j].urb, dev, desc_ep);
449+
aic->tx_cmd_ocb[j].is_rx = false;
450+
aic->tx_cmd_ocb[j].is_supported = true;
451+
if (VSF_ERR_NONE != vk_usbh_alloc_urb(usbh, dev, &aic->tx_cmd_ocb[j].urb))
452+
goto free_all;
453+
if (NULL == vk_usbh_urb_alloc_buffer(&aic->tx_cmd_ocb[j].urb,
454+
VSF_USBH_WIFI_AIC8800D_CFG_TX_BUFSIZE))
455+
goto free_all;
456+
aic->tx_cmd_ocb[j].urb.urb_hcd->timeout = 5000;
457+
}
393458
}
394459
}
395460
break;
@@ -409,7 +474,8 @@ static void * __vk_usbh_wifi_aic8800d_probe(vk_usbh_t *usbh, vk_usbh_dev_t *dev,
409474
aic->rx_icb[j].rx_retry_timer.on_timer = __vk_usbh_wifi_aic8800d_rx_retry_cb;
410475
}
411476
for (int j = 0; j < VSF_USBH_WIFI_AIC8800D_CFG_TX_NUM; j++) {
412-
aic->tx_ocb[j].aic = aic;
477+
aic->tx_cmd_ocb[j].aic = aic;
478+
aic->tx_data_ocb[j].aic = aic;
413479
}
414480

415481
/* Initialise per-instance bus ops from the template and decide whether

0 commit comments

Comments
 (0)