nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@1: #include nuclear@0: #include nuclear@1: #include nuclear@2: #include nuclear@2: #include nuclear@0: nuclear@1: #define TEST_OUTPUT_PIN 4 nuclear@2: #define TEST_OUTPUT_GREEN 17 nuclear@1: #define TEST_INPUT_PIN 22 nuclear@0: nuclear@1: static int dev_init(void); nuclear@1: static void dev_exit(void); nuclear@1: static int dev_open(struct inode *inode, struct file *file); nuclear@1: static int dev_close(struct inode *inode, struct file *file); nuclear@1: static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset); nuclear@0: nuclear@1: static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs); nuclear@0: nuclear@0: MODULE_LICENSE("GPL"); nuclear@0: MODULE_AUTHOR("John Tsiombikas"); nuclear@0: MODULE_DESCRIPTION("gpio module"); nuclear@0: nuclear@1: module_init(dev_init); nuclear@1: module_exit(dev_exit); nuclear@0: nuclear@0: static int major; nuclear@1: static int intr_num = -1; nuclear@1: static int num_presses; nuclear@0: nuclear@0: static struct file_operations ops = { nuclear@1: .open = dev_open, nuclear@1: .release = dev_close, nuclear@1: .write = dev_write nuclear@0: }; nuclear@0: nuclear@1: static int dev_init(void) nuclear@0: { nuclear@0: if((major = register_chrdev(0, "gpio", &ops)) < 0) { nuclear@0: printk("failed to register character device gpio (err: %d)\n", major); nuclear@0: return -1; nuclear@0: } nuclear@0: printk("gpio module registered (device: %d)\n", major); nuclear@1: nuclear@1: gpio_direction_output(TEST_OUTPUT_PIN, 0); nuclear@2: gpio_direction_output(TEST_OUTPUT_GREEN, 0); nuclear@1: nuclear@1: if(gpio_request(TEST_INPUT_PIN, "test_input") != 0) { nuclear@1: printk("gpio: failed to get input gpio pin\n"); nuclear@1: return -1; nuclear@1: } nuclear@2: gpio_direction_input(TEST_INPUT_PIN); nuclear@2: bcm2708_gpio_setpull(gpio_to_chip(TEST_INPUT_PIN), TEST_INPUT_PIN, BCM2708_PULL_DOWN); nuclear@1: if((intr_num = gpio_to_irq(TEST_INPUT_PIN)) < 0) { nuclear@1: printk("gpio: failed to get interrupt line for gpio pin\n"); nuclear@1: return -1; nuclear@1: } nuclear@1: if(request_irq(intr_num, (irq_handler_t)intr_handler, IRQF_TRIGGER_RISING, nuclear@1: "gpio_intr", "gpio") != 0) { nuclear@1: printk("gpio: failed to setup interrupt handler\n"); nuclear@1: return -1; nuclear@1: } nuclear@1: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@1: static void dev_exit(void) nuclear@0: { nuclear@1: printk("gpio exit\n"); nuclear@2: nuclear@0: unregister_chrdev(major, "gpio"); nuclear@1: nuclear@1: if(intr_num != -1) { nuclear@1: free_irq(intr_num, "gpio"); nuclear@1: } nuclear@1: gpio_free(TEST_INPUT_PIN); nuclear@2: nuclear@2: gpio_direction_input(TEST_OUTPUT_PIN); nuclear@2: gpio_direction_input(TEST_OUTPUT_GREEN); nuclear@2: bcm2708_gpio_setpull(gpio_to_chip(TEST_INPUT_PIN), TEST_INPUT_PIN, BCM2708_PULL_OFF); nuclear@0: } nuclear@0: nuclear@1: static int dev_open(struct inode *inode, struct file *file) nuclear@0: { nuclear@0: try_module_get(THIS_MODULE); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@1: static int dev_close(struct inode *inode, struct file *file) nuclear@0: { nuclear@0: module_put(THIS_MODULE); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@1: static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset) nuclear@0: { nuclear@0: unsigned char val; nuclear@0: nuclear@0: if(sz < 1) { nuclear@0: return 0; nuclear@0: } nuclear@0: if(copy_from_user(&val, (unsigned char*)buf + sz - 1, 1) != 0) { nuclear@0: return -EFAULT; nuclear@0: } nuclear@0: nuclear@1: gpio_set_value(TEST_OUTPUT_PIN, val == '0' ? 0 : 1); nuclear@0: return sz; nuclear@0: } nuclear@0: nuclear@1: static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs) nuclear@0: { nuclear@2: static unsigned long ignore_until; nuclear@2: unsigned long now = jiffies; nuclear@2: nuclear@2: if(time_before(now, ignore_until)) { nuclear@2: return IRQ_HANDLED; nuclear@2: } nuclear@2: ignore_until = now + 128 * HZ / 1000; nuclear@2: nuclear@1: printk("presses: %d\n", num_presses++); nuclear@2: gpio_set_value(TEST_OUTPUT_GREEN, num_presses & 1); nuclear@1: return IRQ_HANDLED; nuclear@0: }