Skip to content

Commit 772a43a

Browse files
chejianjjren1
authored andcommitted
dm: virtio-input: implement input event tx/rx
Input events are read from host evdev fd and cached into a local queue. When SYN_REPORT is read, the cached input events are sent to guest via EVENT virtqueue. Guest input events are read from STATUS virtqueue then written to host evdev fd. Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Reviewed-by: Hao Li <hao.l.li@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 25fe563 commit 772a43a

File tree

1 file changed

+97
-2
lines changed

1 file changed

+97
-2
lines changed

devicemodel/hw/pci/virtio/virtio_input.c

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,110 @@ virtio_input_notify_event_vq(void *vdev, struct virtio_vq_info *vq)
245245
static void
246246
virtio_input_notify_status_vq(void *vdev, struct virtio_vq_info *vq)
247247
{
248-
/* to be implemented */
248+
struct virtio_input *vi;
249+
struct virtio_input_event event;
250+
struct input_event host_event;
251+
struct iovec iov;
252+
int n, len;
253+
uint16_t idx;
254+
255+
vi = vdev;
256+
257+
while (vq_has_descs(vq)) {
258+
n = vq_getchain(vq, &idx, &iov, 1, NULL);
259+
assert(n == 1);
260+
261+
memcpy(&event, iov.iov_base, sizeof(event));
262+
host_event.type = event.type;
263+
host_event.code = event.code;
264+
host_event.value = event.value;
265+
len = write(vi->fd, &host_event, sizeof(host_event));
266+
if (len == -1)
267+
WPRINTF(("%s: write failed, len = %d, errno = %d\n",
268+
__func__, len, errno));
269+
vq_relchain(vq, idx, sizeof(event)); /* Release the chain */
270+
}
271+
vq_endchains(vq, 1); /* Generate interrupt if appropriate. */
272+
}
273+
274+
static void
275+
virtio_input_send_event(struct virtio_input *vi,
276+
struct virtio_input_event *event)
277+
{
278+
struct virtio_vq_info *vq;
279+
struct iovec iov;
280+
int n, i;
281+
uint16_t idx;
282+
283+
if (!vi->ready)
284+
return;
285+
286+
if (vi->event_qindex == vi->event_qsize) {
287+
vi->event_qsize++;
288+
vi->event_queue = realloc(vi->event_queue,
289+
vi->event_qsize *
290+
sizeof(struct virtio_input_event_elem));
291+
assert(vi->event_queue);
292+
}
293+
vi->event_queue[vi->event_qindex].event = *event;
294+
vi->event_qindex++;
295+
296+
if (event->type != EV_SYN || event->code != SYN_REPORT)
297+
return;
298+
299+
vq = &vi->queues[VIRTIO_INPUT_EVENT_QUEUE];
300+
for (i = 0; i < vi->event_qindex; i++) {
301+
if (!vq_has_descs(vq)) {
302+
while (i-- > 0)
303+
vq_retchain(vq);
304+
WPRINTF(("%s: not enough avail descs, dropped:%d\n",
305+
__func__, vi->event_qindex));
306+
goto out;
307+
}
308+
n = vq_getchain(vq, &idx, &iov, 1, NULL);
309+
assert(n == 1);
310+
vi->event_queue[i].iov = iov;
311+
vi->event_queue[i].idx = idx;
312+
}
313+
314+
for (i = 0; i < vi->event_qindex; i++) {
315+
memcpy(vi->event_queue[i].iov.iov_base,
316+
&vi->event_queue[i].event,
317+
sizeof(struct virtio_input_event));
318+
vq_relchain(vq, vi->event_queue[i].idx,
319+
sizeof(struct virtio_input_event));
320+
}
321+
322+
out:
323+
vi->event_qindex = 0;
324+
vq_endchains(vq, 1);
249325
}
250326

251327
static void
252328
virtio_input_read_event(int fd __attribute__((unused)),
253329
enum ev_type t __attribute__((unused)),
254330
void *arg)
255331
{
256-
/* to be implemented */
332+
struct virtio_input *vi = arg;
333+
struct virtio_input_event event;
334+
struct input_event host_event;
335+
int len;
336+
337+
while (1) {
338+
len = read(vi->fd, &host_event, sizeof(host_event));
339+
if (len != sizeof(host_event)) {
340+
if (len == -1 && errno != EAGAIN)
341+
WPRINTF(("vtinput: host read failed! "
342+
"len = %d, errno = %d\n",
343+
len, errno));
344+
break;
345+
}
346+
347+
event.type = host_event.type;
348+
event.code = host_event.code;
349+
event.value = host_event.value;
350+
virtio_input_send_event(vi, &event);
351+
}
257352
}
258353

259354
static bool

0 commit comments

Comments
 (0)