diff options
Diffstat (limited to 'drivers/hwmon/ams/ams-input.c')
-rw-r--r-- | drivers/hwmon/ams/ams-input.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c index 48dbf7d6a66d..8a712392cd38 100644 --- a/drivers/hwmon/ams/ams-input.c +++ b/drivers/hwmon/ams/ams-input.c | |||
@@ -27,6 +27,8 @@ static unsigned int invert; | |||
27 | module_param(invert, bool, S_IWUSR | S_IRUGO); | 27 | module_param(invert, bool, S_IWUSR | S_IRUGO); |
28 | MODULE_PARM_DESC(invert, "Invert input data on X and Y axis"); | 28 | MODULE_PARM_DESC(invert, "Invert input data on X and Y axis"); |
29 | 29 | ||
30 | static DEFINE_MUTEX(ams_input_mutex); | ||
31 | |||
30 | static void ams_idev_poll(struct input_polled_dev *dev) | 32 | static void ams_idev_poll(struct input_polled_dev *dev) |
31 | { | 33 | { |
32 | struct input_dev *idev = dev->input; | 34 | struct input_dev *idev = dev->input; |
@@ -50,13 +52,11 @@ static void ams_idev_poll(struct input_polled_dev *dev) | |||
50 | } | 52 | } |
51 | 53 | ||
52 | /* Call with ams_info.lock held! */ | 54 | /* Call with ams_info.lock held! */ |
53 | static void ams_input_enable(void) | 55 | static int ams_input_enable(void) |
54 | { | 56 | { |
55 | struct input_dev *input; | 57 | struct input_dev *input; |
56 | s8 x, y, z; | 58 | s8 x, y, z; |
57 | 59 | int error; | |
58 | if (ams_info.idev) | ||
59 | return; | ||
60 | 60 | ||
61 | ams_sensors(&x, &y, &z); | 61 | ams_sensors(&x, &y, &z); |
62 | ams_info.xcalib = x; | 62 | ams_info.xcalib = x; |
@@ -65,7 +65,7 @@ static void ams_input_enable(void) | |||
65 | 65 | ||
66 | ams_info.idev = input_allocate_polled_device(); | 66 | ams_info.idev = input_allocate_polled_device(); |
67 | if (!ams_info.idev) | 67 | if (!ams_info.idev) |
68 | return; | 68 | return -ENOMEM; |
69 | 69 | ||
70 | ams_info.idev->poll = ams_idev_poll; | 70 | ams_info.idev->poll = ams_idev_poll; |
71 | ams_info.idev->poll_interval = 25; | 71 | ams_info.idev->poll_interval = 25; |
@@ -84,14 +84,18 @@ static void ams_input_enable(void) | |||
84 | set_bit(EV_KEY, input->evbit); | 84 | set_bit(EV_KEY, input->evbit); |
85 | set_bit(BTN_TOUCH, input->keybit); | 85 | set_bit(BTN_TOUCH, input->keybit); |
86 | 86 | ||
87 | if (input_register_polled_device(ams_info.idev)) { | 87 | error = input_register_polled_device(ams_info.idev); |
88 | if (error) { | ||
88 | input_free_polled_device(ams_info.idev); | 89 | input_free_polled_device(ams_info.idev); |
89 | ams_info.idev = NULL; | 90 | ams_info.idev = NULL; |
90 | return; | 91 | return error; |
91 | } | 92 | } |
93 | |||
94 | joystick = 1; | ||
95 | |||
96 | return 0; | ||
92 | } | 97 | } |
93 | 98 | ||
94 | /* Call with ams_info.lock held! */ | ||
95 | static void ams_input_disable(void) | 99 | static void ams_input_disable(void) |
96 | { | 100 | { |
97 | if (ams_info.idev) { | 101 | if (ams_info.idev) { |
@@ -99,6 +103,8 @@ static void ams_input_disable(void) | |||
99 | input_free_polled_device(ams_info.idev); | 103 | input_free_polled_device(ams_info.idev); |
100 | ams_info.idev = NULL; | 104 | ams_info.idev = NULL; |
101 | } | 105 | } |
106 | |||
107 | joystick = 0; | ||
102 | } | 108 | } |
103 | 109 | ||
104 | static ssize_t ams_input_show_joystick(struct device *dev, | 110 | static ssize_t ams_input_show_joystick(struct device *dev, |
@@ -110,39 +116,42 @@ static ssize_t ams_input_show_joystick(struct device *dev, | |||
110 | static ssize_t ams_input_store_joystick(struct device *dev, | 116 | static ssize_t ams_input_store_joystick(struct device *dev, |
111 | struct device_attribute *attr, const char *buf, size_t count) | 117 | struct device_attribute *attr, const char *buf, size_t count) |
112 | { | 118 | { |
113 | if (sscanf(buf, "%d\n", &joystick) != 1) | 119 | unsigned long enable; |
120 | int error = 0; | ||
121 | |||
122 | if (strict_strtoul(buf, 0, &enable) || enable > 1) | ||
114 | return -EINVAL; | 123 | return -EINVAL; |
115 | 124 | ||
116 | mutex_lock(&ams_info.lock); | 125 | mutex_lock(&ams_input_mutex); |
117 | 126 | ||
118 | if (joystick) | 127 | if (enable != joystick) { |
119 | ams_input_enable(); | 128 | if (enable) |
120 | else | 129 | error = ams_input_enable(); |
121 | ams_input_disable(); | 130 | else |
131 | ams_input_disable(); | ||
132 | } | ||
122 | 133 | ||
123 | mutex_unlock(&ams_info.lock); | 134 | mutex_unlock(&ams_input_mutex); |
124 | 135 | ||
125 | return count; | 136 | return error ? error : count; |
126 | } | 137 | } |
127 | 138 | ||
128 | static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR, | 139 | static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR, |
129 | ams_input_show_joystick, ams_input_store_joystick); | 140 | ams_input_show_joystick, ams_input_store_joystick); |
130 | 141 | ||
131 | /* Call with ams_info.lock held! */ | ||
132 | int ams_input_init(void) | 142 | int ams_input_init(void) |
133 | { | 143 | { |
134 | int result; | 144 | if (joystick) |
135 | |||
136 | result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick); | ||
137 | |||
138 | if (!result && joystick) | ||
139 | ams_input_enable(); | 145 | ams_input_enable(); |
140 | return result; | 146 | |
147 | return device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick); | ||
141 | } | 148 | } |
142 | 149 | ||
143 | /* Call with ams_info.lock held! */ | ||
144 | void ams_input_exit(void) | 150 | void ams_input_exit(void) |
145 | { | 151 | { |
146 | ams_input_disable(); | ||
147 | device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick); | 152 | device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick); |
153 | |||
154 | mutex_lock(&ams_input_mutex); | ||
155 | ams_input_disable(); | ||
156 | mutex_unlock(&ams_input_mutex); | ||
148 | } | 157 | } |