summaryrefslogtreecommitdiff
path: root/skey.c
diff options
context:
space:
mode:
Diffstat (limited to 'skey.c')
-rw-r--r--skey.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/skey.c b/skey.c
new file mode 100644
index 0000000..834a6fe
--- /dev/null
+++ b/skey.c
@@ -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");