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