1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /*
17 * Simple virtio-net driver using HDF WIFI framework without real WIFI functions.
18 */
19
20 #include "los_hw_cpu.h"
21 #include "los_vm_iomap.h"
22 #include "los_vm_zone.h"
23 #include "netinet/if_ether.h"
24 #include "arpa/inet.h"
25 #include "hdf_device_desc.h"
26 #include "wifi/hdf_wlan_chipdriver_manager.h"
27 #include "wifi/wifi_mac80211_ops.h"
28 #include "osal.h"
29 #include "osal_io.h"
30 #include "eapol.h"
31 #include "virtmmio.h"
32
33 #define HDF_LOG_TAG HDF_VIRTIO_NET
34
35 #define VIRTIO_NET_F_MTU (1 << 3)
36 #define VIRTIO_NET_F_MAC (1 << 5)
37 struct VirtnetConfig {
38 uint8_t mac[6];
39 uint16_t status;
40 uint16_t maxVirtqPairs;
41 uint16_t mtu;
42 };
43
44 #define VIRTMMIO_NETIF_NAME "virtnet"
45 #define VIRTMMIO_NETIF_DFT_GW "10.0.2.2"
46 #define VIRTMMIO_NETIF_DFT_MASK "255.255.255.0"
47
48 /* This struct is actually ignored by this simple driver */
49 struct VirtnetHdr {
50 uint8_t flag;
51 uint8_t gsoType;
52 uint16_t hdrLen;
53 uint16_t gsoSize;
54 uint16_t csumStart;
55 uint16_t csumOffset;
56 uint16_t numBuffers;
57 };
58
59 /*
60 * We use two queues for Tx/Rx respectively. When Tx, we record outgoing NetBuf
61 * and free it when QEMU done. When Rx, we use fixed buffers, then allocate &
62 * copy to a NetBuf, and then HDF will consume & free the NetBuf.
63 * Every NetBuf is a solo packet, no chaining like LWIP pbuf. So every outgoing
64 * packet always occupy two desc items: one for VirtnetHdr, the other for NetBuf.
65 * Tx/Rx queues memory layout:
66 * Rx queue Tx queue
67 * +-----------------+------------------+------------------++------+-------+------+
68 * | desc: 16B align | avail: 2B align | used: 4B align || desc | avail | used |
69 * | 16∗(Queue Size) | 4+2∗(Queue Size) | 4+8∗(Queue Size) || | | |
70 * +-----------------+------------------+------------------++------+-------+------+
71 */
72 #define VIRTQ_RX_QSZ 16
73 #define VIRTQ_TX_QSZ 32
74 #define PER_TX_ENTRIES 2
75 #define PER_RXBUF_SIZE (sizeof(struct VirtnetHdr) + ETH_FRAME_LEN)
76
77 struct VirtNetif {
78 struct VirtmmioDev dev;
79
80 uint16_t tFreeHdr; /* head of Tx free desc entries list */
81 uint16_t tFreeNum;
82 NetBuf* tbufRec[VIRTQ_TX_QSZ];
83 OSAL_DECLARE_SPINLOCK(transLock);
84
85 uint8_t rbuf[VIRTQ_RX_QSZ][PER_RXBUF_SIZE];
86
87 struct VirtnetHdr vnHdr;
88 };
89
GetVirtnetIf(const NetDevice * netDev)90 static inline struct VirtNetif *GetVirtnetIf(const NetDevice *netDev)
91 {
92 return (struct VirtNetif *)GET_NET_DEV_PRIV(netDev);
93 }
94
Feature0(uint32_t features,uint32_t * supported,void * dev)95 static bool Feature0(uint32_t features, uint32_t *supported, void *dev)
96 {
97 NetDevice *netDev = dev;
98 struct VirtNetif *nic = GetVirtnetIf(netDev);
99 struct VirtnetConfig *conf = (struct VirtnetConfig *)(nic->dev.base + VIRTMMIO_REG_CONFIG);
100 int i;
101
102 if (features & VIRTIO_NET_F_MTU) {
103 if (conf->mtu > WLAN_MAX_MTU || conf->mtu < WLAN_MIN_MTU) {
104 HDF_LOGE("[%s]unsupported backend net MTU: %u", __func__, conf->mtu);
105 return false;
106 }
107 netDev->mtu = conf->mtu;
108 *supported |= VIRTIO_NET_F_MTU;
109 } else {
110 netDev->mtu = DEFAULT_MTU;
111 }
112
113 if ((features & VIRTIO_NET_F_MAC) == 0) {
114 HDF_LOGE("[%s]no MAC feature found", __func__);
115 return false;
116 }
117 for (i = 0; i < MAC_ADDR_SIZE; i++) {
118 netDev->macAddr[i] = conf->mac[i];
119 }
120 netDev->addrLen = MAC_ADDR_SIZE;
121 *supported |= VIRTIO_NET_F_MAC;
122
123 return true;
124 }
125
Feature1(uint32_t features,uint32_t * supported,void * dev)126 static bool Feature1(uint32_t features, uint32_t *supported, void *dev)
127 {
128 (void)dev;
129 if (features & VIRTIO_F_VERSION_1) {
130 *supported |= VIRTIO_F_VERSION_1;
131 } else {
132 HDF_LOGE("[%s]net device has no VERSION_1 feature", __func__);
133 return false;
134 }
135
136 return true;
137 }
138
InitTxFreelist(struct VirtNetif * nic)139 static int32_t InitTxFreelist(struct VirtNetif *nic)
140 {
141 int i;
142
143 for (i = 0; i < nic->dev.vq[1].qsz - 1; i++) {
144 nic->dev.vq[1].desc[i].flag = VIRTQ_DESC_F_NEXT;
145 nic->dev.vq[1].desc[i].next = i + 1;
146 }
147 nic->tFreeHdr = 0;
148 nic->tFreeNum = nic->dev.vq[1].qsz;
149
150 return OsalSpinInit(&nic->transLock);
151 }
152
FreeTxEntry(struct VirtNetif * nic,uint16_t head)153 static void FreeTxEntry(struct VirtNetif *nic, uint16_t head)
154 {
155 struct Virtq *q = &nic->dev.vq[1];
156 uint16_t idx = q->desc[head].next;
157 NetBuf *nb = NULL;
158
159 /* keep track of virt queue free entries */
160 OsalSpinLock(&nic->transLock);
161 if (nic->tFreeNum > 0) {
162 q->desc[idx].next = nic->tFreeHdr;
163 q->desc[idx].flag = VIRTQ_DESC_F_NEXT;
164 }
165 nic->tFreeNum += PER_TX_ENTRIES;
166 nic->tFreeHdr = head;
167 nb = nic->tbufRec[idx];
168 OsalSpinUnlock(&nic->transLock);
169
170 /* We free upstream Tx NetBuf! */
171 NetBufFree(nb);
172 }
173
PopulateRxBuffer(struct VirtNetif * nic)174 static void PopulateRxBuffer(struct VirtNetif *nic)
175 {
176 uint32_t i;
177 PADDR_T paddr;
178 struct Virtq *q = &nic->dev.vq[0];
179
180 for (i = 0; i < q->qsz; i++) {
181 paddr = VMM_TO_DMA_ADDR((VADDR_T)nic->rbuf[i]);
182
183 q->desc[i].pAddr = paddr;
184 q->desc[i].len = PER_RXBUF_SIZE;
185 q->desc[i].flag = VIRTQ_DESC_F_WRITE;
186
187 q->avail->ring[i] = i;
188 }
189 }
190
ConfigQueue(struct VirtNetif * nic)191 static int32_t ConfigQueue(struct VirtNetif *nic)
192 {
193 VADDR_T base;
194 uint16_t qsz[VIRTQ_NUM];
195
196 base = ALIGN((VADDR_T)nic + sizeof(struct VirtNetif), VIRTQ_ALIGN_DESC);
197 qsz[0] = VIRTQ_RX_QSZ;
198 qsz[1] = VIRTQ_TX_QSZ;
199 if (VirtmmioConfigQueue(&nic->dev, base, qsz, VIRTQ_NUM) == 0) {
200 return HDF_DEV_ERR_DEV_INIT_FAIL;
201 }
202
203 PopulateRxBuffer(nic);
204
205 return InitTxFreelist(nic);
206 }
207
GetTxFreeEntry(struct VirtNetif * nic)208 static uint16_t GetTxFreeEntry(struct VirtNetif *nic)
209 {
210 uint32_t intSave;
211 uint16_t head, idx;
212 bool logged = false;
213
214 RETRY:
215 OsalSpinLockIrqSave(&nic->transLock, &intSave);
216 if (PER_TX_ENTRIES > nic->tFreeNum) {
217 OsalSpinUnlockIrqRestore(&nic->transLock, &intSave);
218 if (!logged) {
219 HDF_LOGW("[%s]transmit queue is full", __func__);
220 logged = true;
221 }
222 LOS_TaskYield();
223 goto RETRY;
224 }
225
226 nic->tFreeNum -= PER_TX_ENTRIES;
227 head = nic->tFreeHdr;
228 idx = nic->dev.vq[1].desc[head].next;
229 /* new tFreeHdr may be invalid if list is empty, but tFreeNum must be valid: 0 */
230 nic->tFreeHdr = nic->dev.vq[1].desc[idx].next;
231 OsalSpinUnlockIrqRestore(&nic->transLock, &intSave);
232 nic->dev.vq[1].desc[idx].flag &= ~VIRTQ_DESC_F_NEXT;
233
234 return head;
235 }
236
LowLevelOutput(NetDevice * netDev,NetBuf * p)237 static NetDevTxResult LowLevelOutput(NetDevice *netDev, NetBuf *p)
238 {
239 uint16_t idx, head;
240 struct VirtNetif *nic = GetVirtnetIf(netDev);
241 struct Virtq *trans = &nic->dev.vq[1];
242
243 head = GetTxFreeEntry(nic);
244 trans->desc[head].pAddr = VMM_TO_DMA_ADDR((PADDR_T)&nic->vnHdr);
245 trans->desc[head].len = sizeof(struct VirtnetHdr);
246 idx = trans->desc[head].next;
247 trans->desc[idx].pAddr = LOS_PaddrQuery(NetBufGetAddress(p, E_DATA_BUF));
248 trans->desc[idx].len = NetBufGetDataLen(p);
249
250 nic->tbufRec[idx] = p;
251
252 trans->avail->ring[trans->avail->index % trans->qsz] = head;
253 DSB;
254 trans->avail->index++;
255 if (trans->used->flag != VIRTQ_USED_F_NO_NOTIFY) {
256 OSAL_WRITEL(1, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY);
257 }
258
259 return NETDEV_TX_OK;
260 }
261
LowLevelInput(const NetDevice * netDev,const struct VirtqUsedElem * e)262 static NetBuf *LowLevelInput(const NetDevice *netDev, const struct VirtqUsedElem *e)
263 {
264 struct VirtNetif *nic = GetVirtnetIf(netDev);
265 uint16_t len;
266 uint8_t *payload = NULL;
267 NetBuf *nb = NULL;
268
269 /* we allocate Rx NetBuf & fill in received packet */
270 len = e->len - sizeof(struct VirtnetHdr);
271 nb = NetBufDevAlloc(netDev, len);
272 if (nb == NULL) {
273 HDF_LOGE("[%s]allocate NetBuf failed, drop 1 packet", __func__);
274 return NULL;
275 }
276 payload = NetBufPush(nb, E_DATA_BUF, len); /* here always succeed */
277 (void)memcpy_s(payload, len, nic->rbuf[e->id] + sizeof(struct VirtnetHdr), len);
278
279 return nb;
280 }
281
VirtnetRxHandle(NetDevice * netDev)282 static void VirtnetRxHandle(NetDevice *netDev)
283 {
284 struct VirtNetif *nic = GetVirtnetIf(netDev);
285 struct Virtq *q = &nic->dev.vq[0];
286 NetBuf *nb = NULL;
287 struct VirtqUsedElem *e = NULL;
288 uint16_t add = 0;
289
290 q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT;
291 while (1) {
292 if (q->last == q->used->index) {
293 q->avail->flag = 0;
294 /* recheck if new one come in between empty ring and enable interrupt */
295 DSB;
296 if (q->last == q->used->index) {
297 break;
298 }
299 q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT;
300 }
301
302 DSB;
303 e = &q->used->ring[q->last % q->qsz];
304 nb = LowLevelInput(netDev, e);
305 if (nb && NetIfRx(netDev, nb) != 0) { /* Upstream free Rx NetBuf! */
306 HDF_LOGE("[%s]NetIfRx failed, drop 1 packet", __func__);
307 NetBufFree(nb);
308 }
309
310 /*
311 * Our fixed receive buffers always sit in the appropriate desc[].
312 * We only need to update the available ring to QEMU.
313 */
314 q->avail->ring[(q->avail->index + add++) % q->qsz] = e->id;
315 q->last++;
316 }
317 DSB;
318 q->avail->index += add;
319
320 if (q->used->flag != VIRTQ_USED_F_NO_NOTIFY) {
321 OSAL_WRITEL(0, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY);
322 }
323 }
324
VirtnetTxHandle(struct VirtNetif * nic)325 static void VirtnetTxHandle(struct VirtNetif *nic)
326 {
327 struct Virtq *q = &nic->dev.vq[1];
328 struct VirtqUsedElem *e = NULL;
329
330 /* Bypass recheck as VirtnetRxHandle */
331 q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT;
332 while (q->last != q->used->index) {
333 DSB;
334 e = &q->used->ring[q->last % q->qsz];
335 FreeTxEntry(nic, e->id);
336 q->last++;
337 }
338 q->avail->flag = 0;
339 }
340
VirtnetIRQhandle(int swIrq,void * pDevId)341 static void VirtnetIRQhandle(int swIrq, void *pDevId)
342 {
343 (void)swIrq;
344 NetDevice *netDev = pDevId;
345 struct VirtNetif *nic = GetVirtnetIf(netDev);
346
347 if (!(OSAL_READL(nic->dev.base + VIRTMMIO_REG_INTERRUPTSTATUS) & VIRTMMIO_IRQ_NOTIFY_USED)) {
348 return;
349 }
350
351 VirtnetRxHandle(netDev);
352
353 VirtnetTxHandle(nic);
354
355 OSAL_WRITEL(VIRTMMIO_IRQ_NOTIFY_USED, nic->dev.base + VIRTMMIO_REG_INTERRUPTACK);
356 }
357
358 /*
359 * The whole initialization is complex, here is the main point.
360 * -factory- FakeWifiInit/Release: alloc, set & register HdfChipDriverFactory
361 * -chip- FakeFactoryInitChip/Release: alloc & set HdfChipDriver
362 * -NetDevice- VirtNetDeviceInit/DeInit: set & add NetDevice
363 * -virtnet- VirtnetInit/DeInit: virtio-net driver
364 */
365
VirtnetInit(NetDevice * netDev)366 static int32_t VirtnetInit(NetDevice *netDev)
367 {
368 int32_t ret, len;
369 struct VirtNetif *nic = NULL;
370
371 /* NOTE: For simplicity, alloc all these data from physical continuous memory. */
372 len = sizeof(struct VirtNetif) + VirtqSize(VIRTQ_RX_QSZ) + VirtqSize(VIRTQ_TX_QSZ);
373 nic = LOS_DmaMemAlloc(NULL, len, sizeof(void *), DMA_CACHE);
374 if (nic == NULL) {
375 HDF_LOGE("[%s]alloc nic memory failed", __func__);
376 return HDF_ERR_MALLOC_FAIL;
377 }
378 memset_s(nic, len, 0, len);
379 GET_NET_DEV_PRIV(netDev) = nic;
380
381 if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_NET, &nic->dev)) {
382 return HDF_DEV_ERR_NO_DEVICE;
383 }
384
385 VirtmmioInitBegin(&nic->dev);
386
387 if (!VirtmmioNegotiate(&nic->dev, Feature0, Feature1, netDev)) {
388 ret = HDF_DEV_ERR_DEV_INIT_FAIL;
389 goto ERR_OUT;
390 }
391
392 if ((ret = ConfigQueue(nic)) != HDF_SUCCESS) {
393 goto ERR_OUT;
394 }
395
396 ret = OsalRegisterIrq(nic->dev.irq, OSAL_IRQF_TRIGGER_NONE, (OsalIRQHandle)VirtnetIRQhandle,
397 VIRTMMIO_NETIF_NAME, netDev);
398 if (ret != HDF_SUCCESS) {
399 HDF_LOGE("[%s]register IRQ failed: %d", __func__, ret);
400 goto ERR_OUT;
401 }
402 nic->dev.irq |= ~_IRQ_MASK;
403
404 VritmmioInitEnd(&nic->dev);
405 return HDF_SUCCESS;
406
407 ERR_OUT:
408 VirtmmioInitFailed(&nic->dev);
409 return ret;
410 }
411
VirtnetDeInit(NetDevice * netDev)412 static void VirtnetDeInit(NetDevice *netDev)
413 {
414 struct VirtNetif *nic = GetVirtnetIf(netDev);
415
416 if (nic && (nic->dev.irq & ~_IRQ_MASK)) {
417 OsalUnregisterIrq(nic->dev.irq & _IRQ_MASK, netDev);
418 }
419 if (nic) {
420 LOS_DmaMemFree(nic);
421 }
422 GET_NET_DEV_PRIV(netDev) = NULL;
423 }
424
VirtNetDeviceSetMacAddr(NetDevice * netDev,void * addr)425 static int32_t VirtNetDeviceSetMacAddr(NetDevice *netDev, void *addr)
426 {
427 uint8_t *p = addr;
428 for (int i = 0; i < netDev->addrLen; i++) {
429 netDev->macAddr[i] = p[i];
430 }
431 return HDF_SUCCESS;
432 }
433
434 static struct NetDeviceInterFace g_netDevOps = {
435 .setMacAddr = VirtNetDeviceSetMacAddr,
436 /*
437 * Link layer packet transmission chain:
438 * LWIP netif->linkoutput = driverif_output, in kernel, pbuf
439 * KHDF netif->drv_send = LwipSend, in HDF adapter, NetBuf
440 * NetDevice .xmit = our driver, NetBuf
441 */
442 .xmit = LowLevelOutput,
443 };
444
445 #define VN_RANDOM_IP_MASK 0xFF /* 255.255.255.0 subnet */
446 #define VN_RANDOM_IP_SHF 24 /* network byte order */
447
448 /* fake WIFI have to UP interface, assign IP by hand */
VirtNetDeviceInitDone(NetDevice * netDev)449 static int32_t VirtNetDeviceInitDone(NetDevice *netDev)
450 {
451 IpV4Addr ip, mask, gw;
452 uint32_t h, l;
453 int32_t ret;
454
455 if ((ret = NetIfSetStatus(netDev, NETIF_UP)) != HDF_SUCCESS) {
456 return ret;
457 }
458
459 /* odd way hope to get ~distinct~ IP for different guests */
460 LOS_GetCpuCycle(&h, &l);
461 l &= VN_RANDOM_IP_MASK;
462 if (l == 0 || l == (1 << 1)) { /* avoid 10.0.2.0, 10.0.2.2 */
463 l++;
464 } else if (l == VN_RANDOM_IP_MASK) { /* avoid 10.0.2.255 */
465 l--;
466 }
467 l <<= VN_RANDOM_IP_SHF;
468 ip.addr = (inet_addr(VIRTMMIO_NETIF_DFT_MASK) & inet_addr(VIRTMMIO_NETIF_DFT_GW)) | l;
469 mask.addr = inet_addr(VIRTMMIO_NETIF_DFT_MASK);
470 gw.addr = inet_addr(VIRTMMIO_NETIF_DFT_GW);
471 return NetIfSetAddr(netDev, &ip, &mask, &gw);
472 }
473
VirtNetDeviceInit(struct HdfChipDriver * chipDriver,NetDevice * netDev)474 static int32_t VirtNetDeviceInit(struct HdfChipDriver *chipDriver, NetDevice *netDev)
475 {
476 (void)chipDriver;
477 int32_t ret;
478
479 /* VirtnetInit also set netDev->macAddr, mtu, addrLen */
480 if ((ret = VirtnetInit(netDev)) != HDF_SUCCESS) {
481 return ret;
482 }
483 netDev->flags = NET_DEVICE_IFF_RUNNING;
484 netDev->neededHeadRoom = 0;
485 netDev->neededTailRoom = 0;
486 netDev->funType.wlanType = PROTOCOL_80211_IFTYPE_STATION;
487 netDev->netDeviceIf = &g_netDevOps;
488 if ((ret = NetDeviceAdd(netDev)) != HDF_SUCCESS) {
489 goto ERR_OUT;
490 }
491 if ((ret = CreateEapolData(netDev)) != HDF_SUCCESS) {
492 goto ERR_OUT;
493 }
494
495 /* everything is ready, now notify device the receive buffers */
496 struct VirtNetif *nic = GetVirtnetIf(netDev);
497 nic->dev.vq[0].avail->index = nic->dev.vq[0].qsz;
498 OSAL_WRITEL(0, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY);
499
500 return VirtNetDeviceInitDone(netDev);
501
502 ERR_OUT:
503 VirtnetDeInit(netDev);
504 return ret;
505 }
506
VirtNetDeviceDeInit(struct HdfChipDriver * chipDriver,NetDevice * netDev)507 static int32_t VirtNetDeviceDeInit(struct HdfChipDriver *chipDriver, NetDevice *netDev)
508 {
509 (void)chipDriver;
510
511 DestroyEapolData(netDev);
512
513 if (GetVirtnetIf(netDev)) {
514 VirtnetDeInit(netDev);
515 }
516
517 return NetDeviceDelete(netDev);
518 }
519
520
521 /*
522 * Followings are mainly fake data & funcs to mimic a wireless card.
523 *
524 * Here is fake MAC80211 base operations.
525 */
FakeWalSetMode(NetDevice * netDev,enum WlanWorkMode mode)526 static int32_t FakeWalSetMode(NetDevice *netDev, enum WlanWorkMode mode)
527 {
528 (void)netDev;
529 if (mode != WLAN_WORKMODE_STA) {
530 HDF_LOGE("[%s]unsupported WLAN mode: %u", __func__, mode);
531 return HDF_ERR_NOT_SUPPORT;
532 }
533 return HDF_SUCCESS;
534 }
FakeWalAddKey(NetDevice * netDev,uint8_t keyIndex,bool pairwise,const uint8_t * macAddr,struct KeyParams * params)535 static int32_t FakeWalAddKey(NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr,
536 struct KeyParams *params)
537 {
538 (void)netDev;
539 (void)keyIndex;
540 (void)pairwise;
541 (void)macAddr;
542 (void)params;
543 return HDF_SUCCESS;
544 }
FakeWalDelKey(NetDevice * netDev,uint8_t keyIndex,bool pairwise,const uint8_t * macAddr)545 static int32_t FakeWalDelKey(NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr)
546 {
547 (void)netDev;
548 (void)keyIndex;
549 (void)pairwise;
550 (void)macAddr;
551 return HDF_SUCCESS;
552 }
FakeWalSetDefaultKey(NetDevice * netDev,uint8_t keyIndex,bool unicast,bool multicas)553 static int32_t FakeWalSetDefaultKey(NetDevice *netDev, uint8_t keyIndex, bool unicast, bool multicas)
554 {
555 (void)netDev;
556 (void)keyIndex;
557 (void)unicast;
558 (void)multicas;
559 return HDF_SUCCESS;
560 }
FakeWalGetDeviceMacAddr(NetDevice * netDev,int32_t type,uint8_t * mac,uint8_t len)561 static int32_t FakeWalGetDeviceMacAddr(NetDevice *netDev, int32_t type, uint8_t *mac, uint8_t len)
562 {
563 (void)netDev;
564 (void)type;
565
566 for (int i = 0; i < len && i < netDev->addrLen; i++) {
567 mac[i] = netDev->macAddr[i];
568 }
569
570 return HDF_SUCCESS;
571 }
FakeWalSetMacAddr(NetDevice * netDev,uint8_t * mac,uint8_t len)572 static int32_t FakeWalSetMacAddr(NetDevice *netDev, uint8_t *mac, uint8_t len)
573 {
574 (void)netDev;
575
576 for (int i = 0; i < len && i < netDev->addrLen; i++) {
577 netDev->macAddr[i] = mac[i];
578 }
579
580 return HDF_SUCCESS;
581 }
FakeWalSetTxPower(NetDevice * netDev,int32_t power)582 static int32_t FakeWalSetTxPower(NetDevice *netDev, int32_t power)
583 {
584 (void)netDev;
585 (void)power;
586 return HDF_SUCCESS;
587 }
588 #define FAKE_MAGIC_BAND 20
589 #define FAKE_MAGIC_FREQ 2412
590 #define FAKE_MAGIC_CAPS 20
591 #define FAKE_MAGIC_RATE 100
FakeWalGetValidFreqsWithBand(NetDevice * netDev,int32_t band,int32_t * freqs,uint32_t * num)592 static int32_t FakeWalGetValidFreqsWithBand(NetDevice *netDev, int32_t band, int32_t *freqs, uint32_t *num)
593 {
594 (void)netDev;
595
596 if (band != FAKE_MAGIC_BAND) {
597 HDF_LOGE("[%s]unsupported WLAN band: %dMHz", __func__, band);
598 return HDF_ERR_NOT_SUPPORT;
599 }
600
601 *freqs = FAKE_MAGIC_FREQ; /* MHz, channel 1 */
602 *num = 1;
603 return HDF_SUCCESS;
604 }
605 struct MemAllocForWlanHwCapability {
606 struct WlanHwCapability cap;
607 struct WlanBand band;
608 struct WlanChannel ch;
609 uint16_t rate;
610 };
FakeWalHwCapabilityRelease(struct WlanHwCapability * self)611 static void FakeWalHwCapabilityRelease(struct WlanHwCapability *self)
612 {
613 OsalMemFree(self);
614 }
FakeWalGetHwCapability(NetDevice * netDev,struct WlanHwCapability ** capability)615 static int32_t FakeWalGetHwCapability(NetDevice *netDev, struct WlanHwCapability **capability)
616 {
617 (void)netDev;
618
619 struct MemAllocForWlanHwCapability *p = OsalMemCalloc(sizeof(struct MemAllocForWlanHwCapability));
620 if (p == NULL) {
621 HDF_LOGE("[%s]alloc memory failed", __func__);
622 return HDF_ERR_MALLOC_FAIL;
623 }
624 p->cap.Release = FakeWalHwCapabilityRelease;
625 p->cap.bands[0] = &p->band;
626 p->cap.htCapability = FAKE_MAGIC_CAPS;
627 p->cap.supportedRateCount = 1;
628 p->cap.supportedRates = &p->rate;
629 p->band.channelCount = 1;
630 p->ch.channelId = 1;
631 p->ch.centerFreq = FAKE_MAGIC_FREQ;
632 p->ch.flags = WLAN_CHANNEL_FLAG_NO_IR | WLAN_CHANNEL_FLAG_DFS_UNAVAILABLE;
633 p->rate = FAKE_MAGIC_RATE;
634
635 *capability = &p->cap;
636 return HDF_SUCCESS;
637 }
638 static struct HdfMac80211BaseOps g_fakeBaseOps = {
639 .SetMode = FakeWalSetMode,
640 .AddKey = FakeWalAddKey,
641 .DelKey = FakeWalDelKey,
642 .SetDefaultKey = FakeWalSetDefaultKey,
643 .GetDeviceMacAddr = FakeWalGetDeviceMacAddr,
644 .SetMacAddr = FakeWalSetMacAddr,
645 .SetTxPower = FakeWalSetTxPower,
646 .GetValidFreqsWithBand = FakeWalGetValidFreqsWithBand,
647 .GetHwCapability = FakeWalGetHwCapability
648 };
649
650
651 /*
652 * Fake STA operations.
653 */
FakeStaConnect(NetDevice * netDev,WlanConnectParams * param)654 static int32_t FakeStaConnect(NetDevice *netDev, WlanConnectParams *param)
655 {
656 (void)netDev;
657 (void)param;
658 return HDF_SUCCESS;
659 }
FakeStaDisonnect(NetDevice * netDev,uint16_t reasonCode)660 static int32_t FakeStaDisonnect(NetDevice *netDev, uint16_t reasonCode)
661 {
662 (void)netDev;
663 (void)reasonCode;
664 return HDF_SUCCESS;
665 }
FakeStaStartScan(NetDevice * netDev,struct WlanScanRequest * param)666 static int32_t FakeStaStartScan(NetDevice *netDev, struct WlanScanRequest *param)
667 {
668 (void)netDev;
669 (void)param;
670 return HDF_SUCCESS;
671 }
FakeStaAbortScan(NetDevice * netDev)672 static int32_t FakeStaAbortScan(NetDevice *netDev)
673 {
674 (void)netDev;
675 return HDF_SUCCESS;
676 }
FakeStaSetScanningMacAddress(NetDevice * netDev,unsigned char * mac,uint32_t len)677 static int32_t FakeStaSetScanningMacAddress(NetDevice *netDev, unsigned char *mac, uint32_t len)
678 {
679 (void)netDev;
680 (void)mac;
681 (void)len;
682 return HDF_SUCCESS;
683 }
684 static struct HdfMac80211STAOps g_fakeStaOps = {
685 .Connect = FakeStaConnect,
686 .Disconnect = FakeStaDisonnect,
687 .StartScan = FakeStaStartScan,
688 .AbortScan = FakeStaAbortScan,
689 .SetScanningMacAddress = FakeStaSetScanningMacAddress,
690 };
691
692
693 /*
694 * Fake factory & chip functions.
695 */
FakeFactoryInitChip(struct HdfWlanDevice * device,uint8_t ifIndex)696 static struct HdfChipDriver *FakeFactoryInitChip(struct HdfWlanDevice *device, uint8_t ifIndex)
697 {
698 struct HdfChipDriver *chipDriver = NULL;
699 if (device == NULL || ifIndex > 0) {
700 HDF_LOGE("[%s]HdfWlanDevice is NULL or ifIndex>0", __func__);
701 return NULL;
702 }
703 chipDriver = OsalMemCalloc(sizeof(struct HdfChipDriver));
704 if (chipDriver == NULL) {
705 HDF_LOGE("[%s]alloc memory failed", __func__);
706 return NULL;
707 }
708
709 if (strcpy_s(chipDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, VIRTMMIO_NETIF_NAME) != EOK) {
710 HDF_LOGE("[%s]strcpy_s failed", __func__);
711 OsalMemFree(chipDriver);
712 return NULL;
713 }
714 chipDriver->init = VirtNetDeviceInit;
715 chipDriver->deinit = VirtNetDeviceDeInit;
716 chipDriver->ops = &g_fakeBaseOps;
717 chipDriver->staOps = &g_fakeStaOps;
718
719 return chipDriver;
720 }
FakeFactoryReleaseChip(struct HdfChipDriver * chipDriver)721 static void FakeFactoryReleaseChip(struct HdfChipDriver *chipDriver)
722 {
723 if (chipDriver == NULL) {
724 return;
725 }
726 if (strcmp(chipDriver->name, VIRTMMIO_NETIF_NAME) != 0) {
727 HDF_LOGE("[%s]not my driver: %s", __func__, chipDriver->name);
728 return;
729 }
730 OsalMemFree(chipDriver);
731 }
FakeFactoryGetMaxIFCount(struct HdfChipDriverFactory * factory)732 static uint8_t FakeFactoryGetMaxIFCount(struct HdfChipDriverFactory *factory)
733 {
734 (void)factory;
735 return 1;
736 }
FakeFactoryRelease(struct HdfChipDriverFactory * factory)737 static void FakeFactoryRelease(struct HdfChipDriverFactory *factory)
738 {
739 OsalMemFree(factory);
740 }
FakeFactoryInit(void)741 static int32_t FakeFactoryInit(void)
742 {
743 struct HdfChipDriverManager *driverMgr = NULL;
744 struct HdfChipDriverFactory *tmpFactory = NULL;
745 int32_t ret;
746
747 tmpFactory = OsalMemCalloc(sizeof(struct HdfChipDriverFactory));
748 if (tmpFactory == NULL) {
749 HDF_LOGE("[%s]alloc memory failed", __func__);
750 return HDF_ERR_MALLOC_FAIL;
751 }
752
753 driverMgr = HdfWlanGetChipDriverMgr();
754 if (driverMgr == NULL || driverMgr->RegChipDriver == NULL) {
755 HDF_LOGE("[%s]driverMgr or its RegChipDriver is NULL!", __func__);
756 OsalMemFree(tmpFactory);
757 return HDF_FAILURE;
758 }
759
760 #define VIRTMMIO_WIFI_NAME "fakewifi" /* must match wlan_chip_virtnet.hcs::driverName */
761 tmpFactory->driverName = VIRTMMIO_WIFI_NAME;
762 tmpFactory->ReleaseFactory = FakeFactoryRelease;
763 tmpFactory->Build = FakeFactoryInitChip;
764 tmpFactory->Release = FakeFactoryReleaseChip;
765 tmpFactory->GetMaxIFCount = FakeFactoryGetMaxIFCount;
766 if ((ret = driverMgr->RegChipDriver(tmpFactory)) != HDF_SUCCESS) {
767 HDF_LOGE("[%s]register chip driver failed: %d", __func__, ret);
768 OsalMemFree(tmpFactory);
769 return ret;
770 }
771
772 return HDF_SUCCESS;
773 }
774
775
776 /*
777 * HDF entry.
778 */
779
FakeWifiInit(struct HdfDeviceObject * device)780 static int32_t FakeWifiInit(struct HdfDeviceObject *device)
781 {
782 struct VirtmmioDev dev;
783
784 if (device == NULL) {
785 HDF_LOGE("[%s]device is null", __func__);
786 return HDF_ERR_INVALID_PARAM;
787 }
788
789 /* only when virtio-net do exist, we go on the other lots of work */
790 if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_NET, &dev)) {
791 return HDF_ERR_INVALID_OBJECT;
792 }
793
794 return FakeFactoryInit();
795 }
796
FakeWifiRelease(struct HdfDeviceObject * deviceObject)797 static void FakeWifiRelease(struct HdfDeviceObject *deviceObject)
798 {
799 if (deviceObject) {
800 (void)ChipDriverMgrDeInit();
801 }
802 }
803
804 struct HdfDriverEntry g_fakeWifiEntry = {
805 .moduleVersion = 1,
806 .Init = FakeWifiInit,
807 .Release = FakeWifiRelease,
808 .moduleName = "HDF_FAKE_WIFI"
809 };
810
811 HDF_INIT(g_fakeWifiEntry);
812