1d6aed566Sopenharmony_ci/* 2d6aed566Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3d6aed566Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d6aed566Sopenharmony_ci * you may not use this file except in compliance with the License. 5d6aed566Sopenharmony_ci * You may obtain a copy of the License at 6d6aed566Sopenharmony_ci * 7d6aed566Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d6aed566Sopenharmony_ci * 9d6aed566Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d6aed566Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d6aed566Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d6aed566Sopenharmony_ci * See the License for the specific language governing permissions and 13d6aed566Sopenharmony_ci * limitations under the License. 14d6aed566Sopenharmony_ci */ 15d6aed566Sopenharmony_ci 16d6aed566Sopenharmony_ci#include "osal.h" 17d6aed566Sopenharmony_ci#include "osal_io.h" 18d6aed566Sopenharmony_ci#include "hdf_device_desc.h" 19d6aed566Sopenharmony_ci#include "hdf_input_device_manager.h" 20d6aed566Sopenharmony_ci#include "hdf_hid_adapter.h" 21d6aed566Sopenharmony_ci#include "hdf_syscall_adapter.h" 22d6aed566Sopenharmony_ci#include "los_memory.h" 23d6aed566Sopenharmony_ci#include "los_arch_interrupt.h" 24d6aed566Sopenharmony_ci#include "los_interrupt.h" 25d6aed566Sopenharmony_ci#include "los_task.h" 26d6aed566Sopenharmony_ci#include "cmsis_os2.h" 27d6aed566Sopenharmony_ci#include "virtmmio.h" 28d6aed566Sopenharmony_ci 29d6aed566Sopenharmony_ci#define VIRTQ_EVENT_QSZ 8 30d6aed566Sopenharmony_ci#define VIRTQ_STATUS_QSZ 1 31d6aed566Sopenharmony_ci#define VIRTMMIO_INPUT_NAME "virtinput" 32d6aed566Sopenharmony_ci 33d6aed566Sopenharmony_ci#define VIRTIN_PRECEDE_DOWN_YES 0 34d6aed566Sopenharmony_ci#define VIRTIN_PRECEDE_DOWN_NO 1 35d6aed566Sopenharmony_ci#define VIRTIN_PRECEDE_DOWN_SYN 2 36d6aed566Sopenharmony_ci 37d6aed566Sopenharmony_cienum { 38d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_UNSET = 0x00, 39d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_ID_NAME = 0x01, 40d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_ID_SERIAL = 0x02, 41d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_ID_DEVIDS = 0x03, 42d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_PROP_BITS = 0x10, 43d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_EV_BITS = 0x11, 44d6aed566Sopenharmony_ci VIRTIO_INPUT_CFG_ABS_INFO = 0x12, 45d6aed566Sopenharmony_ci}; 46d6aed566Sopenharmony_ci 47d6aed566Sopenharmony_cistruct VirtinAbsinfo { 48d6aed566Sopenharmony_ci uint32_t min; 49d6aed566Sopenharmony_ci uint32_t max; 50d6aed566Sopenharmony_ci uint32_t fuzz; 51d6aed566Sopenharmony_ci uint32_t flat; 52d6aed566Sopenharmony_ci uint32_t res; 53d6aed566Sopenharmony_ci}; 54d6aed566Sopenharmony_ci 55d6aed566Sopenharmony_cistruct VirtinDevids { 56d6aed566Sopenharmony_ci uint16_t bus; 57d6aed566Sopenharmony_ci uint16_t vendor; 58d6aed566Sopenharmony_ci uint16_t product; 59d6aed566Sopenharmony_ci uint16_t version; 60d6aed566Sopenharmony_ci}; 61d6aed566Sopenharmony_ci 62d6aed566Sopenharmony_cistruct VirtinConfig { 63d6aed566Sopenharmony_ci uint8_t select; 64d6aed566Sopenharmony_ci uint8_t subsel; 65d6aed566Sopenharmony_ci uint8_t size; 66d6aed566Sopenharmony_ci#define VIRTIN_PADDINGS 5 67d6aed566Sopenharmony_ci uint8_t reserved[VIRTIN_PADDINGS]; 68d6aed566Sopenharmony_ci union { 69d6aed566Sopenharmony_ci#define VIRTIN_PROP_LEN 128 70d6aed566Sopenharmony_ci char string[VIRTIN_PROP_LEN]; 71d6aed566Sopenharmony_ci uint8_t bitmap[VIRTIN_PROP_LEN]; 72d6aed566Sopenharmony_ci struct VirtinAbsinfo abs; 73d6aed566Sopenharmony_ci struct VirtinDevids ids; 74d6aed566Sopenharmony_ci } u; 75d6aed566Sopenharmony_ci}; 76d6aed566Sopenharmony_ci 77d6aed566Sopenharmony_cistruct VirtinEvent { 78d6aed566Sopenharmony_ci uint16_t type; 79d6aed566Sopenharmony_ci uint16_t code; 80d6aed566Sopenharmony_ci uint32_t value; 81d6aed566Sopenharmony_ci}; 82d6aed566Sopenharmony_ci 83d6aed566Sopenharmony_cistruct Virtin { 84d6aed566Sopenharmony_ci struct VirtmmioDev dev; 85d6aed566Sopenharmony_ci osThreadId_t tid; 86d6aed566Sopenharmony_ci osSemaphoreId_t sem; 87d6aed566Sopenharmony_ci struct VirtinEvent ev[VIRTQ_EVENT_QSZ]; /* event receive buffer */ 88d6aed566Sopenharmony_ci}; 89d6aed566Sopenharmony_cistatic const InputDevice *g_virtInputDev; /* work thread need this data, using global for simplicity */ 90d6aed566Sopenharmony_ci 91d6aed566Sopenharmony_cistatic bool Feature0(uint32_t features, uint32_t *supported, void *dev) 92d6aed566Sopenharmony_ci{ 93d6aed566Sopenharmony_ci (void)features; 94d6aed566Sopenharmony_ci (void)supported; 95d6aed566Sopenharmony_ci (void)dev; 96d6aed566Sopenharmony_ci return true; 97d6aed566Sopenharmony_ci} 98d6aed566Sopenharmony_ci 99d6aed566Sopenharmony_cistatic bool Feature1(uint32_t features, uint32_t *supported, void *dev) 100d6aed566Sopenharmony_ci{ 101d6aed566Sopenharmony_ci (void)dev; 102d6aed566Sopenharmony_ci if (features & VIRTIO_F_VERSION_1) { 103d6aed566Sopenharmony_ci *supported |= VIRTIO_F_VERSION_1; 104d6aed566Sopenharmony_ci } else { 105d6aed566Sopenharmony_ci HDF_LOGE("[%s]virtio-mmio input has no VERSION_1 feature", __func__); 106d6aed566Sopenharmony_ci return false; 107d6aed566Sopenharmony_ci } 108d6aed566Sopenharmony_ci 109d6aed566Sopenharmony_ci return true; 110d6aed566Sopenharmony_ci} 111d6aed566Sopenharmony_ci 112d6aed566Sopenharmony_cistatic void PopulateEventQ(const struct Virtin *in) 113d6aed566Sopenharmony_ci{ 114d6aed566Sopenharmony_ci const struct Virtq *q = &in->dev.vq[0]; 115d6aed566Sopenharmony_ci int i; 116d6aed566Sopenharmony_ci 117d6aed566Sopenharmony_ci for (i = 0; i < VIRTQ_EVENT_QSZ; i++) { 118d6aed566Sopenharmony_ci q->desc[i].pAddr = u32_to_u64(VMM_TO_DMA_ADDR((VADDR_T)&in->ev[i])); 119d6aed566Sopenharmony_ci q->desc[i].len = sizeof(struct VirtinEvent); 120d6aed566Sopenharmony_ci q->desc[i].flag = VIRTQ_DESC_F_WRITE; 121d6aed566Sopenharmony_ci 122d6aed566Sopenharmony_ci q->avail->ring[i] = i; 123d6aed566Sopenharmony_ci } 124d6aed566Sopenharmony_ci 125d6aed566Sopenharmony_ci in->dev.vq[0].avail->index += in->dev.vq[0].qsz; 126d6aed566Sopenharmony_ci OSAL_WRITEL(0, in->dev.base + VIRTMMIO_REG_QUEUENOTIFY); 127d6aed566Sopenharmony_ci} 128d6aed566Sopenharmony_ci 129d6aed566Sopenharmony_ci/* 130d6aed566Sopenharmony_ci * When VM captures mouse, the event is incomplete. We should filter it 131d6aed566Sopenharmony_ci * out: a left-button-up event happened with no left-button-down preceded. 132d6aed566Sopenharmony_ci * We don't know when mouse released, so have to check the signature often. 133d6aed566Sopenharmony_ci */ 134d6aed566Sopenharmony_cistatic bool VirtinGrabbed(const struct VirtinEvent *ev) 135d6aed566Sopenharmony_ci{ 136d6aed566Sopenharmony_ci static int precedeDown = VIRTIN_PRECEDE_DOWN_NO; 137d6aed566Sopenharmony_ci 138d6aed566Sopenharmony_ci if (ev->type == EV_KEY && ev->code == BTN_LEFT) { 139d6aed566Sopenharmony_ci if (ev->value == 1) { /* left-button-down: must already captured */ 140d6aed566Sopenharmony_ci precedeDown = VIRTIN_PRECEDE_DOWN_YES; 141d6aed566Sopenharmony_ci } else if (precedeDown == VIRTIN_PRECEDE_DOWN_YES) { /* left-button-up: have preceded DOWN, counteract */ 142d6aed566Sopenharmony_ci precedeDown = VIRTIN_PRECEDE_DOWN_NO; 143d6aed566Sopenharmony_ci } else { /* left-button-up: no preceded DOWN, filter this and successive EV_SYN */ 144d6aed566Sopenharmony_ci precedeDown = VIRTIN_PRECEDE_DOWN_SYN; 145d6aed566Sopenharmony_ci return false; 146d6aed566Sopenharmony_ci } 147d6aed566Sopenharmony_ci } 148d6aed566Sopenharmony_ci if (precedeDown == VIRTIN_PRECEDE_DOWN_SYN) { /* EV_SYN */ 149d6aed566Sopenharmony_ci precedeDown = VIRTIN_PRECEDE_DOWN_NO; 150d6aed566Sopenharmony_ci return false; 151d6aed566Sopenharmony_ci } 152d6aed566Sopenharmony_ci return true; 153d6aed566Sopenharmony_ci} 154d6aed566Sopenharmony_ci 155d6aed566Sopenharmony_cistatic void VirtinHandleEv(struct Virtin *in) 156d6aed566Sopenharmony_ci{ 157d6aed566Sopenharmony_ci struct Virtq *q = &in->dev.vq[0]; 158d6aed566Sopenharmony_ci uint16_t idx; 159d6aed566Sopenharmony_ci uint16_t add = 0; 160d6aed566Sopenharmony_ci 161d6aed566Sopenharmony_ci q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT; 162d6aed566Sopenharmony_ci while (q->last != q->used->index) { 163d6aed566Sopenharmony_ci DSB; 164d6aed566Sopenharmony_ci idx = q->used->ring[q->last % q->qsz].id; 165d6aed566Sopenharmony_ci 166d6aed566Sopenharmony_ci if (VirtinGrabbed(&in->ev[idx])) { 167d6aed566Sopenharmony_ci struct VirtinEvent *ev = &in->ev[idx]; 168d6aed566Sopenharmony_ci HidReportEvent(g_virtInputDev, ev->type, ev->code, ev->value); 169d6aed566Sopenharmony_ci } 170d6aed566Sopenharmony_ci 171d6aed566Sopenharmony_ci q->avail->ring[(q->avail->index + add++) % q->qsz] = idx; 172d6aed566Sopenharmony_ci q->last++; 173d6aed566Sopenharmony_ci } 174d6aed566Sopenharmony_ci DSB; 175d6aed566Sopenharmony_ci q->avail->index += add; 176d6aed566Sopenharmony_ci q->avail->flag = 0; 177d6aed566Sopenharmony_ci 178d6aed566Sopenharmony_ci if (q->used->flag != VIRTQ_USED_F_NO_NOTIFY) { 179d6aed566Sopenharmony_ci OSAL_WRITEL(0, in->dev.base + VIRTMMIO_REG_QUEUENOTIFY); 180d6aed566Sopenharmony_ci } 181d6aed566Sopenharmony_ci OSAL_WRITEL(VIRTMMIO_IRQ_NOTIFY_USED, in->dev.base + VIRTMMIO_REG_INTERRUPTACK); 182d6aed566Sopenharmony_ci} 183d6aed566Sopenharmony_ci 184d6aed566Sopenharmony_cistatic uint32_t VirtinIRQhandle(void *param) 185d6aed566Sopenharmony_ci{ 186d6aed566Sopenharmony_ci struct Virtin *in = (struct Virtin *)param; 187d6aed566Sopenharmony_ci 188d6aed566Sopenharmony_ci if (!(OSAL_READL(in->dev.base + VIRTMMIO_REG_INTERRUPTSTATUS) & VIRTMMIO_IRQ_NOTIFY_USED)) { 189d6aed566Sopenharmony_ci return HDF_FAILURE; 190d6aed566Sopenharmony_ci } 191d6aed566Sopenharmony_ci osSemaphoreRelease(in->sem); 192d6aed566Sopenharmony_ci return HDF_SUCCESS; 193d6aed566Sopenharmony_ci} 194d6aed566Sopenharmony_ci 195d6aed566Sopenharmony_cistatic bool VirtinFillHidCodeBitmap(struct VirtinConfig *conf, HidInfo *devInfo) 196d6aed566Sopenharmony_ci{ 197d6aed566Sopenharmony_ci uint8_t *qDest = NULL; 198d6aed566Sopenharmony_ci uint32_t i, evType, len; 199d6aed566Sopenharmony_ci 200d6aed566Sopenharmony_ci devInfo->eventType[0] = 0; 201d6aed566Sopenharmony_ci for (evType = 0; evType < HDF_EV_CNT; evType++) { 202d6aed566Sopenharmony_ci DSB; 203d6aed566Sopenharmony_ci conf->select = VIRTIO_INPUT_CFG_EV_BITS; 204d6aed566Sopenharmony_ci conf->subsel = evType; 205d6aed566Sopenharmony_ci DSB; 206d6aed566Sopenharmony_ci if (conf->size == 0) { 207d6aed566Sopenharmony_ci continue; 208d6aed566Sopenharmony_ci } 209d6aed566Sopenharmony_ci switch (evType) { 210d6aed566Sopenharmony_ci case EV_KEY: 211d6aed566Sopenharmony_ci len = DIV_ROUND_UP(HDF_KEY_CNT, BYTE_HAS_BITS); 212d6aed566Sopenharmony_ci qDest = (uint8_t *)devInfo->keyCode; 213d6aed566Sopenharmony_ci break; 214d6aed566Sopenharmony_ci case EV_REL: 215d6aed566Sopenharmony_ci len = DIV_ROUND_UP(HDF_REL_CNT, BYTE_HAS_BITS); 216d6aed566Sopenharmony_ci qDest = (uint8_t *)devInfo->relCode; 217d6aed566Sopenharmony_ci break; 218d6aed566Sopenharmony_ci case EV_ABS: 219d6aed566Sopenharmony_ci len = DIV_ROUND_UP(HDF_ABS_CNT, BYTE_HAS_BITS); 220d6aed566Sopenharmony_ci qDest = (uint8_t *)devInfo->absCode; 221d6aed566Sopenharmony_ci break; 222d6aed566Sopenharmony_ci default: 223d6aed566Sopenharmony_ci HDF_LOGE("[%s]unsupported event type: %d", __func__, evType); 224d6aed566Sopenharmony_ci return false; 225d6aed566Sopenharmony_ci } 226d6aed566Sopenharmony_ci devInfo->eventType[0] |= 1 << evType; 227d6aed566Sopenharmony_ci for (i = 0; i < len && i < VIRTIN_PROP_LEN; i++) { 228d6aed566Sopenharmony_ci qDest[i] = conf->u.bitmap[i]; 229d6aed566Sopenharmony_ci } 230d6aed566Sopenharmony_ci } 231d6aed566Sopenharmony_ci 232d6aed566Sopenharmony_ci return true; 233d6aed566Sopenharmony_ci} 234d6aed566Sopenharmony_ci 235d6aed566Sopenharmony_cistatic void VirtinFillHidDevIds(struct VirtinConfig *conf, HidInfo *devInfo) 236d6aed566Sopenharmony_ci{ 237d6aed566Sopenharmony_ci conf->select = VIRTIO_INPUT_CFG_ID_DEVIDS; 238d6aed566Sopenharmony_ci conf->subsel = 0; 239d6aed566Sopenharmony_ci DSB; 240d6aed566Sopenharmony_ci if (conf->size) { 241d6aed566Sopenharmony_ci devInfo->bustype = conf->u.ids.bus; 242d6aed566Sopenharmony_ci devInfo->vendor = conf->u.ids.vendor; 243d6aed566Sopenharmony_ci devInfo->product = conf->u.ids.product; 244d6aed566Sopenharmony_ci devInfo->version = conf->u.ids.version; 245d6aed566Sopenharmony_ci } 246d6aed566Sopenharmony_ci} 247d6aed566Sopenharmony_ci 248d6aed566Sopenharmony_cistatic bool VirtinFillHidInfo(const struct Virtin *in, HidInfo *devInfo) 249d6aed566Sopenharmony_ci{ 250d6aed566Sopenharmony_ci struct VirtinConfig *conf = (struct VirtinConfig *)(in->dev.base + VIRTMMIO_REG_CONFIG); 251d6aed566Sopenharmony_ci uint32_t before, after; 252d6aed566Sopenharmony_ci 253d6aed566Sopenharmony_ci devInfo->devType = INDEV_TYPE_MOUSE; /* only mouse and keyboard available */ 254d6aed566Sopenharmony_ci devInfo->devName = VIRTMMIO_INPUT_NAME; 255d6aed566Sopenharmony_ci 256d6aed566Sopenharmony_ci do { 257d6aed566Sopenharmony_ci before = OSAL_READL(in->dev.base + VIRTMMIO_REG_CONFIGGENERATION); 258d6aed566Sopenharmony_ci 259d6aed566Sopenharmony_ci VirtinFillHidDevIds(conf, devInfo); 260d6aed566Sopenharmony_ci 261d6aed566Sopenharmony_ci if (!VirtinFillHidCodeBitmap(conf, devInfo)) { 262d6aed566Sopenharmony_ci return false; 263d6aed566Sopenharmony_ci } 264d6aed566Sopenharmony_ci 265d6aed566Sopenharmony_ci after = OSAL_READL(in->dev.base + VIRTMMIO_REG_CONFIGGENERATION); 266d6aed566Sopenharmony_ci } while (before != after); 267d6aed566Sopenharmony_ci 268d6aed566Sopenharmony_ci return true; 269d6aed566Sopenharmony_ci} 270d6aed566Sopenharmony_ci 271d6aed566Sopenharmony_cistatic int32_t HdfVirtinInitHid(struct Virtin *in) 272d6aed566Sopenharmony_ci{ 273d6aed566Sopenharmony_ci int32_t ret = HDF_SUCCESS; 274d6aed566Sopenharmony_ci 275d6aed566Sopenharmony_ci HidInfo *devInfo = OsalMemCalloc(sizeof(HidInfo)); 276d6aed566Sopenharmony_ci if (devInfo == NULL) { 277d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc HidInfo memory failed", __func__); 278d6aed566Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 279d6aed566Sopenharmony_ci } 280d6aed566Sopenharmony_ci 281d6aed566Sopenharmony_ci if (!VirtinFillHidInfo(in, devInfo)) { 282d6aed566Sopenharmony_ci ret = HDF_ERR_NOT_SUPPORT; 283d6aed566Sopenharmony_ci goto ERR_OUT; 284d6aed566Sopenharmony_ci } 285d6aed566Sopenharmony_ci 286d6aed566Sopenharmony_ci SendInfoToHdf(devInfo); 287d6aed566Sopenharmony_ci 288d6aed566Sopenharmony_ci g_virtInputDev = HidRegisterHdfInputDev(devInfo); 289d6aed566Sopenharmony_ci if (g_virtInputDev == NULL) { 290d6aed566Sopenharmony_ci HDF_LOGE("[%s]register input device failed", __func__); 291d6aed566Sopenharmony_ci ret = HDF_FAILURE; 292d6aed566Sopenharmony_ci } 293d6aed566Sopenharmony_ci 294d6aed566Sopenharmony_ciERR_OUT: 295d6aed566Sopenharmony_ci OsalMemFree(devInfo); 296d6aed566Sopenharmony_ci return ret; 297d6aed566Sopenharmony_ci} 298d6aed566Sopenharmony_ci 299d6aed566Sopenharmony_cistatic void VirtinDeInit(struct Virtin *in) 300d6aed566Sopenharmony_ci{ 301d6aed566Sopenharmony_ci if (in->sem) { 302d6aed566Sopenharmony_ci osSemaphoreDelete(in->sem); 303d6aed566Sopenharmony_ci in->sem = NULL; 304d6aed566Sopenharmony_ci } 305d6aed566Sopenharmony_ci 306d6aed566Sopenharmony_ci if (in->tid) { 307d6aed566Sopenharmony_ci osThreadTerminate(in->tid); 308d6aed566Sopenharmony_ci in->tid = NULL; 309d6aed566Sopenharmony_ci } 310d6aed566Sopenharmony_ci 311d6aed566Sopenharmony_ci if (in->dev.irq) { 312d6aed566Sopenharmony_ci LOS_HwiDelete(in->dev.irq, NULL); 313d6aed566Sopenharmony_ci } 314d6aed566Sopenharmony_ci 315d6aed566Sopenharmony_ci LOS_MemFree(OS_SYS_MEM_ADDR, in); 316d6aed566Sopenharmony_ci} 317d6aed566Sopenharmony_ci 318d6aed566Sopenharmony_cistatic struct Virtin *VirtinInitDev(void) 319d6aed566Sopenharmony_ci{ 320d6aed566Sopenharmony_ci struct Virtin *in = NULL; 321d6aed566Sopenharmony_ci VADDR_T base; 322d6aed566Sopenharmony_ci uint16_t qsz[VIRTQ_NUM]; 323d6aed566Sopenharmony_ci int32_t ret, len; 324d6aed566Sopenharmony_ci 325d6aed566Sopenharmony_ci len = sizeof(struct Virtin) + VirtqSize(VIRTQ_EVENT_QSZ) + VirtqSize(VIRTQ_STATUS_QSZ); 326d6aed566Sopenharmony_ci in = LOS_MemAlloc(OS_SYS_MEM_ADDR, len * sizeof(void *)); 327d6aed566Sopenharmony_ci if (in != NULL) { 328d6aed566Sopenharmony_ci (void)memset_s(in, len * sizeof(void *), 0, len * sizeof(void *)); 329d6aed566Sopenharmony_ci } else { 330d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc virtio-input memory failed", __func__); 331d6aed566Sopenharmony_ci return NULL; 332d6aed566Sopenharmony_ci } 333d6aed566Sopenharmony_ci 334d6aed566Sopenharmony_ci if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_INPUT, &in->dev)) { 335d6aed566Sopenharmony_ci goto ERR_OUT; 336d6aed566Sopenharmony_ci } 337d6aed566Sopenharmony_ci 338d6aed566Sopenharmony_ci VirtmmioInitBegin(&in->dev); 339d6aed566Sopenharmony_ci 340d6aed566Sopenharmony_ci if (!VirtmmioNegotiate(&in->dev, Feature0, Feature1, in)) { 341d6aed566Sopenharmony_ci goto ERR_OUT1; 342d6aed566Sopenharmony_ci } 343d6aed566Sopenharmony_ci 344d6aed566Sopenharmony_ci base = ALIGN((VADDR_T)in + sizeof(struct Virtin), VIRTQ_ALIGN_DESC); 345d6aed566Sopenharmony_ci qsz[0] = VIRTQ_EVENT_QSZ; 346d6aed566Sopenharmony_ci qsz[1] = VIRTQ_STATUS_QSZ; 347d6aed566Sopenharmony_ci if (VirtmmioConfigQueue(&in->dev, base, qsz, VIRTQ_NUM) == 0) { 348d6aed566Sopenharmony_ci goto ERR_OUT1; 349d6aed566Sopenharmony_ci } 350d6aed566Sopenharmony_ci 351d6aed566Sopenharmony_ci if (!VirtmmioRegisterIRQ(&in->dev, (HWI_PROC_FUNC)VirtinIRQhandle, in, VIRTMMIO_INPUT_NAME)) { 352d6aed566Sopenharmony_ci HDF_LOGE("[%s]register IRQ failed: %d", __func__, ret); 353d6aed566Sopenharmony_ci goto ERR_OUT1; 354d6aed566Sopenharmony_ci } 355d6aed566Sopenharmony_ci 356d6aed566Sopenharmony_ci return in; 357d6aed566Sopenharmony_ci 358d6aed566Sopenharmony_ciERR_OUT1: 359d6aed566Sopenharmony_ci VirtmmioInitFailed(&in->dev); 360d6aed566Sopenharmony_ciERR_OUT: 361d6aed566Sopenharmony_ci VirtinDeInit(in); 362d6aed566Sopenharmony_ci return NULL; 363d6aed566Sopenharmony_ci} 364d6aed566Sopenharmony_ci 365d6aed566Sopenharmony_cistatic int32_t InputWorkTask(void *arg) 366d6aed566Sopenharmony_ci{ 367d6aed566Sopenharmony_ci struct Virtin *in = (struct Virtin *)arg; 368d6aed566Sopenharmony_ci 369d6aed566Sopenharmony_ci while (1) { 370d6aed566Sopenharmony_ci int32_t r = osSemaphoreAcquire(in->sem, osWaitForever); 371d6aed566Sopenharmony_ci if (r != 0) { 372d6aed566Sopenharmony_ci continue; 373d6aed566Sopenharmony_ci } 374d6aed566Sopenharmony_ci VirtinHandleEv(in); 375d6aed566Sopenharmony_ci } 376d6aed566Sopenharmony_ci return HDF_FAILURE; 377d6aed566Sopenharmony_ci} 378d6aed566Sopenharmony_ci 379d6aed566Sopenharmony_cistatic int32_t HdfVirtinInit(struct HdfDeviceObject *device) 380d6aed566Sopenharmony_ci{ 381d6aed566Sopenharmony_ci struct Virtin *in = NULL; 382d6aed566Sopenharmony_ci int32_t ret; 383d6aed566Sopenharmony_ci 384d6aed566Sopenharmony_ci if (device == NULL) { 385d6aed566Sopenharmony_ci HDF_LOGE("[%s]device is null", __func__); 386d6aed566Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 387d6aed566Sopenharmony_ci } 388d6aed566Sopenharmony_ci 389d6aed566Sopenharmony_ci if ((in = VirtinInitDev()) == NULL) { 390d6aed566Sopenharmony_ci return HDF_FAILURE; 391d6aed566Sopenharmony_ci } 392d6aed566Sopenharmony_ci device->priv = in; 393d6aed566Sopenharmony_ci 394d6aed566Sopenharmony_ci if ((ret = HdfVirtinInitHid(in)) != HDF_SUCCESS) { 395d6aed566Sopenharmony_ci VirtinDeInit(in); 396d6aed566Sopenharmony_ci return ret; 397d6aed566Sopenharmony_ci } 398d6aed566Sopenharmony_ci 399d6aed566Sopenharmony_ci in->sem = osSemaphoreNew(1, 0, NULL); 400d6aed566Sopenharmony_ci if (in->sem == NULL) { 401d6aed566Sopenharmony_ci HDF_LOGE("%s: osSemaphoreNew failed", __func__); 402d6aed566Sopenharmony_ci VirtinDeInit(in); 403d6aed566Sopenharmony_ci return HDF_FAILURE; 404d6aed566Sopenharmony_ci } 405d6aed566Sopenharmony_ci 406d6aed566Sopenharmony_ci osThreadAttr_t attr = {0}; 407d6aed566Sopenharmony_ci attr.stack_size = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 408d6aed566Sopenharmony_ci attr.priority = osPriorityNormal; 409d6aed566Sopenharmony_ci attr.name = "InputWorkTask"; 410d6aed566Sopenharmony_ci in->tid = osThreadNew((osThreadFunc_t)InputWorkTask, in, &attr); 411d6aed566Sopenharmony_ci if (in->tid == NULL) { 412d6aed566Sopenharmony_ci HDF_LOGE("%s: osThreadNew failed", __func__); 413d6aed566Sopenharmony_ci VirtinDeInit(in); 414d6aed566Sopenharmony_ci return HDF_FAILURE; 415d6aed566Sopenharmony_ci } 416d6aed566Sopenharmony_ci 417d6aed566Sopenharmony_ci PopulateEventQ(in); 418d6aed566Sopenharmony_ci VritmmioInitEnd(&in->dev); /* now virt queue can be used */ 419d6aed566Sopenharmony_ci return HDF_SUCCESS; 420d6aed566Sopenharmony_ci} 421d6aed566Sopenharmony_ci 422d6aed566Sopenharmony_cistatic void HdfVirtinRelease(struct HdfDeviceObject *deviceObject) 423d6aed566Sopenharmony_ci{ 424d6aed566Sopenharmony_ci if (deviceObject == NULL) { 425d6aed566Sopenharmony_ci return; 426d6aed566Sopenharmony_ci } 427d6aed566Sopenharmony_ci 428d6aed566Sopenharmony_ci struct Virtin *in = deviceObject->priv; 429d6aed566Sopenharmony_ci if (in == NULL) { 430d6aed566Sopenharmony_ci return; 431d6aed566Sopenharmony_ci } 432d6aed566Sopenharmony_ci 433d6aed566Sopenharmony_ci if (g_virtInputDev) { 434d6aed566Sopenharmony_ci HidUnregisterHdfInputDev(g_virtInputDev); 435d6aed566Sopenharmony_ci } 436d6aed566Sopenharmony_ci VirtinDeInit(in); 437d6aed566Sopenharmony_ci} 438d6aed566Sopenharmony_ci 439d6aed566Sopenharmony_cistruct HdfDriverEntry g_virtInputEntry = { 440d6aed566Sopenharmony_ci .moduleVersion = 1, 441d6aed566Sopenharmony_ci .moduleName = "HDF_VIRTIO_MOUSE", 442d6aed566Sopenharmony_ci .Init = HdfVirtinInit, 443d6aed566Sopenharmony_ci .Release = HdfVirtinRelease, 444d6aed566Sopenharmony_ci}; 445d6aed566Sopenharmony_ci 446d6aed566Sopenharmony_ciHDF_INIT(g_virtInputEntry); 447d6aed566Sopenharmony_ci 448d6aed566Sopenharmony_cistruct HdfDeviceObject *GetHdfDeviceObject(void) 449d6aed566Sopenharmony_ci{ 450d6aed566Sopenharmony_ci if(g_virtInputDev != NULL){ 451d6aed566Sopenharmony_ci return g_virtInputDev->hdfDevObj; 452d6aed566Sopenharmony_ci } 453d6aed566Sopenharmony_ci return NULL; 454d6aed566Sopenharmony_ci} 455