virtio-input(share-device)数据流向

这里面涉及到几个模块:

virtio-input:virtio-input触摸驱动

virtio-mmio: virtio memory map I/O, 负责host-guest之间的内存映射

virtio-ring: ring buffer,负责virtio的buffer管理

Ring Buffer初始化过程

1,virtio_input_probe函数流程过程中会调用virtinput_init_vqs来申请ring buffer,同时注册回调函数(当中断触发时,调用callback函数)。

2,在virtinput_init_vqs函数运行的过程中,会通过readl/writel的方法从QNX侧获取到需要申请的ring buffer的数量:

    num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
    if (num == 0) {
        err = -ENOENT;
        goto error_new_virtqueue;
    }   

3,在virtio-ring 模块中申请内存,并且把地址的映射关系返回给virtio-mmio

4,virtio-mmio通过readl/writel将这些buffer的地址信息告诉QNX

中断触发情况下的数据走向

1,QNX侧vdev-virtio-input.so接收到screen的touch事件信息

2,vdev-virtio-input.so将得到的touch事件解析成下面这个结构体数据,并且逐个放到guest os给过来的buffer中:

struct virtio_input_event {
    __le16 type;
    __le16 code;
    __le32 value;
};

3,vdev-virtio-input.so触发中断

4,guest触发中断处理函数,在这里是vm_interrupt

5,vm_interrupt函数调用前面注册的回调函数,这里是virtinput_recv_events

6,virtinput_recv_events,函数从ring buffer中把touch数据都获取到,并注入input子系统中

static void virtinput_recv_events(struct virtqueue *vq)
{
    struct virtio_input *vi = vq->vdev->priv;
    struct virtio_input_event *event;
    unsigned long flags;
    unsigned int len;

    spin_lock_irqsave(&vi->lock, flags);
    if (vi->ready) {
        while ((event = virtqueue_get_buf(vi->evt, &len)) != NULL) {
            spin_unlock_irqrestore(&vi->lock, flags);
            input_event(vi->idev,
                    le16_to_cpu(event->type),
                    le16_to_cpu(event->code),
                    le32_to_cpu(event->value));
            spin_lock_irqsave(&vi->lock, flags);
            printk(KERN_INFO "packed_ring:%d input: [0x%x][0x%x][0x%x] \n", vi->evt->packed_ring, event->type,event->code,event->value);
            virtinput_queue_evtbuf(vi, event);
        }
        virtqueue_kick(vq);
    }   
    spin_unlock_irqrestore(&vi->lock, flags);
}

补充一张图:

猜你喜欢

转载自blog.csdn.net/kill150/article/details/130266082