2 * Raw serio device providing access to a raw byte stream from underlying
3 * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
5 * Copyright (c) 2004 Dmitry Torokhov
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
12 #include <linux/slab.h>
13 #include <linux/poll.h>
14 #include <linux/module.h>
15 #include <linux/serio.h>
16 #include <linux/init.h>
17 #include <linux/major.h>
18 #include <linux/device.h>
19 #include <linux/miscdevice.h>
20 #include <linux/wait.h>
21 #include <linux/mutex.h>
23 #define DRIVER_DESC "Raw serio driver"
25 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
26 MODULE_DESCRIPTION(DRIVER_DESC
);
27 MODULE_LICENSE("GPL");
29 #define SERIO_RAW_QUEUE_LEN 64
31 unsigned char queue
[SERIO_RAW_QUEUE_LEN
];
32 unsigned int tail
, head
;
37 struct miscdevice dev
;
38 wait_queue_head_t wait
;
39 struct list_head list
;
40 struct list_head node
;
43 struct serio_raw_list
{
44 struct fasync_struct
*fasync
;
45 struct serio_raw
*serio_raw
;
46 struct list_head node
;
49 static DEFINE_MUTEX(serio_raw_mutex
);
50 static LIST_HEAD(serio_raw_list
);
51 static unsigned int serio_raw_no
;
53 /*********************************************************************
54 * Interface with userspace (file operations) *
55 *********************************************************************/
57 static int serio_raw_fasync(int fd
, struct file
*file
, int on
)
59 struct serio_raw_list
*list
= file
->private_data
;
62 retval
= fasync_helper(fd
, file
, on
, &list
->fasync
);
63 return retval
< 0 ? retval
: 0;
66 static struct serio_raw
*serio_raw_locate(int minor
)
68 struct serio_raw
*serio_raw
;
70 list_for_each_entry(serio_raw
, &serio_raw_list
, node
) {
71 if (serio_raw
->dev
.minor
== minor
)
78 static int serio_raw_open(struct inode
*inode
, struct file
*file
)
80 struct serio_raw
*serio_raw
;
81 struct serio_raw_list
*list
;
84 retval
= mutex_lock_interruptible(&serio_raw_mutex
);
88 if (!(serio_raw
= serio_raw_locate(iminor(inode
)))) {
93 if (!serio_raw
->serio
) {
98 if (!(list
= kzalloc(sizeof(struct serio_raw_list
), GFP_KERNEL
))) {
103 list
->serio_raw
= serio_raw
;
104 file
->private_data
= list
;
107 list_add_tail(&list
->node
, &serio_raw
->list
);
110 mutex_unlock(&serio_raw_mutex
);
114 static int serio_raw_cleanup(struct serio_raw
*serio_raw
)
116 if (--serio_raw
->refcnt
== 0) {
117 misc_deregister(&serio_raw
->dev
);
118 list_del_init(&serio_raw
->node
);
127 static int serio_raw_release(struct inode
*inode
, struct file
*file
)
129 struct serio_raw_list
*list
= file
->private_data
;
130 struct serio_raw
*serio_raw
= list
->serio_raw
;
132 mutex_lock(&serio_raw_mutex
);
134 serio_raw_fasync(-1, file
, 0);
135 serio_raw_cleanup(serio_raw
);
137 mutex_unlock(&serio_raw_mutex
);
141 static int serio_raw_fetch_byte(struct serio_raw
*serio_raw
, char *c
)
146 spin_lock_irqsave(&serio_raw
->serio
->lock
, flags
);
148 empty
= serio_raw
->head
== serio_raw
->tail
;
150 *c
= serio_raw
->queue
[serio_raw
->tail
];
151 serio_raw
->tail
= (serio_raw
->tail
+ 1) % SERIO_RAW_QUEUE_LEN
;
154 spin_unlock_irqrestore(&serio_raw
->serio
->lock
, flags
);
159 static ssize_t
serio_raw_read(struct file
*file
, char __user
*buffer
, size_t count
, loff_t
*ppos
)
161 struct serio_raw_list
*list
= file
->private_data
;
162 struct serio_raw
*serio_raw
= list
->serio_raw
;
163 char uninitialized_var(c
);
166 if (!serio_raw
->serio
)
169 if (serio_raw
->head
== serio_raw
->tail
&& (file
->f_flags
& O_NONBLOCK
))
172 retval
= wait_event_interruptible(list
->serio_raw
->wait
,
173 serio_raw
->head
!= serio_raw
->tail
|| !serio_raw
->serio
);
177 if (!serio_raw
->serio
)
180 while (retval
< count
&& serio_raw_fetch_byte(serio_raw
, &c
)) {
181 if (put_user(c
, buffer
++))
189 static ssize_t
serio_raw_write(struct file
*file
, const char __user
*buffer
, size_t count
, loff_t
*ppos
)
191 struct serio_raw_list
*list
= file
->private_data
;
196 retval
= mutex_lock_interruptible(&serio_raw_mutex
);
200 if (!list
->serio_raw
->serio
) {
209 if (get_user(c
, buffer
++)) {
213 if (serio_write(list
->serio_raw
->serio
, c
)) {
221 mutex_unlock(&serio_raw_mutex
);
225 static unsigned int serio_raw_poll(struct file
*file
, poll_table
*wait
)
227 struct serio_raw_list
*list
= file
->private_data
;
229 poll_wait(file
, &list
->serio_raw
->wait
, wait
);
231 if (list
->serio_raw
->head
!= list
->serio_raw
->tail
)
232 return POLLIN
| POLLRDNORM
;
237 static const struct file_operations serio_raw_fops
= {
238 .owner
= THIS_MODULE
,
239 .open
= serio_raw_open
,
240 .release
= serio_raw_release
,
241 .read
= serio_raw_read
,
242 .write
= serio_raw_write
,
243 .poll
= serio_raw_poll
,
244 .fasync
= serio_raw_fasync
,
248 /*********************************************************************
249 * Interface with serio port *
250 *********************************************************************/
252 static irqreturn_t
serio_raw_interrupt(struct serio
*serio
, unsigned char data
,
255 struct serio_raw
*serio_raw
= serio_get_drvdata(serio
);
256 struct serio_raw_list
*list
;
257 unsigned int head
= serio_raw
->head
;
259 /* we are holding serio->lock here so we are prootected */
260 serio_raw
->queue
[head
] = data
;
261 head
= (head
+ 1) % SERIO_RAW_QUEUE_LEN
;
262 if (likely(head
!= serio_raw
->tail
)) {
263 serio_raw
->head
= head
;
264 list_for_each_entry(list
, &serio_raw
->list
, node
)
265 kill_fasync(&list
->fasync
, SIGIO
, POLL_IN
);
266 wake_up_interruptible(&serio_raw
->wait
);
272 static int serio_raw_connect(struct serio
*serio
, struct serio_driver
*drv
)
274 struct serio_raw
*serio_raw
;
277 if (!(serio_raw
= kzalloc(sizeof(struct serio_raw
), GFP_KERNEL
))) {
278 printk(KERN_ERR
"serio_raw.c: can't allocate memory for a device\n");
282 mutex_lock(&serio_raw_mutex
);
284 snprintf(serio_raw
->name
, sizeof(serio_raw
->name
), "serio_raw%d", serio_raw_no
++);
285 serio_raw
->refcnt
= 1;
286 serio_raw
->serio
= serio
;
287 INIT_LIST_HEAD(&serio_raw
->list
);
288 init_waitqueue_head(&serio_raw
->wait
);
290 serio_set_drvdata(serio
, serio_raw
);
292 err
= serio_open(serio
, drv
);
296 list_add_tail(&serio_raw
->node
, &serio_raw_list
);
298 serio_raw
->dev
.minor
= PSMOUSE_MINOR
;
299 serio_raw
->dev
.name
= serio_raw
->name
;
300 serio_raw
->dev
.parent
= &serio
->dev
;
301 serio_raw
->dev
.fops
= &serio_raw_fops
;
303 err
= misc_register(&serio_raw
->dev
);
305 serio_raw
->dev
.minor
= MISC_DYNAMIC_MINOR
;
306 err
= misc_register(&serio_raw
->dev
);
310 printk(KERN_INFO
"serio_raw: failed to register raw access device for %s\n",
315 printk(KERN_INFO
"serio_raw: raw access enabled on %s (%s, minor %d)\n",
316 serio
->phys
, serio_raw
->name
, serio_raw
->dev
.minor
);
321 list_del_init(&serio_raw
->node
);
323 serio_set_drvdata(serio
, NULL
);
326 mutex_unlock(&serio_raw_mutex
);
330 static int serio_raw_reconnect(struct serio
*serio
)
332 struct serio_raw
*serio_raw
= serio_get_drvdata(serio
);
333 struct serio_driver
*drv
= serio
->drv
;
335 if (!drv
|| !serio_raw
) {
336 printk(KERN_DEBUG
"serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
341 * Nothing needs to be done here, we just need this method to
342 * keep the same device.
347 static void serio_raw_disconnect(struct serio
*serio
)
349 struct serio_raw
*serio_raw
;
351 mutex_lock(&serio_raw_mutex
);
353 serio_raw
= serio_get_drvdata(serio
);
356 serio_set_drvdata(serio
, NULL
);
358 serio_raw
->serio
= NULL
;
359 if (!serio_raw_cleanup(serio_raw
))
360 wake_up_interruptible(&serio_raw
->wait
);
362 mutex_unlock(&serio_raw_mutex
);
365 static struct serio_device_id serio_raw_serio_ids
[] = {
375 MODULE_DEVICE_TABLE(serio
, serio_raw_serio_ids
);
377 static struct serio_driver serio_raw_drv
= {
381 .description
= DRIVER_DESC
,
382 .id_table
= serio_raw_serio_ids
,
383 .interrupt
= serio_raw_interrupt
,
384 .connect
= serio_raw_connect
,
385 .reconnect
= serio_raw_reconnect
,
386 .disconnect
= serio_raw_disconnect
,
390 static int __init
serio_raw_init(void)
392 return serio_register_driver(&serio_raw_drv
);
395 static void __exit
serio_raw_exit(void)
397 serio_unregister_driver(&serio_raw_drv
);
400 module_init(serio_raw_init
);
401 module_exit(serio_raw_exit
);