Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina: - fix for hidraw reference counting regression, by Manoj Chourasia - fix for minor number allocation for uhid, by David Herrmann - other small unsorted fixes / device ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: wiimote: fix FF deadlock HID: add Holtek USB ID 04d9:a081 SHARKOON DarkGlider HID: hidraw: close underlying device at removal of last reader HID: roccat: Fix "cannot create duplicate filename" problems HID: uhid: allocate static minor
This commit is contained in:
Коммит
fd848319e7
|
@ -241,6 +241,7 @@ config HID_HOLTEK
|
||||||
- Sharkoon Drakonia / Perixx MX-2000 gaming mice
|
- Sharkoon Drakonia / Perixx MX-2000 gaming mice
|
||||||
- Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
|
- Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
|
||||||
Zalman ZM-GM1
|
Zalman ZM-GM1
|
||||||
|
- SHARKOON DarkGlider Gaming mouse
|
||||||
|
|
||||||
config HOLTEK_FF
|
config HOLTEK_FF
|
||||||
bool "Holtek On Line Grip force feedback support"
|
bool "Holtek On Line Grip force feedback support"
|
||||||
|
|
|
@ -1715,6 +1715,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000
|
* - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000
|
||||||
* - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
|
* - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
|
||||||
* and Zalman ZM-GM1
|
* and Zalman ZM-GM1
|
||||||
|
* - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
|
@ -46,6 +47,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A:
|
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A:
|
||||||
|
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081:
|
||||||
if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f
|
if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f
|
||||||
&& rdesc[111] == 0xff && rdesc[112] == 0x7f) {
|
&& rdesc[111] == 0xff && rdesc[112] == 0x7f) {
|
||||||
hid_info(hdev, "Fixing up report descriptor\n");
|
hid_info(hdev, "Fixing up report descriptor\n");
|
||||||
|
@ -63,6 +65,8 @@ static const struct hid_device_id holtek_mouse_devices[] = {
|
||||||
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
|
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
|
||||||
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
|
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
|
||||||
|
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
|
MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
|
||||||
|
|
|
@ -450,6 +450,7 @@
|
||||||
#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055
|
#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055
|
||||||
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067
|
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067
|
||||||
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a
|
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a
|
||||||
|
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081
|
||||||
|
|
||||||
#define USB_VENDOR_ID_IMATION 0x0718
|
#define USB_VENDOR_ID_IMATION 0x0718
|
||||||
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
|
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
|
||||||
|
|
|
@ -382,7 +382,7 @@ static ssize_t kone_sysfs_write_profilex(struct file *fp,
|
||||||
}
|
}
|
||||||
#define PROFILE_ATTR(number) \
|
#define PROFILE_ATTR(number) \
|
||||||
static struct bin_attribute bin_attr_profile##number = { \
|
static struct bin_attribute bin_attr_profile##number = { \
|
||||||
.attr = { .name = "profile##number", .mode = 0660 }, \
|
.attr = { .name = "profile" #number, .mode = 0660 }, \
|
||||||
.size = sizeof(struct kone_profile), \
|
.size = sizeof(struct kone_profile), \
|
||||||
.read = kone_sysfs_read_profilex, \
|
.read = kone_sysfs_read_profilex, \
|
||||||
.write = kone_sysfs_write_profilex, \
|
.write = kone_sysfs_write_profilex, \
|
||||||
|
|
|
@ -229,13 +229,13 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
|
||||||
|
|
||||||
#define PROFILE_ATTR(number) \
|
#define PROFILE_ATTR(number) \
|
||||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
|
||||||
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, \
|
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, \
|
||||||
.read = koneplus_sysfs_read_profilex_settings, \
|
.read = koneplus_sysfs_read_profilex_settings, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
}; \
|
}; \
|
||||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
|
||||||
.size = KONEPLUS_SIZE_PROFILE_BUTTONS, \
|
.size = KONEPLUS_SIZE_PROFILE_BUTTONS, \
|
||||||
.read = koneplus_sysfs_read_profilex_buttons, \
|
.read = koneplus_sysfs_read_profilex_buttons, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
|
|
|
@ -257,13 +257,13 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
|
||||||
|
|
||||||
#define PROFILE_ATTR(number) \
|
#define PROFILE_ATTR(number) \
|
||||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
|
||||||
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \
|
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \
|
||||||
.read = kovaplus_sysfs_read_profilex_settings, \
|
.read = kovaplus_sysfs_read_profilex_settings, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
}; \
|
}; \
|
||||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
|
||||||
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \
|
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \
|
||||||
.read = kovaplus_sysfs_read_profilex_buttons, \
|
.read = kovaplus_sysfs_read_profilex_buttons, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
|
|
|
@ -225,13 +225,13 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
|
||||||
|
|
||||||
#define PROFILE_ATTR(number) \
|
#define PROFILE_ATTR(number) \
|
||||||
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
static struct bin_attribute bin_attr_profile##number##_settings = { \
|
||||||
.attr = { .name = "profile##number##_settings", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
|
||||||
.size = PYRA_SIZE_PROFILE_SETTINGS, \
|
.size = PYRA_SIZE_PROFILE_SETTINGS, \
|
||||||
.read = pyra_sysfs_read_profilex_settings, \
|
.read = pyra_sysfs_read_profilex_settings, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
}; \
|
}; \
|
||||||
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
static struct bin_attribute bin_attr_profile##number##_buttons = { \
|
||||||
.attr = { .name = "profile##number##_buttons", .mode = 0440 }, \
|
.attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
|
||||||
.size = PYRA_SIZE_PROFILE_BUTTONS, \
|
.size = PYRA_SIZE_PROFILE_BUTTONS, \
|
||||||
.read = pyra_sysfs_read_profilex_buttons, \
|
.read = pyra_sysfs_read_profilex_buttons, \
|
||||||
.private = &profile_numbers[number-1], \
|
.private = &profile_numbers[number-1], \
|
||||||
|
|
|
@ -119,12 +119,22 @@ static const struct wiimod_ops wiimod_keys = {
|
||||||
* the rumble motor, this flag shouldn't be set.
|
* the rumble motor, this flag shouldn't be set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* used by wiimod_rumble and wiipro_rumble */
|
||||||
|
static void wiimod_rumble_worker(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct wiimote_data *wdata = container_of(work, struct wiimote_data,
|
||||||
|
rumble_worker);
|
||||||
|
|
||||||
|
spin_lock_irq(&wdata->state.lock);
|
||||||
|
wiiproto_req_rumble(wdata, wdata->state.cache_rumble);
|
||||||
|
spin_unlock_irq(&wdata->state.lock);
|
||||||
|
}
|
||||||
|
|
||||||
static int wiimod_rumble_play(struct input_dev *dev, void *data,
|
static int wiimod_rumble_play(struct input_dev *dev, void *data,
|
||||||
struct ff_effect *eff)
|
struct ff_effect *eff)
|
||||||
{
|
{
|
||||||
struct wiimote_data *wdata = input_get_drvdata(dev);
|
struct wiimote_data *wdata = input_get_drvdata(dev);
|
||||||
__u8 value;
|
__u8 value;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The wiimote supports only a single rumble motor so if any magnitude
|
* The wiimote supports only a single rumble motor so if any magnitude
|
||||||
|
@ -137,9 +147,10 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data,
|
||||||
else
|
else
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&wdata->state.lock, flags);
|
/* Locking state.lock here might deadlock with input_event() calls.
|
||||||
wiiproto_req_rumble(wdata, value);
|
* schedule_work acts as barrier. Merging multiple changes is fine. */
|
||||||
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
wdata->state.cache_rumble = value;
|
||||||
|
schedule_work(&wdata->rumble_worker);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +158,8 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data,
|
||||||
static int wiimod_rumble_probe(const struct wiimod_ops *ops,
|
static int wiimod_rumble_probe(const struct wiimod_ops *ops,
|
||||||
struct wiimote_data *wdata)
|
struct wiimote_data *wdata)
|
||||||
{
|
{
|
||||||
|
INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
|
||||||
|
|
||||||
set_bit(FF_RUMBLE, wdata->input->ffbit);
|
set_bit(FF_RUMBLE, wdata->input->ffbit);
|
||||||
if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
|
if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -159,6 +172,8 @@ static void wiimod_rumble_remove(const struct wiimod_ops *ops,
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
cancel_work_sync(&wdata->rumble_worker);
|
||||||
|
|
||||||
spin_lock_irqsave(&wdata->state.lock, flags);
|
spin_lock_irqsave(&wdata->state.lock, flags);
|
||||||
wiiproto_req_rumble(wdata, 0);
|
wiiproto_req_rumble(wdata, 0);
|
||||||
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
||||||
|
@ -1731,7 +1746,6 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
|
||||||
{
|
{
|
||||||
struct wiimote_data *wdata = input_get_drvdata(dev);
|
struct wiimote_data *wdata = input_get_drvdata(dev);
|
||||||
__u8 value;
|
__u8 value;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The wiimote supports only a single rumble motor so if any magnitude
|
* The wiimote supports only a single rumble motor so if any magnitude
|
||||||
|
@ -1744,9 +1758,10 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
|
||||||
else
|
else
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&wdata->state.lock, flags);
|
/* Locking state.lock here might deadlock with input_event() calls.
|
||||||
wiiproto_req_rumble(wdata, value);
|
* schedule_work acts as barrier. Merging multiple changes is fine. */
|
||||||
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
wdata->state.cache_rumble = value;
|
||||||
|
schedule_work(&wdata->rumble_worker);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1756,6 +1771,8 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
|
||||||
|
|
||||||
wdata->extension.input = input_allocate_device();
|
wdata->extension.input = input_allocate_device();
|
||||||
if (!wdata->extension.input)
|
if (!wdata->extension.input)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1817,12 +1834,13 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops,
|
||||||
if (!wdata->extension.input)
|
if (!wdata->extension.input)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
input_unregister_device(wdata->extension.input);
|
||||||
|
wdata->extension.input = NULL;
|
||||||
|
cancel_work_sync(&wdata->rumble_worker);
|
||||||
|
|
||||||
spin_lock_irqsave(&wdata->state.lock, flags);
|
spin_lock_irqsave(&wdata->state.lock, flags);
|
||||||
wiiproto_req_rumble(wdata, 0);
|
wiiproto_req_rumble(wdata, 0);
|
||||||
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
spin_unlock_irqrestore(&wdata->state.lock, flags);
|
||||||
|
|
||||||
input_unregister_device(wdata->extension.input);
|
|
||||||
wdata->extension.input = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wiimod_ops wiimod_pro = {
|
static const struct wiimod_ops wiimod_pro = {
|
||||||
|
|
|
@ -133,13 +133,15 @@ struct wiimote_state {
|
||||||
__u8 *cmd_read_buf;
|
__u8 *cmd_read_buf;
|
||||||
__u8 cmd_read_size;
|
__u8 cmd_read_size;
|
||||||
|
|
||||||
/* calibration data */
|
/* calibration/cache data */
|
||||||
__u16 calib_bboard[4][3];
|
__u16 calib_bboard[4][3];
|
||||||
|
__u8 cache_rumble;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wiimote_data {
|
struct wiimote_data {
|
||||||
struct hid_device *hdev;
|
struct hid_device *hdev;
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
|
struct work_struct rumble_worker;
|
||||||
struct led_classdev *leds[4];
|
struct led_classdev *leds[4];
|
||||||
struct input_dev *accel;
|
struct input_dev *accel;
|
||||||
struct input_dev *ir;
|
struct input_dev *ir;
|
||||||
|
|
|
@ -308,18 +308,25 @@ static int hidraw_fasync(int fd, struct file *file, int on)
|
||||||
static void drop_ref(struct hidraw *hidraw, int exists_bit)
|
static void drop_ref(struct hidraw *hidraw, int exists_bit)
|
||||||
{
|
{
|
||||||
if (exists_bit) {
|
if (exists_bit) {
|
||||||
hid_hw_close(hidraw->hid);
|
|
||||||
hidraw->exist = 0;
|
hidraw->exist = 0;
|
||||||
if (hidraw->open)
|
if (hidraw->open) {
|
||||||
|
hid_hw_close(hidraw->hid);
|
||||||
wake_up_interruptible(&hidraw->wait);
|
wake_up_interruptible(&hidraw->wait);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
--hidraw->open;
|
--hidraw->open;
|
||||||
}
|
}
|
||||||
|
if (!hidraw->open) {
|
||||||
if (!hidraw->open && !hidraw->exist) {
|
if (!hidraw->exist) {
|
||||||
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
|
device_destroy(hidraw_class,
|
||||||
hidraw_table[hidraw->minor] = NULL;
|
MKDEV(hidraw_major, hidraw->minor));
|
||||||
kfree(hidraw);
|
hidraw_table[hidraw->minor] = NULL;
|
||||||
|
kfree(hidraw);
|
||||||
|
} else {
|
||||||
|
/* close device for last reader */
|
||||||
|
hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
|
||||||
|
hid_hw_close(hidraw->hid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -615,7 +615,7 @@ static const struct file_operations uhid_fops = {
|
||||||
|
|
||||||
static struct miscdevice uhid_misc = {
|
static struct miscdevice uhid_misc = {
|
||||||
.fops = &uhid_fops,
|
.fops = &uhid_fops,
|
||||||
.minor = MISC_DYNAMIC_MINOR,
|
.minor = UHID_MINOR,
|
||||||
.name = UHID_NAME,
|
.name = UHID_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -634,4 +634,5 @@ module_exit(uhid_exit);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
|
MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
|
||||||
MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
|
MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
|
||||||
|
MODULE_ALIAS_MISCDEV(UHID_MINOR);
|
||||||
MODULE_ALIAS("devname:" UHID_NAME);
|
MODULE_ALIAS("devname:" UHID_NAME);
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#define MAPPER_CTRL_MINOR 236
|
#define MAPPER_CTRL_MINOR 236
|
||||||
#define LOOP_CTRL_MINOR 237
|
#define LOOP_CTRL_MINOR 237
|
||||||
#define VHOST_NET_MINOR 238
|
#define VHOST_NET_MINOR 238
|
||||||
|
#define UHID_MINOR 239
|
||||||
#define MISC_DYNAMIC_MINOR 255
|
#define MISC_DYNAMIC_MINOR 255
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче