diff options
author | knolax <1339802534.kk@gmail.com> | 2017-12-07 20:19:41 -0500 |
---|---|---|
committer | knolax <1339802534.kk@gmail.com> | 2017-12-07 20:19:41 -0500 |
commit | d3a09ff7f9a2fb497ba492398f4307c2df628a03 (patch) | |
tree | 8c1a406fb0dba2147b6d141014597675a698c58d |
initial commit
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | skey.c | 110 |
2 files changed, 117 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5597d2f --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +obj-m := skey.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean @@ -0,0 +1,110 @@ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/timer.h> +/* + * Unsigned ints containing the BCM pin numbers for the pins used, __initdata + * helps with the loading and unloading of data in memory + */ +static __initdata unsigned int column_pins[10] = {10, 24, 23, 22, 27, 18, 17, 15, 14, 4}; +static __initdata unsigned int row_pins[3] = {3, 6, 5}; +/* + * GPIO labels + */ +static __initdata char * clabels[10] = {"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9",}; +static __initdata char * rlabels[3] = {"R0", "R1", "R2"}; +/* + * timer period in ms and timer struct + */ +static struct timer_list update_timer; +static int update_period = 5000; +/* + *This function is called every timer-period to actually read the keyboard + */ +static void skey_update (unsigned long unused) { + printk(KERN_INFO "skey: updated keyboard\n"); + mod_timer(&update_timer, jiffies + msecs_to_jiffies(update_period)); +} +/* + * This function is called when the module is loaded + * __init functions similar to __initdata + */ +static int __init skey_init (void) { + printk(KERN_INFO "skey: module initiating...\n"); + int i = 0; + //claims the column pins + while (i < 10) { + //checks to see if the gpios are valid + if (!gpio_is_valid(column_pins[i])) { + printk(KERN_ALERT "skey: column_pins[%d], BCM %d request invalid\n", i, column_pins[i]); + return -EINVAL; + } + //requests access of the GPIO + if (gpio_request_one(column_pins[i], GPIOF_DIR_IN ,clabels[i])) { + printk(KERN_ALERT "skey: column_pins[%d], BCM %d request failed\n", i, column_pins[i]); + return -EINVAL; + } + i++; + } + //ditto for row pins + int j = 0; + while (j < 3) { + //checks to see if the gpios are valid + if (!gpio_is_valid(row_pins[j])) { + printk(KERN_ALERT "skey: row_pins[%d], BCM %d request invalid\n", j, row_pins[j]); + return -EINVAL; + } + //requests access of the GPIO + if (gpio_request_one(row_pins[j], GPIOF_OUT_INIT_LOW ,rlabels[j])) { + printk(KERN_ALERT "skey: row_pins[%d], BCM %d request failed\n", j, row_pins[j]); + return -EINVAL; + } + j++; + } + //sets up timer for keyboard read function + setup_timer(&update_timer, skey_update, 0); + if (mod_timer(&update_timer, jiffies + msecs_to_jiffies(update_period))) { + printk(KERN_ALERT "skey: failed to set up timer\n"); + return -EINVAL; + } + printk(KERN_INFO "skey: module finished initiating\n"); + return 0; +} +/* + * This function is called when the module is unloaded + * + */ +static void __exit skey_exit (void) { + printk(KERN_INFO "skey: module exiting...\n"); + //frees column and row pins + int i = 0; + while (i < 10) { + gpio_free(column_pins[i]); + i++; + } + int j = 0; + while (j < 3) { + gpio_free(row_pins[j]); + j++; + } + //deletes update timer + del_timer(&update_timer); + printk(KERN_INFO "skey: module exited\n"); + return; +} +/* + * Registers the init and exit functions + */ +module_init(skey_init); +module_exit(skey_exit); +/* + * registers module metadata + */ +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Haoran S. Diao <1339802534.kk@gmail.com>"); +MODULE_DESCRIPTION("Driver for the omnicom switch keyboard"); +/* + *this sets the name of device files used by this module, this is used + *when the kernel makes devices automatically + */ +MODULE_SUPPORTED_DEVICE("skeydev"); |