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) 37struct 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 */ 49struct 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 77struct 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 90static inline struct VirtNetif *GetVirtnetIf(const NetDevice *netDev) 91{ 92 return (struct VirtNetif *)GET_NET_DEV_PRIV(netDev); 93} 94 95static 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 126static 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 139static 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 153static 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 174static 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 191static 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 208static uint16_t GetTxFreeEntry(struct VirtNetif *nic) 209{ 210 uint32_t intSave; 211 uint16_t head, idx; 212 bool logged = false; 213 214RETRY: 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 237static 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 262static 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 282static 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 325static 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 341static 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 366static 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 407ERR_OUT: 408 VirtmmioInitFailed(&nic->dev); 409 return ret; 410} 411 412static 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 425static 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 434static 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 */ 449static 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 474static 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 502ERR_OUT: 503 VirtnetDeInit(netDev); 504 return ret; 505} 506 507static 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 */ 526static 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} 535static 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} 545static 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} 553static 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} 561static 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} 572static 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} 582static 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 592static 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} 605struct MemAllocForWlanHwCapability { 606 struct WlanHwCapability cap; 607 struct WlanBand band; 608 struct WlanChannel ch; 609 uint16_t rate; 610}; 611static void FakeWalHwCapabilityRelease(struct WlanHwCapability *self) 612{ 613 OsalMemFree(self); 614} 615static 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} 638static 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 */ 654static int32_t FakeStaConnect(NetDevice *netDev, WlanConnectParams *param) 655{ 656 (void)netDev; 657 (void)param; 658 return HDF_SUCCESS; 659} 660static int32_t FakeStaDisonnect(NetDevice *netDev, uint16_t reasonCode) 661{ 662 (void)netDev; 663 (void)reasonCode; 664 return HDF_SUCCESS; 665} 666static int32_t FakeStaStartScan(NetDevice *netDev, struct WlanScanRequest *param) 667{ 668 (void)netDev; 669 (void)param; 670 return HDF_SUCCESS; 671} 672static int32_t FakeStaAbortScan(NetDevice *netDev) 673{ 674 (void)netDev; 675 return HDF_SUCCESS; 676} 677static 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} 684static 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 */ 696static 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} 721static 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} 732static uint8_t FakeFactoryGetMaxIFCount(struct HdfChipDriverFactory *factory) 733{ 734 (void)factory; 735 return 1; 736} 737static void FakeFactoryRelease(struct HdfChipDriverFactory *factory) 738{ 739 OsalMemFree(factory); 740} 741static 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 780static 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 797static void FakeWifiRelease(struct HdfDeviceObject *deviceObject) 798{ 799 if (deviceObject) { 800 (void)ChipDriverMgrDeInit(); 801 } 802} 803 804struct HdfDriverEntry g_fakeWifiEntry = { 805 .moduleVersion = 1, 806 .Init = FakeWifiInit, 807 .Release = FakeWifiRelease, 808 .moduleName = "HDF_FAKE_WIFI" 809}; 810 811HDF_INIT(g_fakeWifiEntry); 812