Path: blob/master/drivers/input/mouse/gpio_mouse.c
15109 views
/*1* Driver for simulating a mouse on GPIO lines.2*3* Copyright (C) 2007 Atmel Corporation4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License version 2 as7* published by the Free Software Foundation.8*/910#include <linux/init.h>11#include <linux/module.h>12#include <linux/platform_device.h>13#include <linux/input-polldev.h>14#include <linux/gpio_mouse.h>1516#include <asm/gpio.h>1718/*19* Timer function which is run every scan_ms ms when the device is opened.20* The dev input variable is set to the the input_dev pointer.21*/22static void gpio_mouse_scan(struct input_polled_dev *dev)23{24struct gpio_mouse_platform_data *gpio = dev->private;25struct input_dev *input = dev->input;26int x, y;2728if (gpio->bleft >= 0)29input_report_key(input, BTN_LEFT,30gpio_get_value(gpio->bleft) ^ gpio->polarity);31if (gpio->bmiddle >= 0)32input_report_key(input, BTN_MIDDLE,33gpio_get_value(gpio->bmiddle) ^ gpio->polarity);34if (gpio->bright >= 0)35input_report_key(input, BTN_RIGHT,36gpio_get_value(gpio->bright) ^ gpio->polarity);3738x = (gpio_get_value(gpio->right) ^ gpio->polarity)39- (gpio_get_value(gpio->left) ^ gpio->polarity);40y = (gpio_get_value(gpio->down) ^ gpio->polarity)41- (gpio_get_value(gpio->up) ^ gpio->polarity);4243input_report_rel(input, REL_X, x);44input_report_rel(input, REL_Y, y);45input_sync(input);46}4748static int __devinit gpio_mouse_probe(struct platform_device *pdev)49{50struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;51struct input_polled_dev *input_poll;52struct input_dev *input;53int pin, i;54int error;5556if (!pdata) {57dev_err(&pdev->dev, "no platform data\n");58error = -ENXIO;59goto out;60}6162if (pdata->scan_ms < 0) {63dev_err(&pdev->dev, "invalid scan time\n");64error = -EINVAL;65goto out;66}6768for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {69pin = pdata->pins[i];7071if (pin < 0) {7273if (i <= GPIO_MOUSE_PIN_RIGHT) {74/* Mouse direction is required. */75dev_err(&pdev->dev,76"missing GPIO for directions\n");77error = -EINVAL;78goto out_free_gpios;79}8081if (i == GPIO_MOUSE_PIN_BLEFT)82dev_dbg(&pdev->dev, "no left button defined\n");8384} else {85error = gpio_request(pin, "gpio_mouse");86if (error) {87dev_err(&pdev->dev, "fail %d pin (%d idx)\n",88pin, i);89goto out_free_gpios;90}9192gpio_direction_input(pin);93}94}9596input_poll = input_allocate_polled_device();97if (!input_poll) {98dev_err(&pdev->dev, "not enough memory for input device\n");99error = -ENOMEM;100goto out_free_gpios;101}102103platform_set_drvdata(pdev, input_poll);104105/* set input-polldev handlers */106input_poll->private = pdata;107input_poll->poll = gpio_mouse_scan;108input_poll->poll_interval = pdata->scan_ms;109110input = input_poll->input;111input->name = pdev->name;112input->id.bustype = BUS_HOST;113input->dev.parent = &pdev->dev;114115input_set_capability(input, EV_REL, REL_X);116input_set_capability(input, EV_REL, REL_Y);117if (pdata->bleft >= 0)118input_set_capability(input, EV_KEY, BTN_LEFT);119if (pdata->bmiddle >= 0)120input_set_capability(input, EV_KEY, BTN_MIDDLE);121if (pdata->bright >= 0)122input_set_capability(input, EV_KEY, BTN_RIGHT);123124error = input_register_polled_device(input_poll);125if (error) {126dev_err(&pdev->dev, "could not register input device\n");127goto out_free_polldev;128}129130dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",131pdata->scan_ms,132pdata->bleft < 0 ? "" : "left ",133pdata->bmiddle < 0 ? "" : "middle ",134pdata->bright < 0 ? "" : "right");135136return 0;137138out_free_polldev:139input_free_polled_device(input_poll);140platform_set_drvdata(pdev, NULL);141142out_free_gpios:143while (--i >= 0) {144pin = pdata->pins[i];145if (pin)146gpio_free(pin);147}148out:149return error;150}151152static int __devexit gpio_mouse_remove(struct platform_device *pdev)153{154struct input_polled_dev *input = platform_get_drvdata(pdev);155struct gpio_mouse_platform_data *pdata = input->private;156int pin, i;157158input_unregister_polled_device(input);159input_free_polled_device(input);160161for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {162pin = pdata->pins[i];163if (pin >= 0)164gpio_free(pin);165}166167platform_set_drvdata(pdev, NULL);168169return 0;170}171172static struct platform_driver gpio_mouse_device_driver = {173.probe = gpio_mouse_probe,174.remove = __devexit_p(gpio_mouse_remove),175.driver = {176.name = "gpio_mouse",177.owner = THIS_MODULE,178}179};180181static int __init gpio_mouse_init(void)182{183return platform_driver_register(&gpio_mouse_device_driver);184}185module_init(gpio_mouse_init);186187static void __exit gpio_mouse_exit(void)188{189platform_driver_unregister(&gpio_mouse_device_driver);190}191module_exit(gpio_mouse_exit);192193MODULE_AUTHOR("Hans-Christian Egtvedt <[email protected]>");194MODULE_DESCRIPTION("GPIO mouse driver");195MODULE_LICENSE("GPL");196MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */197198199200