aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tsdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tsdev.c')
-rw-r--r--drivers/input/tsdev.c110
1 files changed, 59 insertions, 51 deletions
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index a23aedc64ab1..fbef35d2d76c 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -111,13 +111,13 @@ struct tsdev {
111 int minor; 111 int minor;
112 char name[8]; 112 char name[8];
113 wait_queue_head_t wait; 113 wait_queue_head_t wait;
114 struct list_head list; 114 struct list_head client_list;
115 struct input_handle handle; 115 struct input_handle handle;
116 int x, y, pressure; 116 int x, y, pressure;
117 struct ts_calibration cal; 117 struct ts_calibration cal;
118}; 118};
119 119
120struct tsdev_list { 120struct tsdev_client {
121 struct fasync_struct *fasync; 121 struct fasync_struct *fasync;
122 struct list_head node; 122 struct list_head node;
123 struct tsdev *tsdev; 123 struct tsdev *tsdev;
@@ -139,17 +139,18 @@ static struct tsdev *tsdev_table[TSDEV_MINORS/2];
139 139
140static int tsdev_fasync(int fd, struct file *file, int on) 140static int tsdev_fasync(int fd, struct file *file, int on)
141{ 141{
142 struct tsdev_list *list = file->private_data; 142 struct tsdev_client *client = file->private_data;
143 int retval; 143 int retval;
144 144
145 retval = fasync_helper(fd, file, on, &list->fasync); 145 retval = fasync_helper(fd, file, on, &client->fasync);
146 return retval < 0 ? retval : 0; 146 return retval < 0 ? retval : 0;
147} 147}
148 148
149static int tsdev_open(struct inode *inode, struct file *file) 149static int tsdev_open(struct inode *inode, struct file *file)
150{ 150{
151 int i = iminor(inode) - TSDEV_MINOR_BASE; 151 int i = iminor(inode) - TSDEV_MINOR_BASE;
152 struct tsdev_list *list; 152 struct tsdev_client *client;
153 struct tsdev *tsdev;
153 154
154 printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " 155 printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
155 "for removal.\nSee Documentation/feature-removal-schedule.txt " 156 "for removal.\nSee Documentation/feature-removal-schedule.txt "
@@ -158,19 +159,22 @@ static int tsdev_open(struct inode *inode, struct file *file)
158 if (i >= TSDEV_MINORS) 159 if (i >= TSDEV_MINORS)
159 return -ENODEV; 160 return -ENODEV;
160 161
161 if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) 162 tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
163 if (!tsdev || !tsdev->exist)
164 return -ENODEV;
165
166 client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
167 if (!client)
162 return -ENOMEM; 168 return -ENOMEM;
163 169
164 list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; 170 client->tsdev = tsdev;
171 client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
172 list_add_tail(&client->node, &tsdev->client_list);
165 173
166 i &= TSDEV_MINOR_MASK; 174 if (!tsdev->open++ && tsdev->exist)
167 list->tsdev = tsdev_table[i]; 175 input_open_device(&tsdev->handle);
168 list_add_tail(&list->node, &tsdev_table[i]->list);
169 file->private_data = list;
170 176
171 if (!list->tsdev->open++) 177 file->private_data = client;
172 if (list->tsdev->exist)
173 input_open_device(&list->tsdev->handle);
174 return 0; 178 return 0;
175} 179}
176 180
@@ -182,45 +186,48 @@ static void tsdev_free(struct tsdev *tsdev)
182 186
183static int tsdev_release(struct inode *inode, struct file *file) 187static int tsdev_release(struct inode *inode, struct file *file)
184{ 188{
185 struct tsdev_list *list = file->private_data; 189 struct tsdev_client *client = file->private_data;
190 struct tsdev *tsdev = client->tsdev;
186 191
187 tsdev_fasync(-1, file, 0); 192 tsdev_fasync(-1, file, 0);
188 list_del(&list->node);
189 193
190 if (!--list->tsdev->open) { 194 list_del(&client->node);
191 if (list->tsdev->exist) 195 kfree(client);
192 input_close_device(&list->tsdev->handle); 196
197 if (!--tsdev->open) {
198 if (tsdev->exist)
199 input_close_device(&tsdev->handle);
193 else 200 else
194 tsdev_free(list->tsdev); 201 tsdev_free(tsdev);
195 } 202 }
196 kfree(list); 203
197 return 0; 204 return 0;
198} 205}
199 206
200static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, 207static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
201 loff_t * ppos) 208 loff_t *ppos)
202{ 209{
203 struct tsdev_list *list = file->private_data; 210 struct tsdev_client *client = file->private_data;
211 struct tsdev *tsdev = client->tsdev;
204 int retval = 0; 212 int retval = 0;
205 213
206 if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK)) 214 if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
207 return -EAGAIN; 215 return -EAGAIN;
208 216
209 retval = wait_event_interruptible(list->tsdev->wait, 217 retval = wait_event_interruptible(tsdev->wait,
210 list->head != list->tail || !list->tsdev->exist); 218 client->head != client->tail || !tsdev->exist);
211
212 if (retval) 219 if (retval)
213 return retval; 220 return retval;
214 221
215 if (!list->tsdev->exist) 222 if (!tsdev->exist)
216 return -ENODEV; 223 return -ENODEV;
217 224
218 while (list->head != list->tail && 225 while (client->head != client->tail &&
219 retval + sizeof (struct ts_event) <= count) { 226 retval + sizeof (struct ts_event) <= count) {
220 if (copy_to_user (buffer + retval, list->event + list->tail, 227 if (copy_to_user (buffer + retval, client->event + client->tail,
221 sizeof (struct ts_event))) 228 sizeof (struct ts_event)))
222 return -EFAULT; 229 return -EFAULT;
223 list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); 230 client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
224 retval += sizeof (struct ts_event); 231 retval += sizeof (struct ts_event);
225 } 232 }
226 233
@@ -228,20 +235,21 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
228} 235}
229 236
230/* No kernel lock - fine */ 237/* No kernel lock - fine */
231static unsigned int tsdev_poll(struct file *file, poll_table * wait) 238static unsigned int tsdev_poll(struct file *file, poll_table *wait)
232{ 239{
233 struct tsdev_list *list = file->private_data; 240 struct tsdev_client *client = file->private_data;
241 struct tsdev *tsdev = client->tsdev;
234 242
235 poll_wait(file, &list->tsdev->wait, wait); 243 poll_wait(file, &tsdev->wait, wait);
236 return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | 244 return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
237 (list->tsdev->exist ? 0 : (POLLHUP | POLLERR)); 245 (tsdev->exist ? 0 : (POLLHUP | POLLERR));
238} 246}
239 247
240static int tsdev_ioctl(struct inode *inode, struct file *file, 248static int tsdev_ioctl(struct inode *inode, struct file *file,
241 unsigned int cmd, unsigned long arg) 249 unsigned int cmd, unsigned long arg)
242{ 250{
243 struct tsdev_list *list = file->private_data; 251 struct tsdev_client *client = file->private_data;
244 struct tsdev *tsdev = list->tsdev; 252 struct tsdev *tsdev = client->tsdev;
245 int retval = 0; 253 int retval = 0;
246 254
247 switch (cmd) { 255 switch (cmd) {
@@ -279,7 +287,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
279 unsigned int code, int value) 287 unsigned int code, int value)
280{ 288{
281 struct tsdev *tsdev = handle->private; 289 struct tsdev *tsdev = handle->private;
282 struct tsdev_list *list; 290 struct tsdev_client *client;
283 struct timeval time; 291 struct timeval time;
284 292
285 switch (type) { 293 switch (type) {
@@ -343,18 +351,18 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
343 if (type != EV_SYN || code != SYN_REPORT) 351 if (type != EV_SYN || code != SYN_REPORT)
344 return; 352 return;
345 353
346 list_for_each_entry(list, &tsdev->list, node) { 354 list_for_each_entry(client, &tsdev->client_list, node) {
347 int x, y, tmp; 355 int x, y, tmp;
348 356
349 do_gettimeofday(&time); 357 do_gettimeofday(&time);
350 list->event[list->head].millisecs = time.tv_usec / 100; 358 client->event[client->head].millisecs = time.tv_usec / 100;
351 list->event[list->head].pressure = tsdev->pressure; 359 client->event[client->head].pressure = tsdev->pressure;
352 360
353 x = tsdev->x; 361 x = tsdev->x;
354 y = tsdev->y; 362 y = tsdev->y;
355 363
356 /* Calibration */ 364 /* Calibration */
357 if (!list->raw) { 365 if (!client->raw) {
358 x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; 366 x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
359 y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; 367 y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
360 if (tsdev->cal.xyswap) { 368 if (tsdev->cal.xyswap) {
@@ -362,10 +370,10 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
362 } 370 }
363 } 371 }
364 372
365 list->event[list->head].x = x; 373 client->event[client->head].x = x;
366 list->event[list->head].y = y; 374 client->event[client->head].y = y;
367 list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); 375 client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
368 kill_fasync(&list->fasync, SIGIO, POLL_IN); 376 kill_fasync(&client->fasync, SIGIO, POLL_IN);
369 } 377 }
370 wake_up_interruptible(&tsdev->wait); 378 wake_up_interruptible(&tsdev->wait);
371} 379}
@@ -390,7 +398,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
390 if (!tsdev) 398 if (!tsdev)
391 return -ENOMEM; 399 return -ENOMEM;
392 400
393 INIT_LIST_HEAD(&tsdev->list); 401 INIT_LIST_HEAD(&tsdev->client_list);
394 init_waitqueue_head(&tsdev->wait); 402 init_waitqueue_head(&tsdev->wait);
395 403
396 sprintf(tsdev->name, "ts%d", minor); 404 sprintf(tsdev->name, "ts%d", minor);
@@ -451,7 +459,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
451static void tsdev_disconnect(struct input_handle *handle) 459static void tsdev_disconnect(struct input_handle *handle)
452{ 460{
453 struct tsdev *tsdev = handle->private; 461 struct tsdev *tsdev = handle->private;
454 struct tsdev_list *list; 462 struct tsdev_client *client;
455 463
456 input_unregister_handle(handle); 464 input_unregister_handle(handle);
457 465
@@ -463,8 +471,8 @@ static void tsdev_disconnect(struct input_handle *handle)
463 if (tsdev->open) { 471 if (tsdev->open) {
464 input_close_device(handle); 472 input_close_device(handle);
465 wake_up_interruptible(&tsdev->wait); 473 wake_up_interruptible(&tsdev->wait);
466 list_for_each_entry(list, &tsdev->list, node) 474 list_for_each_entry(client, &tsdev->client_list, node)
467 kill_fasync(&list->fasync, SIGIO, POLL_HUP); 475 kill_fasync(&client->fasync, SIGIO, POLL_HUP);
468 } else 476 } else
469 tsdev_free(tsdev); 477 tsdev_free(tsdev);
470} 478}