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 "los_queue.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
86 struct VirtinEvent ev[VIRTQ_EVENT_QSZ]; /* event receive buffer */
87 };
88 static const InputDevice *g_virtInputDev; /* work thread need this data, using global for simplicity */
89
90 static UINT32 g_queue;
91
Feature0(uint32_t features,uint32_t * supported,void * dev)92 static bool Feature0(uint32_t features, uint32_t *supported, void *dev)
93 {
94 (void)features;
95 (void)supported;
96 (void)dev;
97 return true;
98 }
99
Feature1(uint32_t features,uint32_t * supported,void * dev)100 static bool Feature1(uint32_t features, uint32_t *supported, void *dev)
101 {
102 (void)dev;
103 if (features & VIRTIO_F_VERSION_1) {
104 *supported |= VIRTIO_F_VERSION_1;
105 } else {
106 HDF_LOGE("[%s]virtio-mmio input has no VERSION_1 feature", __func__);
107 return false;
108 }
109
110 return true;
111 }
112
PopulateEventQ(const struct Virtin * in)113 static void PopulateEventQ(const struct Virtin *in)
114 {
115 const struct Virtq *q = &in->dev.vq[0];
116 int i;
117
118 for (i = 0; i < VIRTQ_EVENT_QSZ; i++) {
119 q->desc[i].pAddr = u32_to_u64(VMM_TO_DMA_ADDR((VADDR_T)&in->ev[i]));
120 q->desc[i].len = sizeof(struct VirtinEvent);
121 q->desc[i].flag = VIRTQ_DESC_F_WRITE;
122
123 q->avail->ring[i] = i;
124 }
125
126 in->dev.vq[0].avail->index += in->dev.vq[0].qsz;
127 OSAL_WRITEL(0, in->dev.base + VIRTMMIO_REG_QUEUENOTIFY);
128 }
129
VirtinWorkCallback(void * arg)130 static void VirtinWorkCallback(void *arg)
131 {
132 struct VirtinEvent *ev = arg;
133 HidReportEvent(g_virtInputDev, ev->type, ev->code, ev->value);
134 }
135
136 /*
137 * When VM captures mouse, the event is incomplete. We should filter it
138 * out: a left-button-up event happened with no left-button-down preceded.
139 * We don't know when mouse released, so have to check the signature often.
140 */
VirtinGrabbed(const struct VirtinEvent * ev)141 static bool VirtinGrabbed(const struct VirtinEvent *ev)
142 {
143 static int precedeDown = VIRTIN_PRECEDE_DOWN_NO;
144
145 if (ev->type == EV_KEY && ev->code == BTN_LEFT) {
146 if (ev->value == 1) { /* left-button-down: must already captured */
147 precedeDown = VIRTIN_PRECEDE_DOWN_YES;
148 } else if (precedeDown == VIRTIN_PRECEDE_DOWN_YES) { /* left-button-up: have preceded DOWN, counteract */
149 precedeDown = VIRTIN_PRECEDE_DOWN_NO;
150 } else { /* left-button-up: no preceded DOWN, filter this and successive EV_SYN */
151 precedeDown = VIRTIN_PRECEDE_DOWN_SYN;
152 return false;
153 }
154 }
155 if (precedeDown == VIRTIN_PRECEDE_DOWN_SYN) { /* EV_SYN */
156 precedeDown = VIRTIN_PRECEDE_DOWN_NO;
157 return false;
158 }
159 return true;
160 }
161
VirtinHandleEv(struct Virtin * in)162 static void VirtinHandleEv(struct Virtin *in)
163 {
164 struct Virtq *q = &in->dev.vq[0];
165 uint16_t idx;
166 uint16_t add = 0;
167
168 q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT;
169 while (q->last != q->used->index) {
170 DSB;
171 idx = q->used->ring[q->last % q->qsz].id;
172
173 if (VirtinGrabbed(&in->ev[idx])) {
174 int ret = 0;
175 ret = LOS_QueueWriteCopy(g_queue, &in->ev[idx], sizeof(struct VirtinEvent), 0);
176 if(ret != LOS_OK) {
177 HDF_LOGE("send message failure, error: %x\n", ret);
178 }
179 }
180
181 q->avail->ring[(q->avail->index + add++) % q->qsz] = idx;
182 q->last++;
183 }
184 DSB;
185 q->avail->index += add;
186 q->avail->flag = 0;
187
188 if (q->used->flag != VIRTQ_USED_F_NO_NOTIFY) {
189 OSAL_WRITEL(0, in->dev.base + VIRTMMIO_REG_QUEUENOTIFY);
190 }
191 }
192
VirtinIRQhandle(HwiIrqParam * param)193 static uint32_t VirtinIRQhandle(HwiIrqParam *param)
194 {
195 struct Virtin *in = param->pDevId;
196
197 if (!(OSAL_READL(in->dev.base + VIRTMMIO_REG_INTERRUPTSTATUS) & VIRTMMIO_IRQ_NOTIFY_USED)) {
198
199 return 1;
200 }
201 VirtinHandleEv(in);
202
203 OSAL_WRITEL(VIRTMMIO_IRQ_NOTIFY_USED, in->dev.base + VIRTMMIO_REG_INTERRUPTACK);
204 return 0;
205 }
206
VirtinFillHidCodeBitmap(struct VirtinConfig * conf,HidInfo * devInfo)207 static bool VirtinFillHidCodeBitmap(struct VirtinConfig *conf, HidInfo *devInfo)
208 {
209 uint8_t *qDest = NULL;
210 uint32_t i, evType, len;
211
212 devInfo->eventType[0] = 0;
213 for (evType = 0; evType < HDF_EV_CNT; evType++) {
214 DSB;
215 conf->select = VIRTIO_INPUT_CFG_EV_BITS;
216 conf->subsel = evType;
217 DSB;
218 if (conf->size == 0) {
219 continue;
220 }
221 switch (evType) {
222 case EV_KEY:
223 len = DIV_ROUND_UP(HDF_KEY_CNT, BYTE_HAS_BITS);
224 qDest = (uint8_t *)devInfo->keyCode;
225 break;
226 case EV_REL:
227 len = DIV_ROUND_UP(HDF_REL_CNT, BYTE_HAS_BITS);
228 qDest = (uint8_t *)devInfo->relCode;
229 break;
230 case EV_ABS:
231 len = DIV_ROUND_UP(HDF_ABS_CNT, BYTE_HAS_BITS);
232 qDest = (uint8_t *)devInfo->absCode;
233 break;
234 default:
235 HDF_LOGE("[%s]unsupported event type: %d", __func__, evType);
236 return false;
237 }
238 devInfo->eventType[0] |= 1 << evType;
239 for (i = 0; i < len && i < VIRTIN_PROP_LEN; i++) {
240 qDest[i] = conf->u.bitmap[i];
241 }
242 }
243
244 return true;
245 }
246
VirtinFillHidDevIds(struct VirtinConfig * conf,HidInfo * devInfo)247 static void VirtinFillHidDevIds(struct VirtinConfig *conf, HidInfo *devInfo)
248 {
249 conf->select = VIRTIO_INPUT_CFG_ID_DEVIDS;
250 conf->subsel = 0;
251 DSB;
252 if (conf->size) {
253 devInfo->bustype = conf->u.ids.bus;
254 devInfo->vendor = conf->u.ids.vendor;
255 devInfo->product = conf->u.ids.product;
256 devInfo->version = conf->u.ids.version;
257 }
258 }
259
VirtinFillHidInfo(const struct Virtin * in,HidInfo * devInfo)260 static bool VirtinFillHidInfo(const struct Virtin *in, HidInfo *devInfo)
261 {
262 struct VirtinConfig *conf = (struct VirtinConfig *)(in->dev.base + VIRTMMIO_REG_CONFIG);
263 uint32_t before, after;
264
265 devInfo->devType = INDEV_TYPE_MOUSE; /* only mouse and keyboard available */
266 devInfo->devName = VIRTMMIO_INPUT_NAME;
267
268 do {
269 before = OSAL_READL(in->dev.base + VIRTMMIO_REG_CONFIGGENERATION);
270
271 VirtinFillHidDevIds(conf, devInfo);
272
273 if (!VirtinFillHidCodeBitmap(conf, devInfo)) {
274 return false;
275 }
276
277 after = OSAL_READL(in->dev.base + VIRTMMIO_REG_CONFIGGENERATION);
278 } while (before != after);
279
280 return true;
281 }
282
HdfVirtinInitHid(struct Virtin * in)283 static int32_t HdfVirtinInitHid(struct Virtin *in)
284 {
285 int32_t ret = HDF_SUCCESS;
286
287 HidInfo *devInfo = OsalMemCalloc(sizeof(HidInfo));
288 if (devInfo == NULL) {
289 HDF_LOGE("[%s]alloc HidInfo memory failed", __func__);
290 return HDF_ERR_MALLOC_FAIL;
291 }
292
293 if (!VirtinFillHidInfo(in, devInfo)) {
294 ret = HDF_ERR_NOT_SUPPORT;
295 goto ERR_OUT;
296 }
297
298 SendInfoToHdf(devInfo);
299
300 g_virtInputDev = HidRegisterHdfInputDev(devInfo);
301 if (g_virtInputDev == NULL) {
302 HDF_LOGE("[%s]register input device failed", __func__);
303 ret = HDF_FAILURE;
304 }
305
306 ERR_OUT:
307 OsalMemFree(devInfo);
308 return ret;
309 }
310
VirtinDeInit(struct Virtin * in)311 static void VirtinDeInit(struct Virtin *in)
312 {
313 if (in->dev.irq) {
314 LOS_HwiDelete(in->dev.irq, NULL);
315 }
316 LOS_MemFree(OS_SYS_MEM_ADDR, in);
317 }
318
VirtinInitDev(void)319 static struct Virtin *VirtinInitDev(void)
320 {
321 struct Virtin *in = NULL;
322 VADDR_T base;
323 uint16_t qsz[VIRTQ_NUM];
324 int32_t ret, len;
325
326 len = sizeof(struct Virtin) + VirtqSize(VIRTQ_EVENT_QSZ) + VirtqSize(VIRTQ_STATUS_QSZ);
327 in = LOS_MemAlloc(OS_SYS_MEM_ADDR, len * sizeof(void *));
328 if (in != NULL) {
329 memset_s(in, len * sizeof(void *), 0, len * sizeof(void *));
330 } else {
331 HDF_LOGE("[%s]alloc virtio-input memory failed", __func__);
332 return NULL;
333 }
334
335 if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_INPUT, &in->dev)) {
336 goto ERR_OUT;
337 }
338
339 VirtmmioInitBegin(&in->dev);
340
341 if (!VirtmmioNegotiate(&in->dev, Feature0, Feature1, in)) {
342 goto ERR_OUT1;
343 }
344
345 base = ALIGN((VADDR_T)in + sizeof(struct Virtin), VIRTQ_ALIGN_DESC);
346 qsz[0] = VIRTQ_EVENT_QSZ;
347 qsz[1] = VIRTQ_STATUS_QSZ;
348 if (VirtmmioConfigQueue(&in->dev, base, qsz, VIRTQ_NUM) == 0) {
349 goto ERR_OUT1;
350 }
351
352 if (!VirtmmioRegisterIRQ(&in->dev, (HWI_PROC_FUNC)VirtinIRQhandle, in, VIRTMMIO_INPUT_NAME)) {
353 HDF_LOGE("[%s]register IRQ failed: %d", __func__, ret);
354 goto ERR_OUT1;
355 }
356
357 return in;
358
359 ERR_OUT1:
360 VirtmmioInitFailed(&in->dev);
361 ERR_OUT:
362 VirtinDeInit(in);
363 return NULL;
364 }
365
WorkTask(void)366 static int32_t WorkTask(void) {
367 UINT32 ret = 0;
368 struct VirtinEvent ev;
369 UINT32 readLen = sizeof(ev);
370
371 while(1) {
372 ret = LOS_QueueReadCopy(g_queue, &ev, &readLen, 0);
373 if(ret == LOS_OK) {
374 HDF_LOGI("VirtinEvent Type: %d, Code: %d, Value: %d\n",
375 ev.type, ev.code, ev.value);
376 VirtinWorkCallback(&ev);
377 }
378 }
379 }
380
HdfVirtinInit(struct HdfDeviceObject * device)381 static int32_t HdfVirtinInit(struct HdfDeviceObject *device)
382 {
383 struct Virtin *in = NULL;
384 int32_t ret;
385
386 if (device == NULL) {
387 HDF_LOGE("[%s]device is null", __func__);
388 return HDF_ERR_INVALID_PARAM;
389 }
390
391 if ((in = VirtinInitDev()) == NULL) {
392 return HDF_FAILURE;
393 }
394 device->priv = in;
395
396 if ((ret = HdfVirtinInitHid(in)) != HDF_SUCCESS) {
397 return ret;
398 }
399
400 ret = LOS_QueueCreate("queue", 50, &g_queue, 0, sizeof(struct VirtinEvent));
401 if(ret != LOS_OK) {
402 HDF_LOGE("create queue failure, error: %x\n", ret);
403 }
404
405 LOS_TaskLock();
406 UINT32 g_taskLoId;
407 TSK_INIT_PARAM_S initParam = {0};
408
409 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)WorkTask;
410 initParam.usTaskPrio = 9;
411 initParam.pcName = "WorkTask";
412 initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
413
414 ret = LOS_TaskCreate(&g_taskLoId, &initParam);
415 if (ret != HDF_SUCCESS) {
416 HDF_LOGE("Create Task failed! ERROR: 0x%x\n", ret);
417 }
418 LOS_TaskUnlock();
419
420 PopulateEventQ(in);
421 VritmmioInitEnd(&in->dev); /* now virt queue can be used */
422 return HDF_SUCCESS;
423 }
424
HdfVirtinRelease(struct HdfDeviceObject * deviceObject)425 static void HdfVirtinRelease(struct HdfDeviceObject *deviceObject)
426 {
427 if (deviceObject == NULL) {
428 return;
429 }
430
431 struct Virtin *in = deviceObject->priv;
432 if (in == NULL) {
433 return;
434 }
435
436 LOS_QueueDelete(g_queue);
437
438 if (g_virtInputDev) {
439 HidUnregisterHdfInputDev(g_virtInputDev);
440 }
441 VirtinDeInit(in);
442 }
443
444 struct HdfDriverEntry g_virtInputEntry = {
445 .moduleVersion = 1,
446 .moduleName = "HDF_VIRTIO_MOUSE",
447 .Init = HdfVirtinInit,
448 .Release = HdfVirtinRelease,
449 };
450
451 HDF_INIT(g_virtInputEntry);
452
GetHdfDeviceObject(void)453 struct HdfDeviceObject *GetHdfDeviceObject(void)
454 {
455 if(g_virtInputDev != NULL){
456 return g_virtInputDev->hdfDevObj;
457 }
458 return HDF_FAILURE;
459 }
460