1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-11-11     GuEe-GUI     the first version
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <cpuport.h>
14 
15 #ifdef RT_USING_VIRTIO_INPUT
16 
17 #include <virtio_input.h>
18 
_set_bit(rt_uint32_t nr,volatile rt_ubase_t * addr)19 static void _set_bit(rt_uint32_t nr, volatile rt_ubase_t *addr)
20 {
21     rt_ubase_t mask = BIT_MASK(nr);
22     rt_ubase_t *p = ((rt_ubase_t *)addr) + BIT_WORD(nr);
23 
24     *p  |= mask;
25 }
26 
virtio_input_cfg_select(struct virtio_input_device * virtio_input_dev,rt_uint8_t select,rt_uint8_t subsel)27 static rt_ssize_t virtio_input_cfg_select(struct virtio_input_device *virtio_input_dev,
28         rt_uint8_t select, rt_uint8_t subsel)
29 {
30     struct virtio_input_config *config = virtio_input_dev->config;
31 
32     rt_hw_dsb();
33     config->select = select;
34     config->subsel = subsel;
35     rt_hw_dsb();
36 
37     return config->size;
38 }
39 
virtio_input_cfg_bits(struct virtio_input_device * virtio_input_dev,rt_uint8_t select,rt_uint8_t subsel,rt_ubase_t * bits,rt_uint32_t bitcount)40 static void virtio_input_cfg_bits(struct virtio_input_device *virtio_input_dev,
41         rt_uint8_t select, rt_uint8_t subsel, rt_ubase_t *bits, rt_uint32_t bitcount)
42 {
43     int i;
44     rt_uint32_t bit;
45     rt_uint8_t bytes;
46     rt_uint8_t *virtio_bits;
47     void *config_base = virtio_input_dev->config;
48     rt_off_t offset = (rt_size_t)&((struct virtio_input_config *)0)->bitmap;
49 
50     bytes = virtio_input_cfg_select(virtio_input_dev, select, subsel);
51 
52     if (bytes == 0)
53     {
54         return;
55     }
56 
57     if (bitcount > bytes * 8)
58     {
59         bitcount = bytes * 8;
60     }
61 
62     /*
63      * Bitmap in virtio config space is a simple stream of bytes,
64      * with the first byte carrying bits 0-7, second bits 8-15 and
65      * so on.
66      */
67     virtio_bits = rt_malloc(bytes);
68 
69     if (virtio_bits == RT_NULL)
70     {
71         return;
72     }
73 
74     for (i = 0; i < bytes; ++i)
75     {
76         void *buffer = (void *)virtio_bits + i;
77 
78         if (virtio_input_dev->virtio_dev.mmio_config->version == 1)
79         {
80             HWREG8(config_base + offset + i) = *((rt_uint8_t *)buffer);
81         }
82         else
83         {
84             rt_memcpy(config_base + offset + i, buffer, sizeof(rt_uint8_t));
85         }
86     }
87 
88     for (bit = 0; bit < bitcount; ++bit)
89     {
90         if (virtio_bits[bit / 8] & (1 << (bit % 8)))
91         {
92             _set_bit(bit, bits);
93         }
94     }
95 
96     rt_free(virtio_bits);
97 
98     if (select == VIRTIO_INPUT_CFG_EV_BITS)
99     {
100         _set_bit(subsel, virtio_input_dev->ev_bit);
101     }
102 }
103 
virtio_input_init(rt_device_t dev)104 static rt_err_t virtio_input_init(rt_device_t dev)
105 {
106     int i;
107     rt_uint16_t idx[VIRTIO_INPUT_QUEUE_MAX_SIZE];
108     struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
109     struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
110     struct virtq *queue_event, *queue_status;
111 
112     virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_KEY, virtio_input_dev->key_bit, KEY_CNT);
113     virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_REL, virtio_input_dev->rel_bit, REL_CNT);
114     virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_ABS, virtio_input_dev->abs_bit, ABS_CNT);
115 
116     queue_event = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_EVENT];
117     queue_status = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_STATUS];
118 
119     virtio_alloc_desc_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, queue_event->num, idx);
120     virtio_alloc_desc_chain(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, queue_status->num, idx);
121 
122     for (i = 0; i < queue_event->num; ++i)
123     {
124         rt_uint16_t id = i;
125         void *addr = &virtio_input_dev->recv_events[i];
126 
127         virtio_fill_desc(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id,
128                 VIRTIO_VA2PA(addr), sizeof(struct virtio_input_event), VIRTQ_DESC_F_WRITE, 0);
129 
130         virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id);
131     }
132     rt_hw_dsb();
133 
134     queue_event->avail->flags = 0;
135     queue_status->avail->flags = VIRTQ_AVAIL_F_NO_INTERRUPT;
136 
137     virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
138 
139     return RT_EOK;
140 }
141 
virtio_input_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)142 static rt_ssize_t virtio_input_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
143 {
144     struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
145 
146     if (buffer == RT_NULL || pos + size >= virtio_input_dev->virtio_dev.queues[VIRTIO_INPUT_QUEUE_EVENT].num)
147     {
148         return 0;
149     }
150 
151     rt_mutex_take(&virtio_input_dev->rw_mutex, RT_WAITING_FOREVER);
152 
153     rt_memcpy(buffer, &virtio_input_dev->bcst_events[pos], size);
154 
155     rt_mutex_release(&virtio_input_dev->rw_mutex);
156 
157     return size;
158 }
159 
virtio_input_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)160 static rt_ssize_t virtio_input_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
161 {
162     struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
163 
164     if (buffer == RT_NULL || pos + size >= virtio_input_dev->virtio_dev.queues[VIRTIO_INPUT_QUEUE_EVENT].num)
165     {
166         return 0;
167     }
168 
169     rt_mutex_take(&virtio_input_dev->rw_mutex, RT_WAITING_FOREVER);
170 
171     rt_memcpy(&virtio_input_dev->bcst_events[pos], buffer, size);
172 
173     rt_mutex_release(&virtio_input_dev->rw_mutex);
174 
175     return size;
176 }
177 
virtio_input_control(rt_device_t dev,int cmd,void * args)178 static rt_err_t virtio_input_control(rt_device_t dev, int cmd, void *args)
179 {
180     rt_err_t status = RT_EOK;
181     struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
182     struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
183     struct virtio_input_config *config = virtio_input_dev->config;
184 
185     if (args == RT_NULL)
186     {
187         return -RT_ERROR;
188     }
189 
190     switch (cmd)
191     {
192     case VIRTIO_DEVICE_CTRL_INPUT_GET_TYPE:
193 
194         *(enum virtio_input_type *)args = virtio_input_dev->type;
195 
196         break;
197     case VIRTIO_DEVICE_CTRL_INPUT_BIND_BSCT_HANDLER:
198 
199         virtio_input_dev->bsct_handler = args;
200 
201         break;
202     case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_X_INFO:
203 
204         virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_ABS_AXIS_X);
205         rt_memcpy(args, config, sizeof(struct virtio_input_config));
206 
207         break;
208     case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_Y_INFO:
209 
210         virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_ABS_AXIS_Y);
211         rt_memcpy(args, config, sizeof(struct virtio_input_config));
212 
213         break;
214     case VIRTIO_DEVICE_CTRL_INPUT_SET_STATUS:
215         {
216             rt_uint16_t id;
217             void *addr;
218             struct virtq *queue_status = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_STATUS];
219 
220 #ifdef RT_USING_SMP
221             rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
222 #endif
223             id = queue_status->avail->idx % queue_status->num;
224             addr = &virtio_input_dev->xmit_events[id];
225 
226             rt_memcpy(addr, args, sizeof(struct virtio_input_event));
227 
228             virtio_free_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id);
229 
230             virtio_fill_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id,
231                     VIRTIO_VA2PA(addr), sizeof(struct virtio_input_event), 0, 0);
232 
233             virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id);
234 
235             virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS);
236 
237             virtio_alloc_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS);
238 
239 #ifdef RT_USING_SMP
240             rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
241 #endif
242         }
243         break;
244     case VIRTIO_DEVICE_CTRL_INPUT_GET_EV_BIT:
245 
246         rt_memcpy(args, virtio_input_dev->ev_bit, sizeof(virtio_input_dev->ev_bit));
247 
248         break;
249     case VIRTIO_DEVICE_CTRL_INPUT_GET_KEY_BIT:
250 
251         rt_memcpy(args, virtio_input_dev->key_bit, sizeof(virtio_input_dev->key_bit));
252 
253         break;
254     case VIRTIO_DEVICE_CTRL_INPUT_GET_REL_BIT:
255 
256         rt_memcpy(args, virtio_input_dev->rel_bit, sizeof(virtio_input_dev->rel_bit));
257 
258         break;
259     case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_BIT:
260 
261         rt_memcpy(args, virtio_input_dev->abs_bit, sizeof(virtio_input_dev->abs_bit));
262 
263         break;
264     default:
265         status = -RT_EINVAL;
266         break;
267     }
268 
269     return status;
270 }
271 
272 #ifdef RT_USING_DEVICE_OPS
273 const static struct rt_device_ops virtio_input_ops =
274 {
275     virtio_input_init,
276     RT_NULL,
277     RT_NULL,
278     virtio_input_read,
279     virtio_input_write,
280     virtio_input_control
281 };
282 #endif
283 
virtio_input_isr(int irqno,void * param)284 static void virtio_input_isr(int irqno, void *param)
285 {
286     struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)param;
287     struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
288     struct virtq *event_queue = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_EVENT];
289     const char *dev_name = virtio_input_dev->parent.parent.name;
290 
291 #ifdef RT_USING_SMP
292     rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
293 #endif
294 
295     virtio_interrupt_ack(virtio_dev);
296     rt_hw_dsb();
297 
298     while (event_queue->used_idx != event_queue->used->idx)
299     {
300         rt_uint16_t id = event_queue->used->ring[event_queue->used_idx % event_queue->num].id;
301         rt_uint32_t len = event_queue->used->ring[event_queue->used_idx % event_queue->num].len;
302 
303         if (len == sizeof(struct virtio_input_event))
304         {
305             struct virtio_input_event *recv_events = &virtio_input_dev->recv_events[id];
306             struct virtio_input_event *bcst_events = &virtio_input_dev->bcst_events[id];
307 
308             if (recv_events->type >= EV_SYN && recv_events->type <= EV_ABS)
309             {
310                 bcst_events->type = recv_events->type;
311                 bcst_events->code = recv_events->code;
312                 bcst_events->value = recv_events->value;
313 
314                 if (virtio_input_dev->bsct_handler != RT_NULL)
315                 {
316                     virtio_input_dev->bsct_handler(*bcst_events);
317                 }
318             }
319             else
320             {
321                 rt_kprintf("%s: Unsupport event[type: %02x, code: %02x, value: %08x]!\n",
322                         dev_name, recv_events->type, recv_events->code, recv_events->value);
323             }
324         }
325         else
326         {
327             rt_kprintf("%s: Invalid event!\n", dev_name);
328         }
329 
330         event_queue->used_idx++;
331 
332         virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id);
333 
334         virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
335     }
336 
337 #ifdef RT_USING_SMP
338     rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
339 #endif
340 }
341 
rt_virtio_input_init(rt_ubase_t * mmio_base,rt_uint32_t irq)342 rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
343 {
344     rt_uint32_t flag;
345     static int dev_no = 0;
346     char dev_name[RT_NAME_MAX];
347     struct virtio_device *virtio_dev;
348     struct virtio_input_device *virtio_input_dev;
349 
350     virtio_input_dev = rt_malloc(sizeof(struct virtio_input_device));
351 
352     if (virtio_input_dev == RT_NULL)
353     {
354         goto _alloc_fail;
355     }
356 
357     virtio_dev = &virtio_input_dev->virtio_dev;
358     virtio_dev->irq = irq;
359     virtio_dev->mmio_base = mmio_base;
360 
361     virtio_input_dev->config = (struct virtio_input_config *)virtio_dev->mmio_config->config;
362     virtio_input_dev->bsct_handler = RT_NULL;
363 
364 #ifdef RT_USING_SMP
365     rt_spin_lock_init(&virtio_dev->spinlock);
366 #endif
367 
368     virtio_reset_device(virtio_dev);
369     virtio_status_acknowledge_driver(virtio_dev);
370 
371     virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
372             (1 << VIRTIO_F_RING_EVENT_IDX) |
373             (1 << VIRTIO_F_RING_INDIRECT_DESC));
374 
375     virtio_status_driver_ok(virtio_dev);
376 
377     if (virtio_queues_alloc(virtio_dev, 2) != RT_EOK)
378     {
379         goto _alloc_fail;
380     }
381 
382     if (virtio_queue_init(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, VIRTIO_INPUT_EVENT_QUEUE_SIZE) != RT_EOK)
383     {
384         goto _alloc_fail;
385     }
386 
387     if (virtio_queue_init(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, VIRTIO_INPUT_STATUS_QUEUE_SIZE) != RT_EOK)
388     {
389         virtio_queue_destroy(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
390 
391         goto _alloc_fail;
392     }
393 
394     virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
395 
396     if (virtio_input_dev->config->ids.product == EV_ABS)
397     {
398         virtio_input_dev->type = VIRTIO_INPUT_TYPE_TABLET;
399 
400         virtio_input_dev->parent.type = RT_Device_Class_Touch;
401 
402         flag = RT_DEVICE_FLAG_STANDALONE | RT_DEVICE_FLAG_INT_RX;
403     }
404     else
405     {
406         if (virtio_input_dev->config->ids.product == EV_KEY)
407         {
408             virtio_input_dev->type = VIRTIO_INPUT_TYPE_KEYBOARD;
409         }
410         else
411         {
412             virtio_input_dev->type = VIRTIO_INPUT_TYPE_MOUSE;
413         }
414 
415         /* Replace it to "KeyBoard" or "Mouse" if support in the future */
416         virtio_input_dev->parent.type = RT_Device_Class_Miscellaneous;
417 
418         flag = RT_DEVICE_FLAG_RDWR;
419     }
420 #ifdef RT_USING_DEVICE_OPS
421     virtio_input_dev->parent.ops = &virtio_input_ops;
422 #else
423     virtio_input_dev->parent.init     = virtio_input_init;
424     virtio_input_dev->parent.open     = RT_NULL;
425     virtio_input_dev->parent.close    = RT_NULL;
426     virtio_input_dev->parent.read     = virtio_input_read;
427     virtio_input_dev->parent.write    = virtio_input_write;
428     virtio_input_dev->parent.control  = virtio_input_control;
429 #endif
430 
431     rt_snprintf(dev_name, RT_NAME_MAX, "virtio-input%d", dev_no++);
432 
433     rt_mutex_init(&virtio_input_dev->rw_mutex, dev_name, RT_IPC_FLAG_PRIO);
434 
435     rt_hw_interrupt_install(irq, virtio_input_isr, virtio_input_dev, dev_name);
436     rt_hw_interrupt_umask(irq);
437 
438     return rt_device_register((rt_device_t)virtio_input_dev, dev_name, flag);
439 
440 _alloc_fail:
441 
442     if (virtio_input_dev != RT_NULL)
443     {
444         virtio_queues_free(virtio_dev);
445         rt_free(virtio_input_dev);
446     }
447     return -RT_ENOMEM;
448 }
449 #endif /* RT_USING_VIRTIO_INPUT */
450