1 /* 2 * Driver for simulating a mouse on GPIO lines. 3 * 4 * Copyright (C) 2007 Atmel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/init.h> 12 #include <linux/version.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <linux/input-polldev.h> 16 #include <linux/gpio_mouse.h> 17 18 #include <asm/gpio.h> 19 20 /* 21 * Timer function which is run every scan_ms ms when the device is opened. 22 * The dev input varaible is set to the the input_dev pointer. 23 */ 24 static void gpio_mouse_scan(struct input_polled_dev *dev) 25 { 26 struct gpio_mouse_platform_data *gpio = dev->private; 27 struct input_dev *input = dev->input; 28 int x, y; 29 30 if (gpio->bleft >= 0) 31 input_report_key(input, BTN_LEFT, 32 gpio_get_value(gpio->bleft) ^ gpio->polarity); 33 if (gpio->bmiddle >= 0) 34 input_report_key(input, BTN_MIDDLE, 35 gpio_get_value(gpio->bmiddle) ^ gpio->polarity); 36 if (gpio->bright >= 0) 37 input_report_key(input, BTN_RIGHT, 38 gpio_get_value(gpio->bright) ^ gpio->polarity); 39 40 x = (gpio_get_value(gpio->right) ^ gpio->polarity) 41 - (gpio_get_value(gpio->left) ^ gpio->polarity); 42 y = (gpio_get_value(gpio->down) ^ gpio->polarity) 43 - (gpio_get_value(gpio->up) ^ gpio->polarity); 44 45 input_report_rel(input, REL_X, x); 46 input_report_rel(input, REL_Y, y); 47 input_sync(input); 48 } 49 50 static int __init gpio_mouse_probe(struct platform_device *pdev) 51 { 52 struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; 53 struct input_polled_dev *input_poll; 54 struct input_dev *input; 55 int pin, i; 56 int error; 57 58 if (!pdata) { 59 dev_err(&pdev->dev, "no platform data\n"); 60 error = -ENXIO; 61 goto out; 62 } 63 64 if (pdata->scan_ms < 0) { 65 dev_err(&pdev->dev, "invalid scan time\n"); 66 error = -EINVAL; 67 goto out; 68 } 69 70 for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { 71 pin = pdata->pins[i]; 72 73 if (pin < 0) { 74 75 if (i <= GPIO_MOUSE_PIN_RIGHT) { 76 /* Mouse direction is required. */ 77 dev_err(&pdev->dev, 78 "missing GPIO for directions\n"); 79 error = -EINVAL; 80 goto out_free_gpios; 81 } 82 83 if (i == GPIO_MOUSE_PIN_BLEFT) 84 dev_dbg(&pdev->dev, "no left button defined\n"); 85 86 } else { 87 error = gpio_request(pin, "gpio_mouse"); 88 if (error) { 89 dev_err(&pdev->dev, "fail %d pin (%d idx)\n", 90 pin, i); 91 goto out_free_gpios; 92 } 93 94 gpio_direction_input(pin); 95 } 96 } 97 98 input_poll = input_allocate_polled_device(); 99 if (!input_poll) { 100 dev_err(&pdev->dev, "not enough memory for input device\n"); 101 error = -ENOMEM; 102 goto out_free_gpios; 103 } 104 105 platform_set_drvdata(pdev, input_poll); 106 107 /* set input-polldev handlers */ 108 input_poll->private = pdata; 109 input_poll->poll = gpio_mouse_scan; 110 input_poll->poll_interval = pdata->scan_ms; 111 112 input = input_poll->input; 113 input->name = pdev->name; 114 input->id.bustype = BUS_HOST; 115 input->dev.parent = &pdev->dev; 116 117 input_set_capability(input, EV_REL, REL_X); 118 input_set_capability(input, EV_REL, REL_Y); 119 if (pdata->bleft >= 0) 120 input_set_capability(input, EV_KEY, BTN_LEFT); 121 if (pdata->bmiddle >= 0) 122 input_set_capability(input, EV_KEY, BTN_MIDDLE); 123 if (pdata->bright >= 0) 124 input_set_capability(input, EV_KEY, BTN_RIGHT); 125 126 error = input_register_polled_device(input_poll); 127 if (error) { 128 dev_err(&pdev->dev, "could not register input device\n"); 129 goto out_free_polldev; 130 } 131 132 dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", 133 pdata->scan_ms, 134 pdata->bleft < 0 ? "" : "left ", 135 pdata->bmiddle < 0 ? "" : "middle ", 136 pdata->bright < 0 ? "" : "right"); 137 138 return 0; 139 140 out_free_polldev: 141 input_free_polled_device(input_poll); 142 platform_set_drvdata(pdev, NULL); 143 144 out_free_gpios: 145 while (--i >= 0) { 146 pin = pdata->pins[i]; 147 if (pin) 148 gpio_free(pin); 149 } 150 out: 151 return error; 152 } 153 154 static int __devexit gpio_mouse_remove(struct platform_device *pdev) 155 { 156 struct input_polled_dev *input = platform_get_drvdata(pdev); 157 struct gpio_mouse_platform_data *pdata = input->private; 158 int pin, i; 159 160 input_unregister_polled_device(input); 161 input_free_polled_device(input); 162 163 for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { 164 pin = pdata->pins[i]; 165 if (pin >= 0) 166 gpio_free(pin); 167 } 168 169 platform_set_drvdata(pdev, NULL); 170 171 return 0; 172 } 173 174 /* work with hotplug and coldplug */ 175 MODULE_ALIAS("platform:gpio_mouse"); 176 177 struct platform_driver gpio_mouse_device_driver = { 178 .remove = __devexit_p(gpio_mouse_remove), 179 .driver = { 180 .name = "gpio_mouse", 181 .owner = THIS_MODULE, 182 } 183 }; 184 185 static int __init gpio_mouse_init(void) 186 { 187 return platform_driver_probe(&gpio_mouse_device_driver, 188 gpio_mouse_probe); 189 } 190 module_init(gpio_mouse_init); 191 192 static void __exit gpio_mouse_exit(void) 193 { 194 platform_driver_unregister(&gpio_mouse_device_driver); 195 } 196 module_exit(gpio_mouse_exit); 197 198 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 199 MODULE_DESCRIPTION("GPIO mouse driver"); 200 MODULE_LICENSE("GPL"); 201