Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316066
b: refs/heads/master
c: ace3d86
h: refs/heads/master
v: v3
  • Loading branch information
David Herrmann authored and Jiri Kosina committed Jun 18, 2012
1 parent 51d7532 commit c8a43a1
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1ccd7a2a33f2b47e46c51f4501e9623a51d28090
refs/heads/master: ace3d8614ab0e6544f5f85921085b55b915fe9aa
65 changes: 65 additions & 0 deletions trunk/drivers/hid/uhid.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,81 @@
#include <linux/wait.h>

#define UHID_NAME "uhid"
#define UHID_BUFSIZE 32

struct uhid_device {
struct hid_device *hid;

wait_queue_head_t waitq;
spinlock_t qlock;
__u8 head;
__u8 tail;
struct uhid_event *outq[UHID_BUFSIZE];
};

static struct miscdevice uhid_misc;

static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
{
__u8 newhead;

newhead = (uhid->head + 1) % UHID_BUFSIZE;

if (newhead != uhid->tail) {
uhid->outq[uhid->head] = ev;
uhid->head = newhead;
wake_up_interruptible(&uhid->waitq);
} else {
hid_warn(uhid->hid, "Output queue is full\n");
kfree(ev);
}
}

static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
{
unsigned long flags;
struct uhid_event *ev;

ev = kzalloc(sizeof(*ev), GFP_KERNEL);
if (!ev)
return -ENOMEM;

ev->type = event;

spin_lock_irqsave(&uhid->qlock, flags);
uhid_queue(uhid, ev);
spin_unlock_irqrestore(&uhid->qlock, flags);

return 0;
}

static int uhid_char_open(struct inode *inode, struct file *file)
{
struct uhid_device *uhid;

uhid = kzalloc(sizeof(*uhid), GFP_KERNEL);
if (!uhid)
return -ENOMEM;

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

file->private_data = uhid;
nonseekable_open(inode, file);

return 0;
}

static int uhid_char_release(struct inode *inode, struct file *file)
{
struct uhid_device *uhid = file->private_data;
unsigned int i;

for (i = 0; i < UHID_BUFSIZE; ++i)
kfree(uhid->outq[i]);

kfree(uhid);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ header-y += tty.h
header-y += types.h
header-y += udf_fs_i.h
header-y += udp.h
header-y += uhid.h
header-y += uinput.h
header-y += uio.h
header-y += ultrasound.h
Expand Down
33 changes: 33 additions & 0 deletions trunk/include/linux/uhid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef __UHID_H_
#define __UHID_H_

/*
* User-space I/O driver support for HID subsystem
* Copyright (c) 2012 David Herrmann
*/

/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/

/*
* Public header for user-space communication. We try to keep every structure
* aligned but to be safe we also use __attribute__((__packed__)). Therefore,
* the communication should be ABI compatible even between architectures.
*/

#include <linux/input.h>
#include <linux/types.h>

enum uhid_event_type {
UHID_DUMMY,
};

struct uhid_event {
__u32 type;
} __attribute__((__packed__));

#endif /* __UHID_H_ */

0 comments on commit c8a43a1

Please sign in to comment.