aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ams/ams-input.c
diff options
context:
space:
mode:
authorStelian Pop <stelian@popies.net>2006-12-12 12:18:30 -0500
committerJean Delvare <khali@arrakis.delvare>2006-12-12 12:18:30 -0500
commitdcb69dd010c182507a8db8940618f6413f65e0af (patch)
treeb0a2d0795866d7d787af82be6041cf3cabb6c640 /drivers/hwmon/ams/ams-input.c
parent61db011d403388b2dd342489d7110cf13cb99025 (diff)
hwmon: New AMS hardware monitoring driver
This driver adds support for the Apple Motion Sensor (AMS) as found in 2005 revisions of Apple PowerBooks and iBooks. It implements both the PMU and I2C variants. The I2C driver and mouse emulation is based on code by Stelian Pop, while the PMU driver has been developped by Michael Hanselmann. HD parking support will be added later. Various people contributed fixes to this driver, including Aristeu Sergio Rozanski Filho and Jean Delvare. Signed-off-by: Stelian Pop <stelian@popies.net> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Robert Love <rml@novell.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/ams/ams-input.c')
-rw-r--r--drivers/hwmon/ams/ams-input.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
new file mode 100644
index 000000000000..f126aa485134
--- /dev/null
+++ b/drivers/hwmon/ams/ams-input.c
@@ -0,0 +1,160 @@
1/*
2 * Apple Motion Sensor driver (joystick emulation)
3 *
4 * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
5 * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/module.h>
14
15#include <linux/types.h>
16#include <linux/errno.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19
20#include "ams.h"
21
22static unsigned int joystick;
23module_param(joystick, bool, 0644);
24MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
25
26static unsigned int invert;
27module_param(invert, bool, 0644);
28MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
29
30static int ams_input_kthread(void *data)
31{
32 s8 x, y, z;
33
34 while (!kthread_should_stop()) {
35 mutex_lock(&ams_info.lock);
36
37 ams_sensors(&x, &y, &z);
38
39 x -= ams_info.xcalib;
40 y -= ams_info.ycalib;
41 z -= ams_info.zcalib;
42
43 input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
44 input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
45 input_report_abs(ams_info.idev, ABS_Z, z);
46
47 input_sync(ams_info.idev);
48
49 mutex_unlock(&ams_info.lock);
50
51 msleep(25);
52 }
53
54 return 0;
55}
56
57static int ams_input_open(struct input_dev *dev)
58{
59 ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
60 return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
61}
62
63static void ams_input_close(struct input_dev *dev)
64{
65 kthread_stop(ams_info.kthread);
66}
67
68/* Call with ams_info.lock held! */
69static void ams_input_enable(void)
70{
71 s8 x, y, z;
72
73 if (ams_info.idev)
74 return;
75
76 ams_sensors(&x, &y, &z);
77 ams_info.xcalib = x;
78 ams_info.ycalib = y;
79 ams_info.zcalib = z;
80
81 ams_info.idev = input_allocate_device();
82 if (!ams_info.idev)
83 return;
84
85 ams_info.idev->name = "Apple Motion Sensor";
86 ams_info.idev->id.bustype = ams_info.bustype;
87 ams_info.idev->id.vendor = 0;
88 ams_info.idev->open = ams_input_open;
89 ams_info.idev->close = ams_input_close;
90 ams_info.idev->cdev.dev = &ams_info.of_dev->dev;
91
92 input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
93 input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
94 input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
95
96 set_bit(EV_ABS, ams_info.idev->evbit);
97 set_bit(EV_KEY, ams_info.idev->evbit);
98 set_bit(BTN_TOUCH, ams_info.idev->keybit);
99
100 if (input_register_device(ams_info.idev)) {
101 input_free_device(ams_info.idev);
102 ams_info.idev = NULL;
103 return;
104 }
105}
106
107/* Call with ams_info.lock held! */
108static void ams_input_disable(void)
109{
110 if (ams_info.idev) {
111 input_unregister_device(ams_info.idev);
112 ams_info.idev = NULL;
113 }
114}
115
116static ssize_t ams_input_show_joystick(struct device *dev,
117 struct device_attribute *attr, char *buf)
118{
119 return sprintf(buf, "%d\n", joystick);
120}
121
122static ssize_t ams_input_store_joystick(struct device *dev,
123 struct device_attribute *attr, const char *buf, size_t count)
124{
125 if (sscanf(buf, "%d\n", &joystick) != 1)
126 return -EINVAL;
127
128 mutex_lock(&ams_info.lock);
129
130 if (joystick)
131 ams_input_enable();
132 else
133 ams_input_disable();
134
135 mutex_unlock(&ams_info.lock);
136
137 return count;
138}
139
140static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
141 ams_input_show_joystick, ams_input_store_joystick);
142
143/* Call with ams_info.lock held! */
144int ams_input_init(void)
145{
146 int result;
147
148 result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
149
150 if (!result && joystick)
151 ams_input_enable();
152 return result;
153}
154
155/* Call with ams_info.lock held! */
156void ams_input_exit()
157{
158 ams_input_disable();
159 device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
160}