mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
Merge branch 'hidraw' into for-linus
This commit is contained in:
commit
d057fd4cb8
7 changed files with 565 additions and 2 deletions
|
@ -46,6 +46,25 @@ config HID_DEBUG
|
|||
|
||||
If unsure, say N
|
||||
|
||||
config HIDRAW
|
||||
bool "/dev/hidraw raw HID device support"
|
||||
depends on HID
|
||||
---help---
|
||||
Say Y here if you want to support HID devices (from the USB
|
||||
specification standpoint) that aren't strictly user interface
|
||||
devices, like monitor controls and Uninterruptable Power Supplies.
|
||||
|
||||
This module supports these devices separately using a separate
|
||||
event interface on /dev/hidraw.
|
||||
|
||||
There is also a /dev/hiddev configuration option in the USB HID
|
||||
configuration menu. In comparison to hiddev, this device does not process
|
||||
the hid events at all (no parsing, no lookups). This lets applications
|
||||
to work on raw hid events when they want to, and avoid using transport-specific
|
||||
userspace libhid/libusb libraries.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
source "drivers/hid/usbhid/Kconfig"
|
||||
|
||||
endif # HID_SUPPORT
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
hid-objs := hid-core.o hid-input.o
|
||||
|
||||
obj-$(CONFIG_HID) += hid.o
|
||||
|
||||
hid-$(CONFIG_HID_DEBUG) += hid-debug.o
|
||||
hid-$(CONFIG_HIDRAW) += hidraw.o
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid/
|
||||
obj-$(CONFIG_USB_MOUSE) += usbhid/
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/hid.h>
|
||||
#include <linux/hiddev.h>
|
||||
#include <linux/hid-debug.h>
|
||||
#include <linux/hidraw.h>
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
|
@ -979,6 +980,8 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
|||
|
||||
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
|
||||
hid->hiddev_report_event(hid, report);
|
||||
if (hid->claimed & HID_CLAIMED_HIDRAW)
|
||||
hidraw_report_event(hid, data, size);
|
||||
|
||||
for (n = 0; n < report->maxfield; n++)
|
||||
hid_input_field(hid, report->field[n], data, interrupt);
|
||||
|
@ -990,5 +993,18 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(hid_input_report);
|
||||
|
||||
static int __init hid_init(void)
|
||||
{
|
||||
return hidraw_init();
|
||||
}
|
||||
|
||||
static void __exit hid_exit(void)
|
||||
{
|
||||
hidraw_exit();
|
||||
}
|
||||
|
||||
module_init(hid_init);
|
||||
module_exit(hid_exit);
|
||||
|
||||
MODULE_LICENSE(DRIVER_LICENSE);
|
||||
|
||||
|
|
401
drivers/hid/hidraw.c
Normal file
401
drivers/hid/hidraw.c
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* HID raw devices, giving access to raw HID events.
|
||||
*
|
||||
* In comparison to hiddev, this device does not process the
|
||||
* hid events at all (no parsing, no lookups). This lets applications
|
||||
* to work on raw hid events as they want to, and avoids a need to
|
||||
* use a transport-specific userspace libhid/libusb libraries.
|
||||
*
|
||||
* Copyright (c) 2007 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/hidraw.h>
|
||||
|
||||
static int hidraw_major;
|
||||
static struct cdev hidraw_cdev;
|
||||
static struct class *hidraw_class;
|
||||
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
|
||||
static DEFINE_SPINLOCK(minors_lock);
|
||||
|
||||
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hidraw_list *list = file->private_data;
|
||||
int ret = 0, len;
|
||||
char *report;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
while (ret == 0) {
|
||||
|
||||
mutex_lock(&list->read_mutex);
|
||||
|
||||
if (list->head == list->tail) {
|
||||
add_wait_queue(&list->hidraw->wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
while (list->head == list->tail) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (!list->hidraw->exist) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* allow O_NONBLOCK to work well from other threads */
|
||||
mutex_unlock(&list->read_mutex);
|
||||
schedule();
|
||||
mutex_lock(&list->read_mutex);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&list->hidraw->wait, &wait);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
report = list->buffer[list->tail].value;
|
||||
len = list->buffer[list->tail].len > count ?
|
||||
count : list->buffer[list->tail].len;
|
||||
|
||||
if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
ret += len;
|
||||
|
||||
kfree(list->buffer[list->tail].value);
|
||||
list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&list->read_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* the first byte is expected to be a report number */
|
||||
static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned int minor = iminor(file->f_path.dentry->d_inode);
|
||||
struct hid_device *dev = hidraw_table[minor]->hid;
|
||||
__u8 *buf;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev->hid_output_raw_report)
|
||||
return -ENODEV;
|
||||
|
||||
if (count > HID_MIN_BUFFER_SIZE) {
|
||||
printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
|
||||
current->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count < 2) {
|
||||
printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
|
||||
current->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(buf, buffer, count)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = dev->hid_output_raw_report(dev, buf, count);
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int hidraw_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct hidraw_list *list = file->private_data;
|
||||
|
||||
poll_wait(file, &list->hidraw->wait, wait);
|
||||
if (list->head != list->tail)
|
||||
return POLLIN | POLLRDNORM;
|
||||
if (!list->hidraw->exist)
|
||||
return POLLERR | POLLHUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hidraw_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned int minor = iminor(inode);
|
||||
struct hidraw *dev;
|
||||
struct hidraw_list *list;
|
||||
int err = 0;
|
||||
|
||||
if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock(&minors_lock);
|
||||
if (!hidraw_table[minor]) {
|
||||
printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
|
||||
minor);
|
||||
kfree(list);
|
||||
err = -ENODEV;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
list->hidraw = hidraw_table[minor];
|
||||
mutex_init(&list->read_mutex);
|
||||
list_add_tail(&list->node, &hidraw_table[minor]->list);
|
||||
file->private_data = list;
|
||||
|
||||
dev = hidraw_table[minor];
|
||||
if (!dev->open++)
|
||||
dev->hid->hid_open(dev->hid);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&minors_lock);
|
||||
out:
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static int hidraw_release(struct inode * inode, struct file * file)
|
||||
{
|
||||
unsigned int minor = iminor(inode);
|
||||
struct hidraw *dev;
|
||||
struct hidraw_list *list = file->private_data;
|
||||
|
||||
if (!hidraw_table[minor]) {
|
||||
printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
|
||||
minor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
list_del(&list->node);
|
||||
dev = hidraw_table[minor];
|
||||
if (!dev->open--) {
|
||||
if (list->hidraw->exist)
|
||||
dev->hid->hid_close(dev->hid);
|
||||
else
|
||||
kfree(list->hidraw);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int minor = iminor(inode);
|
||||
struct hidraw *dev = hidraw_table[minor];
|
||||
void __user *user_arg = (void __user*) arg;
|
||||
|
||||
switch (cmd) {
|
||||
case HIDIOCGRDESCSIZE:
|
||||
if (put_user(dev->hid->rsize, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case HIDIOCGRDESC:
|
||||
{
|
||||
__u32 len;
|
||||
|
||||
if (get_user(len, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
if (copy_to_user(*((__u8 **)(user_arg +
|
||||
sizeof(__u32))),
|
||||
dev->hid->rdesc, len))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case HIDIOCGRAWINFO:
|
||||
{
|
||||
struct hidraw_devinfo dinfo;
|
||||
|
||||
dinfo.bustype = dev->hid->bus;
|
||||
dinfo.vendor = dev->hid->vendor;
|
||||
dinfo.product = dev->hid->product;
|
||||
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
|
||||
cmd);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct file_operations hidraw_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = hidraw_read,
|
||||
.write = hidraw_write,
|
||||
.poll = hidraw_poll,
|
||||
.open = hidraw_open,
|
||||
.release = hidraw_release,
|
||||
.ioctl = hidraw_ioctl,
|
||||
};
|
||||
|
||||
void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
|
||||
{
|
||||
struct hidraw *dev = hid->hidraw;
|
||||
struct hidraw_list *list;
|
||||
|
||||
list_for_each_entry(list, &dev->list, node) {
|
||||
list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
|
||||
list->buffer[list->head].len = len;
|
||||
list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
|
||||
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
||||
}
|
||||
|
||||
wake_up_interruptible(&dev->wait);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hidraw_report_event);
|
||||
|
||||
int hidraw_connect(struct hid_device *hid)
|
||||
{
|
||||
int minor, result;
|
||||
struct hidraw *dev;
|
||||
|
||||
/* TODO currently we accept any HID device. This should later
|
||||
* probably be fixed to accept only those devices which provide
|
||||
* non-input applications
|
||||
*/
|
||||
|
||||
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
result = -EINVAL;
|
||||
|
||||
spin_lock(&minors_lock);
|
||||
|
||||
for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
|
||||
if (hidraw_table[minor])
|
||||
continue;
|
||||
hidraw_table[minor] = dev;
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&minors_lock);
|
||||
|
||||
if (result) {
|
||||
kfree(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
|
||||
"%s%d", "hidraw", minor);
|
||||
|
||||
if (IS_ERR(dev->dev)) {
|
||||
spin_lock(&minors_lock);
|
||||
hidraw_table[minor] = NULL;
|
||||
spin_unlock(&minors_lock);
|
||||
result = PTR_ERR(dev->dev);
|
||||
kfree(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&dev->wait);
|
||||
INIT_LIST_HEAD(&dev->list);
|
||||
|
||||
dev->hid = hid;
|
||||
dev->minor = minor;
|
||||
|
||||
dev->exist = 1;
|
||||
hid->hidraw = dev;
|
||||
|
||||
out:
|
||||
return result;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hidraw_connect);
|
||||
|
||||
void hidraw_disconnect(struct hid_device *hid)
|
||||
{
|
||||
struct hidraw *hidraw = hid->hidraw;
|
||||
|
||||
hidraw->exist = 0;
|
||||
|
||||
spin_lock(&minors_lock);
|
||||
hidraw_table[hidraw->minor] = NULL;
|
||||
spin_unlock(&minors_lock);
|
||||
|
||||
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
|
||||
|
||||
if (hidraw->open) {
|
||||
hid->hid_close(hid);
|
||||
wake_up_interruptible(&hidraw->wait);
|
||||
} else {
|
||||
kfree(hidraw);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hidraw_disconnect);
|
||||
|
||||
int __init hidraw_init(void)
|
||||
{
|
||||
int result;
|
||||
dev_t dev_id;
|
||||
|
||||
result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
|
||||
HIDRAW_MAX_DEVICES, "hidraw");
|
||||
|
||||
hidraw_major = MAJOR(dev_id);
|
||||
|
||||
if (result < 0) {
|
||||
printk(KERN_WARNING "hidraw: can't get major number\n");
|
||||
result = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hidraw_class = class_create(THIS_MODULE, "hidraw");
|
||||
if (IS_ERR(hidraw_class)) {
|
||||
result = PTR_ERR(hidraw_class);
|
||||
unregister_chrdev(hidraw_major, "hidraw");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cdev_init(&hidraw_cdev, &hidraw_ops);
|
||||
cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
void __exit hidraw_exit(void)
|
||||
{
|
||||
dev_t dev_id = MKDEV(hidraw_major, 0);
|
||||
|
||||
cdev_del(&hidraw_cdev);
|
||||
class_destroy(hidraw_class);
|
||||
unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/hid.h>
|
||||
#include <linux/hiddev.h>
|
||||
#include <linux/hid-debug.h>
|
||||
#include <linux/hidraw.h>
|
||||
#include "usbhid.h"
|
||||
|
||||
/*
|
||||
|
@ -639,6 +640,28 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
struct usb_device *dev = hid_to_usb_dev(hid);
|
||||
struct usb_interface *intf = usbhid->intf;
|
||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
HID_REQ_SET_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
cpu_to_le16(((HID_OUTPUT_REPORT + 1) << 8) | *buf),
|
||||
interface->desc.bInterfaceNumber, buf + 1, count - 1,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
/* count also the report id */
|
||||
if (ret > 0)
|
||||
ret++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
@ -882,6 +905,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
|||
hid->hiddev_hid_event = hiddev_hid_event;
|
||||
hid->hiddev_report_event = hiddev_report_event;
|
||||
#endif
|
||||
hid->hid_output_raw_report = usbhid_output_raw_report;
|
||||
return hid;
|
||||
|
||||
fail:
|
||||
|
@ -920,6 +944,8 @@ static void hid_disconnect(struct usb_interface *intf)
|
|||
hidinput_disconnect(hid);
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV)
|
||||
hiddev_disconnect(hid);
|
||||
if (hid->claimed & HID_CLAIMED_HIDRAW)
|
||||
hidraw_disconnect(hid);
|
||||
|
||||
usb_free_urb(usbhid->urbin);
|
||||
usb_free_urb(usbhid->urbctrl);
|
||||
|
@ -952,11 +978,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
hid->claimed |= HID_CLAIMED_INPUT;
|
||||
if (!hiddev_connect(hid))
|
||||
hid->claimed |= HID_CLAIMED_HIDDEV;
|
||||
if (!hidraw_connect(hid))
|
||||
hid->claimed |= HID_CLAIMED_HIDRAW;
|
||||
|
||||
usb_set_intfdata(intf, hid);
|
||||
|
||||
if (!hid->claimed) {
|
||||
printk ("HID device not claimed by input or hiddev\n");
|
||||
printk ("HID device claimed by neither input, hiddev nor hidraw\n");
|
||||
hid_disconnect(intf);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -972,10 +1000,16 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
|
||||
if (hid->claimed & HID_CLAIMED_INPUT)
|
||||
printk("input");
|
||||
if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
|
||||
if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
|
||||
hid->claimed & HID_CLAIMED_HIDRAW))
|
||||
printk(",");
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV)
|
||||
printk("hiddev%d", hid->minor);
|
||||
if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
|
||||
(hid->claimed & HID_CLAIMED_HIDRAW))
|
||||
printk(",");
|
||||
if (hid->claimed & HID_CLAIMED_HIDRAW)
|
||||
printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
|
||||
|
||||
c = "Device";
|
||||
for (i = 0; i < hid->maxcollection; i++) {
|
||||
|
|
|
@ -405,6 +405,7 @@ struct hid_control_fifo {
|
|||
|
||||
#define HID_CLAIMED_INPUT 1
|
||||
#define HID_CLAIMED_HIDDEV 2
|
||||
#define HID_CLAIMED_HIDRAW 4
|
||||
|
||||
#define HID_CTRL_RUNNING 1
|
||||
#define HID_OUT_RUNNING 2
|
||||
|
@ -440,6 +441,7 @@ struct hid_device { /* device report descriptor */
|
|||
|
||||
struct list_head inputs; /* The list of inputs */
|
||||
void *hiddev; /* The hiddev structure */
|
||||
void *hidraw;
|
||||
int minor; /* Hiddev minor number */
|
||||
|
||||
wait_queue_head_t wait; /* For sleeping */
|
||||
|
@ -460,6 +462,9 @@ struct hid_device { /* device report descriptor */
|
|||
void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
|
||||
struct hid_usage *, __s32);
|
||||
void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
|
||||
|
||||
/* handler for raw output data, used by hidraw */
|
||||
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
|
||||
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
|
||||
unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
|
||||
unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
|
||||
|
|
86
include/linux/hidraw.h
Normal file
86
include/linux/hidraw.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
#ifndef _HIDRAW_H
|
||||
#define _HIDRAW_H
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
struct hidraw_report_descriptor {
|
||||
__u32 size;
|
||||
__u8 *value;
|
||||
};
|
||||
|
||||
struct hidraw_devinfo {
|
||||
__u32 bustype;
|
||||
__s16 vendor;
|
||||
__s16 product;
|
||||
};
|
||||
|
||||
/* ioctl interface */
|
||||
#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
|
||||
#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
|
||||
#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
|
||||
|
||||
#define HIDRAW_FIRST_MINOR 0
|
||||
#define HIDRAW_MAX_DEVICES 64
|
||||
/* number of reports to buffer */
|
||||
#define HIDRAW_BUFFER_SIZE 64
|
||||
|
||||
|
||||
/* kernel-only API declarations */
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/hid.h>
|
||||
|
||||
struct hidraw {
|
||||
unsigned int minor;
|
||||
int exist;
|
||||
int open;
|
||||
wait_queue_head_t wait;
|
||||
struct hid_device *hid;
|
||||
struct device *dev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct hidraw_report {
|
||||
__u8 *value;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct hidraw_list {
|
||||
struct hidraw_report buffer[HIDRAW_BUFFER_SIZE];
|
||||
int head;
|
||||
int tail;
|
||||
struct fasync_struct *fasync;
|
||||
struct hidraw *hidraw;
|
||||
struct list_head node;
|
||||
struct mutex read_mutex;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HIDRAW
|
||||
int hidraw_init(void);
|
||||
void hidraw_exit(void);
|
||||
void hidraw_report_event(struct hid_device *, u8 *, int);
|
||||
int hidraw_connect(struct hid_device *);
|
||||
void hidraw_disconnect(struct hid_device *);
|
||||
#else
|
||||
static inline int hidraw_init(void) { return 0; }
|
||||
static inline void hidraw_exit(void) { }
|
||||
static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
|
||||
static inline int hidraw_connect(struct hid_device *hid) { return -1; }
|
||||
static inline void hidraw_disconnect(struct hid_device *hid) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue