Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316068
b: refs/heads/master
c: d937ae5
h: refs/heads/master
v: v3
  • Loading branch information
David Herrmann authored and Jiri Kosina committed Jun 18, 2012
1 parent 4c573bf commit b3e6cdf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1f9dec1e0164b48da9b268a02197f38caa69b118
refs/heads/master: d937ae5fae17e63aaa97f029be221a6516b25475
46 changes: 45 additions & 1 deletion trunk/drivers/hid/uhid.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define UHID_BUFSIZE 32

struct uhid_device {
struct mutex devlock;
struct hid_device *hid;

wait_queue_head_t waitq;
Expand Down Expand Up @@ -81,6 +82,7 @@ static int uhid_char_open(struct inode *inode, struct file *file)
if (!uhid)
return -ENOMEM;

mutex_init(&uhid->devlock);
spin_lock_init(&uhid->qlock);
init_waitqueue_head(&uhid->waitq);

Expand All @@ -106,7 +108,49 @@ static int uhid_char_release(struct inode *inode, struct file *file)
static ssize_t uhid_char_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
return 0;
struct uhid_device *uhid = file->private_data;
int ret;
unsigned long flags;
size_t len;

/* they need at least the "type" member of uhid_event */
if (count < sizeof(__u32))
return -EINVAL;

try_again:
if (file->f_flags & O_NONBLOCK) {
if (uhid->head == uhid->tail)
return -EAGAIN;
} else {
ret = wait_event_interruptible(uhid->waitq,
uhid->head != uhid->tail);
if (ret)
return ret;
}

ret = mutex_lock_interruptible(&uhid->devlock);
if (ret)
return ret;

if (uhid->head == uhid->tail) {
mutex_unlock(&uhid->devlock);
goto try_again;
} else {
len = min(count, sizeof(**uhid->outq));
if (copy_to_user(buffer, &uhid->outq[uhid->tail], len)) {
ret = -EFAULT;
} else {
kfree(uhid->outq[uhid->tail]);
uhid->outq[uhid->tail] = NULL;

spin_lock_irqsave(&uhid->qlock, flags);
uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE;
spin_unlock_irqrestore(&uhid->qlock, flags);
}
}

mutex_unlock(&uhid->devlock);
return ret ? ret : len;
}

static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
Expand Down

0 comments on commit b3e6cdf

Please sign in to comment.