174 lines
6.3 KiB
C
174 lines
6.3 KiB
C
#include <linux/module.h>
|
|
#include <linux/device.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/gpio.h>
|
|
|
|
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;
|
|
|
|
// Operation prototypes
|
|
static int dev_open(struct inode *, struct file *);
|
|
|
|
int major;
|
|
struct class *j_class;
|
|
struct device *j_device;
|
|
|
|
// The driver's file operations
|
|
static const struct file_operations fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = dev_open
|
|
};
|
|
|
|
/*
|
|
* 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
|
|
if (value == 1) {
|
|
pr_info("GPIO %d: Rising edge detected\n", gpio);
|
|
} else {
|
|
pr_info("GPIO %d: Falling edge detected\n", gpio);
|
|
}
|
|
return (irqreturn_t) IRQ_HANDLED; // Announce that the IRQ has been handled correctly
|
|
}
|
|
|
|
/**
|
|
* 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 <maxime.rohmer@hesge.ch>");
|
|
MODULE_DESCRIPTION("Module to drive the joystick on the myLab1 card");
|
|
MODULE_VERSION("0.1"); |