#include #include #include #include #include #include #include const int JOYSTICK_UP = 16; //GPIO0 const int JOYSTICK_DOWN = 17; //GPIO0 const int JOYSTICK_LEFT = 21; //GPIO0 const int JOYSTICK_RIGHT = 27 + 32; //GPIO1 offset of 32 on GPIO 1 const int JOYSTICK_BUTTON = 23; //GPIO0 #define IRQ_NAME "myjoystick_irq" int irqNbr_UP,irqNbr_DOWN,irqNbr_LEFT,irqNbr_RIGHT,irqNbr_BUTTON = 0; static int UP,DOWN,LEFT,RIGHT,BUTTON = 0; int major; struct class *j_class; struct device *j_device; // Operation prototypes static int dev_open(struct inode *, struct file *); static ssize_t dev_read(struct file *filep, char __user *buffer, size_t len, loff_t *offset){ int joystick_status[5] = {UP,DOWN,LEFT,RIGHT,BUTTON}; int data_len = 5*sizeof(int); // Copy data to user-space buffer if (copy_to_user(buffer, joystick_status, data_len)) { pr_err("Failed to send data to user\n"); return -EFAULT; } return 0; } // The driver's file operations static const struct file_operations fops = { .owner = THIS_MODULE, .open = dev_open, .read = dev_read }; /* * Joystick IRQ handler */ static irqreturn_t mylab_irq_handler(int irq, void *dev_id) { int gpio = (int)dev_id; // GPIO number passed as dev_id int value = gpio_get_value(gpio); // Get the current GPIO value switch(gpio){ case JOYSTICK_UP: UP = value; break; case JOYSTICK_DOWN: DOWN = value; break; case JOYSTICK_LEFT: LEFT = value; break; case JOYSTICK_RIGHT: RIGHT = value; break; case JOYSTICK_BUTTON: BUTTON = value; break; default: //Wtf? break; } return (irqreturn_t) IRQ_HANDLED; } /** * Driver initialization code. */ static int __init mylab1_joystick_dev_init(void) { // TODO // 1) Register the device by dynamically obtaining a major number major = register_chrdev(0, "mylab1_joystick", &fops); if(major < 0){ pr_info("mylab1_joystick: could not get a major number, initialisation failed\n"); return -1; } // 2) Create the class j_class = class_create("mylab1_joystick"); if (IS_ERR(j_class)){ pr_info("mylab1_joystick: could not create class, initialisation failed\n"); return -1; } // 3) Create the device in /dev j_device = device_create(j_class, NULL, MKDEV(major, 0), NULL, "mylab1_joystick"); if (IS_ERR(j_device)){ pr_info("mylab1_joystick: could not create device, initialisation failed\n"); return -1; } // 6) Request the necessary GPIOs int err = 0; err = gpio_request_one(JOYSTICK_UP,GPIOF_DIR_IN,"UP"); if(err != 0) pr_info("mylab1_joystick: Could not request GPIO %d\n",JOYSTICK_UP); err = gpio_request_one(JOYSTICK_DOWN,GPIOF_DIR_IN,"DOWN"); if(err != 0) pr_info("mylab1_joystick: Could not request GPIO %d\n",JOYSTICK_DOWN); err = gpio_request_one(JOYSTICK_LEFT,GPIOF_DIR_IN,"UP"); if(err != 0) pr_info("mylab1_joystick: Could not request GPIO %d\n",JOYSTICK_LEFT); err = gpio_request_one(JOYSTICK_RIGHT,GPIOF_DIR_IN,"UP"); if(err != 0) pr_info("mylab1_joystick: Could not request GPIO %d\n",JOYSTICK_RIGHT); err = gpio_request_one(JOYSTICK_BUTTON,GPIOF_DIR_IN,"UP"); if(err != 0) pr_info("mylab1_joystick: Could not request GPIO %d\n",JOYSTICK_BUTTON); // 7) Register an IRQ handler per GPIO int irqres = 0; // JOYSTICK UP irqNbr_UP = gpio_to_irq(JOYSTICK_UP); if(irqNbr_UP < 0) pr_info("mylab1_joystick: Could not request IRQ number on GPIO : %d\n",JOYSTICK_UP); irqres = request_irq(irqNbr_UP, mylab_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQ_NAME, (void*)JOYSTICK_UP); if(irqres < 0) pr_info("mylab1_joystick: Could not request IRQ on GPIO : %d\n",JOYSTICK_UP); //JOYSTICK DOWN irqNbr_DOWN = gpio_to_irq(JOYSTICK_DOWN); if(irqNbr_DOWN < 0) pr_info("mylab1_joystick: Could not request IRQ number on GPIO : %d\n",JOYSTICK_DOWN); irqres = request_irq(irqNbr_DOWN, mylab_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQ_NAME, (void*)JOYSTICK_DOWN); if(irqres < 0) pr_info("mylab1_joystick: Could not request IRQ on GPIO : %d\n",JOYSTICK_DOWN); // JOYSTICK LEFT irqNbr_LEFT = gpio_to_irq(JOYSTICK_LEFT); if(irqNbr_LEFT < 0) pr_info("mylab1_joystick: Could not request IRQ number on GPIO : %d\n",JOYSTICK_LEFT); irqres = request_irq(irqNbr_LEFT, mylab_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQ_NAME, (void*)JOYSTICK_LEFT); if(irqres < 0) pr_info("mylab1_joystick: Could not request IRQ on GPIO : %d\n",JOYSTICK_LEFT); // JOYSTICK RIGHT irqNbr_RIGHT = gpio_to_irq(JOYSTICK_RIGHT); if(irqNbr_RIGHT < 0) pr_info("mylab1_joystick: Could not request IRQ number on GPIO : %d\n",JOYSTICK_RIGHT); irqres = request_irq(irqNbr_RIGHT, mylab_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQ_NAME, (void*)JOYSTICK_RIGHT); if(irqres < 0) pr_info("mylab1_joystick: Could not request IRQ on GPIO : %d\n",JOYSTICK_RIGHT); // JOYSTICK BUTTON irqNbr_BUTTON = gpio_to_irq(JOYSTICK_BUTTON); if(irqNbr_BUTTON < 0) pr_info("mylab1_joystick: Could not request IRQ number on GPIO : %d\n",JOYSTICK_BUTTON); irqres = request_irq(irqNbr_BUTTON, mylab_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQ_NAME, (void*)JOYSTICK_BUTTON); if(irqres < 0) pr_info("mylab1_joystick: Could not request IRQ on GPIO : %d\n",JOYSTICK_BUTTON); //init finished pr_info("mylab1_joystick: driver initialized\n"); return 0; } /** * This function is called when the module is unloaded. */ static void __exit mylab1_joystick_dev_exit(void) { // TODO // 1) Destroy the device device_destroy(j_class,MKDEV(major, 0)); // 2) Destroy the class class_destroy(j_class); // 4) Unregister the device unregister_chrdev(major,"mylab1_joystick"); // 5) Free the IRQs free_irq(irqNbr_UP, (void*)JOYSTICK_UP); free_irq(irqNbr_DOWN, (void*)JOYSTICK_DOWN); free_irq(irqNbr_LEFT, (void*)JOYSTICK_LEFT); free_irq(irqNbr_RIGHT, (void*)JOYSTICK_RIGHT); free_irq(irqNbr_BUTTON, (void*)JOYSTICK_BUTTON); // 6) Free the GPIOs gpio_free(JOYSTICK_UP); gpio_free(JOYSTICK_DOWN); gpio_free(JOYSTICK_LEFT); gpio_free(JOYSTICK_RIGHT); gpio_free(JOYSTICK_BUTTON); pr_info("mylab1_joystick: driver destroyed\n"); } /** * Open operation */ static int dev_open(struct inode *inod, struct file *f) { pr_info("mylab1_joystick: device opened\n"); return 0; } module_init(mylab1_joystick_dev_init); module_exit(mylab1_joystick_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("defenestration en cours "); MODULE_DESCRIPTION("Module to drive the joystick on the myLab1 card"); MODULE_VERSION("0.1");