#include <linux/virtio.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/io.h>               /* io map */
#include <linux/dma-mapping.h>      /* DMA */
#include <linux/kernel.h>           /* kstrtoint() func */
#include <linux/virtio_config.h>    /* find_single_vq() func */

#include "../files/src/virtio-note.h"


#define VIRTIO_NOTE_ID 42

static void virtio_note_store(struct device *dev, const char *buf, size_t count){
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    

}

static void virtio_dummy_recv_cb(struct virtqueue *vq)
{
        struct virtio_dummy_dev *dev = vq->vdev->priv;
        char *buf;
        unsigned int len;

        while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) {
            pr_info("%s\n", buf); 
        }
}

static int virtio_dummy_probe(struct virtio_device *vdev)
{
        struct virtio_dummy_dev *dev = NULL;

        /* initialize device data */
        dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;

        /* the device has a single virtqueue */
        dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input");
        if (IS_ERR(dev->vq)) {
                kfree(dev);
                return PTR_ERR(dev->vq);

        }
        vdev->priv = dev;

        /* from this point on, the device can notify and get callbacks */
        virtio_device_ready(vdev);

        return 0;
}

static void virtio_dummy_remove(struct virtio_device *vdev)
{
        struct virtio_dummy_dev *dev = vdev->priv;

        /*
         * disable vq interrupts: equivalent to
         * vdev->config->reset(vdev)
         */
        virtio_reset_device(vdev);

        char *buf;
        /* detach unused buffers */
        while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) {
                kfree(buf);
        }

        /* remove virtqueues */
        vdev->config->del_vqs(vdev);

        kfree(dev);
}

static const struct virtio_device_id id_table[] = {
        { VIRTIO_NOTE_ID, VIRTIO_DEV_ANY_ID },
        { 0 },
};

static struct virtio_driver virtio_dummy_driver = {
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
        .probe =        virtio_dummy_probe,
        .remove =       virtio_dummy_remove,
};

module_virtio_driver(virtio_dummy_driver);
MODULE_DEVICE_TABLE(virtio, id_table);
MODULE_DESCRIPTION("Dummy virtio driver");
MODULE_LICENSE("GPL");
