Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (34 commits) HID: roccat: Update sysfs attribute doc HID: roccat: don't use #pragma pack HID: roccat: Add support for Roccat Kone[+] v2 HID: roccat: reduce number of functions in kone and pyra drivers HID: roccat: declare meaning of pack pragma usage in driver headers HID: roccat: use class for char device for sysfs attribute creation sysfs: Introducing binary attributes for struct class HID: hidraw: add compatibility ioctl() for 32-bit applications. HID: hid-picolcd: Fix memory leak in picolcd_debug_out_report() HID: picolcd: fix misuse of logical operation in place of bitop HID: usbhid: base runtime PM on modern API HID: replace offsets values with their corresponding BTN_* defines HID: hid-mosart: support suspend/resume HID: hid-mosart: ignore buttons report HID: hid-picolcd: don't use flush_scheduled_work() HID: simplify an index check in hid_lookup_collection HID: Hoist assigns from ifs HID: Remove superfluous __inline__ HID: Use vzalloc for vmalloc/memset(,0...) HID: Add and use hid_<level>: dev_<level> equivalents ...
This commit is contained in:
commit
facc7a96d4
|
@ -1,4 +1,4 @@
|
|||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_dpi
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_dpi
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: It is possible to switch the dpi setting of the mouse with the
|
||||
|
@ -17,13 +17,13 @@ Description: It is possible to switch the dpi setting of the mouse with the
|
|||
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_profile
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the number of the actual profile.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/firmware_version
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the raw integer version number of the
|
||||
|
@ -33,7 +33,7 @@ Description: When read, this file returns the raw integer version number of the
|
|||
left. E.g. a returned value of 138 means 1.38
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/profile[1-5]
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
|
@ -48,7 +48,7 @@ Description: The mouse can store 5 profiles which can be switched by the
|
|||
stored in the profile doesn't need to fit the number of the
|
||||
store.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/settings
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the settings stored in the mouse.
|
||||
|
@ -58,7 +58,7 @@ Description: When read, this file returns the settings stored in the mouse.
|
|||
The data has to be 36 bytes long. The mouse will reject invalid
|
||||
data.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/startup_profile
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The integer value of this attribute ranges from 1 to 5.
|
||||
|
@ -67,7 +67,7 @@ Description: The integer value of this attribute ranges from 1 to 5.
|
|||
When written, this file sets the number of the startup profile
|
||||
and the mouse activates this profile immediately.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/tcu
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/tcu
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse has a "Tracking Control Unit" which lets the user
|
||||
|
@ -78,7 +78,7 @@ Description: The mouse has a "Tracking Control Unit" which lets the user
|
|||
Writing 1 in this file will start the calibration which takes
|
||||
around 6 seconds to complete and activates the TCU.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/weight
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/weight
|
||||
Date: March 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can be equipped with one of four supplied weights
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the number of the actual profile in
|
||||
range 0-4.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the raw integer version number of the
|
||||
firmware reported by the mouse. Using the integer value eases
|
||||
further usage in other programs. To receive the real version
|
||||
number the decimal point has to be shifted 2 positions to the
|
||||
left. E.g. a returned value of 121 means 1.21
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store a macro with max 500 key/button strokes
|
||||
internally.
|
||||
When written, this file lets one set the sequence for a specific
|
||||
button for a specific profile. Button and profile numbers are
|
||||
included in written data. The data has to be 2082 bytes long.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
press of a button. A profile is split in settings and buttons.
|
||||
profile_buttons holds informations about button layout.
|
||||
When written, this file lets one write the respective profile
|
||||
buttons back to the mouse. The data has to be 77 bytes long.
|
||||
The mouse will reject invalid data.
|
||||
Which profile to write is determined by the profile number
|
||||
contained in the data.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
press of a button. A profile is split in settings and buttons.
|
||||
profile_buttons holds informations about button layout.
|
||||
When read, these files return the respective profile buttons.
|
||||
The returned data is 77 bytes in size.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
press of a button. A profile is split in settings and buttons.
|
||||
profile_settings holds informations like resolution, sensitivity
|
||||
and light effects.
|
||||
When written, this file lets one write the respective profile
|
||||
settings back to the mouse. The data has to be 43 bytes long.
|
||||
The mouse will reject invalid data.
|
||||
Which profile to write is determined by the profile number
|
||||
contained in the data.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
press of a button. A profile is split in settings and buttons.
|
||||
profile_settings holds informations like resolution, sensitivity
|
||||
and light effects.
|
||||
When read, these files return the respective profile settings.
|
||||
The returned data is 43 bytes in size.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse has a tracking- and a distance-control-unit. These
|
||||
can be activated/deactivated and the lift-off distance can be
|
||||
set. The data has to be 6 bytes long.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The integer value of this attribute ranges from 0-4.
|
||||
When read, this attribute returns the number of the profile
|
||||
that's active when the mouse is powered on.
|
||||
When written, this file sets the number of the startup profile
|
||||
and the mouse activates this profile immediately.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When written a calibration process for the tracking control unit
|
||||
can be initiated/cancelled.
|
||||
The data has to be 3 bytes long.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read the mouse returns a 30x30 pixel image of the
|
||||
sampled underground. This works only in the course of a
|
||||
calibration process initiated with tcu.
|
||||
The returned data is 1028 bytes in size.
|
||||
This file is readonly.
|
|
@ -1,4 +1,4 @@
|
|||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_cpi
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: It is possible to switch the cpi setting of the mouse with the
|
||||
|
@ -14,14 +14,14 @@ Description: It is possible to switch the cpi setting of the mouse with the
|
|||
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the number of the actual profile in
|
||||
range 0-4.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the raw integer version number of the
|
||||
|
@ -31,7 +31,7 @@ Description: When read, this file returns the raw integer version number of the
|
|||
left. E.g. a returned value of 138 means 1.38
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_settings
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
|
@ -45,7 +45,7 @@ Description: The mouse can store 5 profiles which can be switched by the
|
|||
contained in the data.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_settings
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
|
@ -56,7 +56,7 @@ Description: The mouse can store 5 profiles which can be switched by the
|
|||
The returned data is 13 bytes in size.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_buttons
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
|
@ -69,7 +69,7 @@ Description: The mouse can store 5 profiles which can be switched by the
|
|||
contained in the data.
|
||||
This file is writeonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_buttons
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The mouse can store 5 profiles which can be switched by the
|
||||
|
@ -79,7 +79,7 @@ Description: The mouse can store 5 profiles which can be switched by the
|
|||
The returned data is 19 bytes in size.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The integer value of this attribute ranges from 0-4.
|
||||
|
@ -87,7 +87,7 @@ Description: The integer value of this attribute ranges from 0-4.
|
|||
that's active when the mouse is powered on.
|
||||
This file is readonly.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
|
||||
Date: August 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the settings stored in the mouse.
|
||||
|
|
|
@ -338,6 +338,35 @@ static void device_remove_attributes(struct device *dev,
|
|||
device_remove_file(dev, &attrs[i]);
|
||||
}
|
||||
|
||||
static int device_add_bin_attributes(struct device *dev,
|
||||
struct bin_attribute *attrs)
|
||||
{
|
||||
int error = 0;
|
||||
int i;
|
||||
|
||||
if (attrs) {
|
||||
for (i = 0; attr_name(attrs[i]); i++) {
|
||||
error = device_create_bin_file(dev, &attrs[i]);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
if (error)
|
||||
while (--i >= 0)
|
||||
device_remove_bin_file(dev, &attrs[i]);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static void device_remove_bin_attributes(struct device *dev,
|
||||
struct bin_attribute *attrs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (attrs)
|
||||
for (i = 0; attr_name(attrs[i]); i++)
|
||||
device_remove_bin_file(dev, &attrs[i]);
|
||||
}
|
||||
|
||||
static int device_add_groups(struct device *dev,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
|
@ -378,12 +407,15 @@ static int device_add_attrs(struct device *dev)
|
|||
error = device_add_attributes(dev, class->dev_attrs);
|
||||
if (error)
|
||||
return error;
|
||||
error = device_add_bin_attributes(dev, class->dev_bin_attrs);
|
||||
if (error)
|
||||
goto err_remove_class_attrs;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
error = device_add_groups(dev, type->groups);
|
||||
if (error)
|
||||
goto err_remove_class_attrs;
|
||||
goto err_remove_class_bin_attrs;
|
||||
}
|
||||
|
||||
error = device_add_groups(dev, dev->groups);
|
||||
|
@ -395,6 +427,9 @@ static int device_add_attrs(struct device *dev)
|
|||
err_remove_type_groups:
|
||||
if (type)
|
||||
device_remove_groups(dev, type->groups);
|
||||
err_remove_class_bin_attrs:
|
||||
if (class)
|
||||
device_remove_bin_attributes(dev, class->dev_bin_attrs);
|
||||
err_remove_class_attrs:
|
||||
if (class)
|
||||
device_remove_attributes(dev, class->dev_attrs);
|
||||
|
@ -412,8 +447,10 @@ static void device_remove_attrs(struct device *dev)
|
|||
if (type)
|
||||
device_remove_groups(dev, type->groups);
|
||||
|
||||
if (class)
|
||||
if (class) {
|
||||
device_remove_attributes(dev, class->dev_attrs);
|
||||
device_remove_bin_attributes(dev, class->dev_bin_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -150,6 +150,16 @@ config DRAGONRISE_FF
|
|||
Say Y here if you want to enable force feedback support for DragonRise Inc.
|
||||
game controllers.
|
||||
|
||||
config HID_EMS_FF
|
||||
tristate "EMS Production Inc. force feedback support"
|
||||
depends on USB_HID
|
||||
select INPUT_FF_MEMLESS
|
||||
---help---
|
||||
Say Y here if you want to enable force feedback support for devices by
|
||||
EMS Production Ltd.
|
||||
Currently the following devices are known to be supported:
|
||||
- Trio Linker Plus II
|
||||
|
||||
config HID_EGALAX
|
||||
tristate "eGalax multi-touch panel"
|
||||
depends on USB_HID
|
||||
|
@ -397,6 +407,13 @@ config HID_ROCCAT_KONE
|
|||
---help---
|
||||
Support for Roccat Kone mouse.
|
||||
|
||||
config HID_ROCCAT_KONEPLUS
|
||||
tristate "Roccat Kone[+] mouse support"
|
||||
depends on USB_HID
|
||||
select HID_ROCCAT
|
||||
---help---
|
||||
Support for Roccat Kone[+] mouse.
|
||||
|
||||
config HID_ROCCAT_PYRA
|
||||
tristate "Roccat Pyra mouse support"
|
||||
depends on USB_HID
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Makefile for the HID driver
|
||||
#
|
||||
hid-objs := hid-core.o hid-input.o
|
||||
hid-y := hid-core.o hid-input.o
|
||||
|
||||
ifdef CONFIG_DEBUG_FS
|
||||
hid-objs += hid-debug.o
|
||||
|
@ -11,18 +11,18 @@ obj-$(CONFIG_HID) += hid.o
|
|||
|
||||
hid-$(CONFIG_HIDRAW) += hidraw.o
|
||||
|
||||
hid-logitech-objs := hid-lg.o
|
||||
hid-logitech-y := hid-lg.o
|
||||
ifdef CONFIG_LOGITECH_FF
|
||||
hid-logitech-objs += hid-lgff.o
|
||||
hid-logitech-y += hid-lgff.o
|
||||
endif
|
||||
ifdef CONFIG_LOGIRUMBLEPAD2_FF
|
||||
hid-logitech-objs += hid-lg2ff.o
|
||||
hid-logitech-y += hid-lg2ff.o
|
||||
endif
|
||||
ifdef CONFIG_LOGIG940_FF
|
||||
hid-logitech-objs += hid-lg3ff.o
|
||||
hid-logitech-y += hid-lg3ff.o
|
||||
endif
|
||||
ifdef CONFIG_LOGIWII_FF
|
||||
hid-logitech-objs += hid-lg4ff.o
|
||||
hid-logitech-y += hid-lg4ff.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o
|
||||
|
@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
|
|||
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
|
||||
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
||||
obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o
|
||||
obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
|
||||
obj-$(CONFIG_HID_EGALAX) += hid-egalax.o
|
||||
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
|
||||
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
||||
|
@ -55,6 +56,7 @@ obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
|
|||
obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
|
||||
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o
|
||||
obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o
|
||||
obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o
|
||||
obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o
|
||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
|
||||
|
|
|
@ -246,7 +246,7 @@ static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
|
||||
if (!md) {
|
||||
dev_err(&hdev->dev, "cannot allocate 3M data\n");
|
||||
hid_err(hdev, "cannot allocate 3M data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, md);
|
||||
|
|
|
@ -93,7 +93,7 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
|
||||
if (a4 == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc device descriptor\n");
|
||||
hid_err(hdev, "can't alloc device descriptor\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_free;
|
||||
}
|
||||
|
@ -104,13 +104,13 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -59,6 +61,27 @@ struct apple_key_translation {
|
|||
u8 flags;
|
||||
};
|
||||
|
||||
static const struct apple_key_translation macbookair_fn_keys[] = {
|
||||
{ KEY_BACKSPACE, KEY_DELETE },
|
||||
{ KEY_ENTER, KEY_INSERT },
|
||||
{ KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
|
||||
{ KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
|
||||
{ KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY },
|
||||
{ KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY },
|
||||
{ KEY_UP, KEY_PAGEUP },
|
||||
{ KEY_DOWN, KEY_PAGEDOWN },
|
||||
{ KEY_LEFT, KEY_HOME },
|
||||
{ KEY_RIGHT, KEY_END },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct apple_key_translation apple_fn_keys[] = {
|
||||
{ KEY_BACKSPACE, KEY_DELETE },
|
||||
{ KEY_ENTER, KEY_INSERT },
|
||||
|
@ -146,7 +169,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
|||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct apple_sc *asc = hid_get_drvdata(hid);
|
||||
const struct apple_key_translation *trans;
|
||||
const struct apple_key_translation *trans, *table;
|
||||
|
||||
if (usage->code == KEY_FN) {
|
||||
asc->fn_on = !!value;
|
||||
|
@ -157,10 +180,16 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
|||
if (fnmode) {
|
||||
int do_translate;
|
||||
|
||||
trans = apple_find_translation((hid->product < 0x21d ||
|
||||
hid->product >= 0x300) ?
|
||||
powerbook_fn_keys : apple_fn_keys,
|
||||
usage->code);
|
||||
if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
|
||||
hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
|
||||
table = macbookair_fn_keys;
|
||||
else if (hid->product < 0x21d || hid->product >= 0x300)
|
||||
table = powerbook_fn_keys;
|
||||
else
|
||||
table = apple_fn_keys;
|
||||
|
||||
trans = apple_find_translation (table, usage->code);
|
||||
|
||||
if (trans) {
|
||||
if (test_bit(usage->code, asc->pressed_fn))
|
||||
do_translate = 1;
|
||||
|
@ -253,8 +282,8 @@ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
|
||||
rdesc[53] == 0x65 && rdesc[59] == 0x65) {
|
||||
dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up MacBook JIS keyboard report descriptor\n");
|
||||
rdesc[53] = rdesc[59] = 0xe7;
|
||||
}
|
||||
return rdesc;
|
||||
|
@ -324,7 +353,7 @@ static int apple_probe(struct hid_device *hdev,
|
|||
|
||||
asc = kzalloc(sizeof(*asc), GFP_KERNEL);
|
||||
if (asc == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc apple descriptor\n");
|
||||
hid_err(hdev, "can't alloc apple descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -334,7 +363,7 @@ static int apple_probe(struct hid_device *hdev,
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -345,7 +374,7 @@ static int apple_probe(struct hid_device *hdev,
|
|||
|
||||
ret = hid_hw_start(hdev, connect_mask);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -440,6 +469,18 @@ static const struct hid_device_id apple_devices[] = {
|
|||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||||
|
@ -473,7 +514,7 @@ static int __init apple_init(void)
|
|||
|
||||
ret = hid_register_driver(&apple_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "can't register apple driver\n");
|
||||
pr_err("can't register apple driver\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -73,14 +73,14 @@ static int axff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_first_entry(report_list, struct hid_report, list);
|
||||
|
||||
if (report->maxfield < 4) {
|
||||
dev_err(&hid->dev, "no fields in the report: %d\n", report->maxfield);
|
||||
hid_err(hid, "no fields in the report: %d\n", report->maxfield);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static int axff_init(struct hid_device *hid)
|
|||
axff->report->field[3]->value[0] = 0x00;
|
||||
usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n");
|
||||
hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n");
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -114,17 +114,17 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
{
|
||||
int error;
|
||||
|
||||
dev_dbg(&hdev->dev, "ACRUX HID hardware probe...");
|
||||
dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n");
|
||||
|
||||
error = hid_parse(hdev);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
* Do not fail device initialization completely as device
|
||||
* may still be partially operable, just warn.
|
||||
*/
|
||||
dev_warn(&hdev->dev,
|
||||
hid_warn(hdev,
|
||||
"Failed to enable force feedback support, error: %d\n",
|
||||
error);
|
||||
}
|
||||
|
|
|
@ -56,14 +56,14 @@ static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
|
||||
((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0));
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
dev_err(&hdev->dev, "cannot allocate Cando Touch data\n");
|
||||
hid_err(hdev, "cannot allocate Cando Touch data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, td);
|
||||
|
|
|
@ -30,8 +30,7 @@ static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
unsigned int *rsize)
|
||||
{
|
||||
if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
|
||||
dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
|
||||
rdesc[11] = rdesc[16] = 0xff;
|
||||
rdesc[12] = rdesc[17] = 0x03;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -59,7 +61,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type,
|
|||
if (report_enum->report_id_hash[id])
|
||||
return report_enum->report_id_hash[id];
|
||||
|
||||
if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
|
||||
report = kzalloc(sizeof(struct hid_report), GFP_KERNEL);
|
||||
if (!report)
|
||||
return NULL;
|
||||
|
||||
if (id != 0)
|
||||
|
@ -90,8 +93,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
|
||||
+ values * sizeof(unsigned), GFP_KERNEL))) return NULL;
|
||||
field = kzalloc((sizeof(struct hid_field) +
|
||||
usages * sizeof(struct hid_usage) +
|
||||
values * sizeof(unsigned)), GFP_KERNEL);
|
||||
if (!field)
|
||||
return NULL;
|
||||
|
||||
field->index = report->maxfield++;
|
||||
report->field[field->index] = field;
|
||||
|
@ -172,10 +178,14 @@ static int close_collection(struct hid_parser *parser)
|
|||
|
||||
static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
|
||||
{
|
||||
struct hid_collection *collection = parser->device->collection;
|
||||
int n;
|
||||
for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
|
||||
if (parser->device->collection[parser->collection_stack[n]].type == type)
|
||||
return parser->device->collection[parser->collection_stack[n]].usage;
|
||||
|
||||
for (n = parser->collection_stack_ptr - 1; n >= 0; n--) {
|
||||
unsigned index = parser->collection_stack[n];
|
||||
if (collection[index].type == type)
|
||||
return collection[index].usage;
|
||||
}
|
||||
return 0; /* we know nothing about this usage type */
|
||||
}
|
||||
|
||||
|
@ -209,7 +219,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
|
|||
unsigned offset;
|
||||
int i;
|
||||
|
||||
if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
|
||||
report = hid_register_report(parser->device, report_type, parser->global.report_id);
|
||||
if (!report) {
|
||||
dbg_hid("hid_register_report failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -227,7 +238,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
|
|||
|
||||
usages = max_t(int, parser->local.usage_index, parser->global.report_count);
|
||||
|
||||
if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
|
||||
field = hid_register_field(report, usages, parser->global.report_count);
|
||||
if (!field)
|
||||
return 0;
|
||||
|
||||
field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
|
||||
|
@ -652,13 +664,12 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
|
|||
return -ENOMEM;
|
||||
device->rsize = size;
|
||||
|
||||
parser = vmalloc(sizeof(struct hid_parser));
|
||||
parser = vzalloc(sizeof(struct hid_parser));
|
||||
if (!parser) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(parser, 0, sizeof(struct hid_parser));
|
||||
parser->device = device;
|
||||
|
||||
end = start + size;
|
||||
|
@ -672,7 +683,8 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
|
|||
|
||||
if (dispatch_type[item.type](parser, &item)) {
|
||||
dbg_hid("item %u %u %u %u parsing failed\n",
|
||||
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
|
||||
item.format, (unsigned)item.size,
|
||||
(unsigned)item.type, (unsigned)item.tag);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -737,13 +749,14 @@ static u32 s32ton(__s32 value, unsigned n)
|
|||
* Search linux-kernel and linux-usb-devel archives for "hid-core extract".
|
||||
*/
|
||||
|
||||
static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
|
||||
static __u32 extract(const struct hid_device *hid, __u8 *report,
|
||||
unsigned offset, unsigned n)
|
||||
{
|
||||
u64 x;
|
||||
|
||||
if (n > 32)
|
||||
printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
|
||||
n, current->comm);
|
||||
hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n",
|
||||
n, current->comm);
|
||||
|
||||
report += offset >> 3; /* adjust byte index */
|
||||
offset &= 7; /* now only need bit offset into one byte */
|
||||
|
@ -760,18 +773,19 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
|
|||
* endianness of register values by considering a register
|
||||
* a "cached" copy of the little endiad bit stream.
|
||||
*/
|
||||
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
|
||||
static void implement(const struct hid_device *hid, __u8 *report,
|
||||
unsigned offset, unsigned n, __u32 value)
|
||||
{
|
||||
u64 x;
|
||||
u64 m = (1ULL << n) - 1;
|
||||
|
||||
if (n > 32)
|
||||
printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
|
||||
n, current->comm);
|
||||
hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
|
||||
__func__, n, current->comm);
|
||||
|
||||
if (value > m)
|
||||
printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
|
||||
value, current->comm);
|
||||
hid_warn(hid, "%s() called with too large value %d! (%s)\n",
|
||||
__func__, value, current->comm);
|
||||
WARN_ON(value > m);
|
||||
value &= m;
|
||||
|
||||
|
@ -788,7 +802,7 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
|
|||
* Search an array for a value.
|
||||
*/
|
||||
|
||||
static __inline__ int search(__s32 *array, __s32 value, unsigned n)
|
||||
static int search(__s32 *array, __s32 value, unsigned n)
|
||||
{
|
||||
while (n--) {
|
||||
if (*array++ == value)
|
||||
|
@ -887,18 +901,22 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
|
|||
__s32 max = field->logical_maximum;
|
||||
__s32 *value;
|
||||
|
||||
if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
|
||||
value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC);
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
|
||||
value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
|
||||
extract(data, offset + n * size, size);
|
||||
value[n] = min < 0 ?
|
||||
snto32(extract(hid, data, offset + n * size, size),
|
||||
size) :
|
||||
extract(hid, data, offset + n * size, size);
|
||||
|
||||
if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
|
||||
&& value[n] >= min && value[n] <= max
|
||||
&& field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
|
||||
goto exit;
|
||||
/* Ignore report if ErrorRollOver */
|
||||
if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
|
||||
value[n] >= min && value[n] <= max &&
|
||||
field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
|
@ -928,7 +946,8 @@ exit:
|
|||
* Output the field into the report.
|
||||
*/
|
||||
|
||||
static void hid_output_field(struct hid_field *field, __u8 *data)
|
||||
static void hid_output_field(const struct hid_device *hid,
|
||||
struct hid_field *field, __u8 *data)
|
||||
{
|
||||
unsigned count = field->report_count;
|
||||
unsigned offset = field->report_offset;
|
||||
|
@ -937,9 +956,11 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
|
|||
|
||||
for (n = 0; n < count; n++) {
|
||||
if (field->logical_minimum < 0) /* signed values */
|
||||
implement(data, offset + n * size, size, s32ton(field->value[n], size));
|
||||
implement(hid, data, offset + n * size, size,
|
||||
s32ton(field->value[n], size));
|
||||
else /* unsigned values */
|
||||
implement(data, offset + n * size, size, field->value[n]);
|
||||
implement(hid, data, offset + n * size, size,
|
||||
field->value[n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -956,7 +977,7 @@ void hid_output_report(struct hid_report *report, __u8 *data)
|
|||
|
||||
memset(data, 0, ((report->size - 1) >> 3) + 1);
|
||||
for (n = 0; n < report->maxfield; n++)
|
||||
hid_output_field(report->field[n], data);
|
||||
hid_output_field(report->device, report->field[n], data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_output_report);
|
||||
|
||||
|
@ -1169,8 +1190,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
|
|||
hdev->claimed |= HID_CLAIMED_HIDRAW;
|
||||
|
||||
if (!hdev->claimed) {
|
||||
dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
|
||||
"hidraw\n");
|
||||
hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1210,9 +1230,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
|
|||
bus = "<UNKNOWN>";
|
||||
}
|
||||
|
||||
dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
|
||||
buf, bus, hdev->version >> 8, hdev->version & 0xff,
|
||||
type, hdev->name, hdev->phys);
|
||||
hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
|
||||
buf, bus, hdev->version >> 8, hdev->version & 0xff,
|
||||
type, hdev->name, hdev->phys);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1230,7 +1250,7 @@ void hid_disconnect(struct hid_device *hdev)
|
|||
EXPORT_SYMBOL_GPL(hid_disconnect);
|
||||
|
||||
/* a list of devices for which there is a specialized driver on HID bus */
|
||||
static const struct hid_device_id hid_blacklist[] = {
|
||||
static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
|
||||
|
@ -1276,6 +1296,12 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
|
||||
|
@ -1292,6 +1318,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
|
||||
|
@ -1304,6 +1331,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
|
||||
|
@ -1372,6 +1400,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
|
||||
|
@ -1499,9 +1528,9 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
|
|||
if (!hid_match_device(hdev, hdrv))
|
||||
return 0;
|
||||
|
||||
/* generic wants all non-blacklisted */
|
||||
/* generic wants all that don't have specialized driver */
|
||||
if (!strncmp(hdrv->name, "generic-", 8))
|
||||
return !hid_match_id(hdev, hid_blacklist);
|
||||
return !hid_match_id(hdev, hid_have_special_driver);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1761,6 +1790,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||
{ }
|
||||
|
@ -1952,12 +1987,12 @@ static int __init hid_init(void)
|
|||
int ret;
|
||||
|
||||
if (hid_debug)
|
||||
printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
|
||||
"HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
|
||||
pr_warn("hid_debug is now used solely for parser and driver debugging.\n"
|
||||
"debugfs is now used for inspecting the device (report descriptor, reports)\n");
|
||||
|
||||
ret = bus_register(&hid_bus_type);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "HID: can't register hid bus\n");
|
||||
pr_err("can't register hid bus\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,13 +107,13 @@ static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -393,7 +395,7 @@ char *hid_resolv_usage(unsigned usage, struct seq_file *f) {
|
|||
|
||||
buf = resolv_usage_page(usage >> 16, f);
|
||||
if (IS_ERR(buf)) {
|
||||
printk(KERN_ERR "error allocating HID debug buffer\n");
|
||||
pr_err("error allocating HID debug buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,18 +96,18 @@ static int drff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_first_entry(report_list, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "no fields in the report\n");
|
||||
hid_err(hid, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 7) {
|
||||
dev_err(&hid->dev, "not enough values in the field\n");
|
||||
hid_err(hid, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -133,8 +133,8 @@ static int drff_init(struct hid_device *hid)
|
|||
drff->report->field[0]->value[6] = 0x00;
|
||||
usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "Force Feedback for DragonRise Inc. game "
|
||||
"controllers by Richard Walmsley <richwalm@gmail.com>\n");
|
||||
hid_info(hid, "Force Feedback for DragonRise Inc. "
|
||||
"game controllers by Richard Walmsley <richwalm@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -153,13 +153,13 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
dev_err(&hdev->dev, "cannot allocate eGalax data\n");
|
||||
hid_err(hdev, "cannot allocate eGalax data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, td);
|
||||
|
|
|
@ -24,8 +24,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
unsigned int *rsize)
|
||||
{
|
||||
if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
|
||||
dev_info(&hdev->dev, "Fixing up Elecom BM084 "
|
||||
"report descriptor.\n");
|
||||
hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
|
||||
rdesc[47] = 0x00;
|
||||
}
|
||||
return rdesc;
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Force feedback support for EMS Trio Linker Plus II
|
||||
*
|
||||
* Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
#include "usbhid/usbhid.h"
|
||||
|
||||
struct emsff_device {
|
||||
struct hid_report *report;
|
||||
};
|
||||
|
||||
static int emsff_play(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
struct emsff_device *emsff = data;
|
||||
int weak, strong;
|
||||
|
||||
weak = effect->u.rumble.weak_magnitude;
|
||||
strong = effect->u.rumble.strong_magnitude;
|
||||
|
||||
dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
|
||||
|
||||
weak = weak * 0xff / 0xffff;
|
||||
strong = strong * 0xff / 0xffff;
|
||||
|
||||
emsff->report->field[0]->value[1] = weak;
|
||||
emsff->report->field[0]->value[2] = strong;
|
||||
|
||||
dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
|
||||
usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emsff_init(struct hid_device *hid)
|
||||
{
|
||||
struct emsff_device *emsff;
|
||||
struct hid_report *report;
|
||||
struct hid_input *hidinput = list_first_entry(&hid->inputs,
|
||||
struct hid_input, list);
|
||||
struct list_head *report_list =
|
||||
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||
struct input_dev *dev = hidinput->input;
|
||||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_first_entry(report_list, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
hid_err(hid, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 7) {
|
||||
hid_err(hid, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL);
|
||||
if (!emsff)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(FF_RUMBLE, dev->ffbit);
|
||||
|
||||
error = input_ff_create_memless(dev, emsff, emsff_play);
|
||||
if (error) {
|
||||
kfree(emsff);
|
||||
return error;
|
||||
}
|
||||
|
||||
emsff->report = report;
|
||||
emsff->report->field[0]->value[0] = 0x01;
|
||||
emsff->report->field[0]->value[1] = 0x00;
|
||||
emsff->report->field[0]->value[2] = 0x00;
|
||||
emsff->report->field[0]->value[3] = 0x00;
|
||||
emsff->report->field[0]->value[4] = 0x00;
|
||||
emsff->report->field[0]->value[5] = 0x00;
|
||||
emsff->report->field[0]->value[6] = 0x00;
|
||||
usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
|
||||
|
||||
hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
emsff_init(hdev);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hid_device_id ems_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ems_devices);
|
||||
|
||||
static struct hid_driver ems_driver = {
|
||||
.name = "hkems",
|
||||
.id_table = ems_devices,
|
||||
.probe = ems_probe,
|
||||
};
|
||||
|
||||
static int ems_init(void)
|
||||
{
|
||||
return hid_register_driver(&ems_driver);
|
||||
}
|
||||
|
||||
static void ems_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&ems_driver);
|
||||
}
|
||||
|
||||
module_init(ems_init);
|
||||
module_exit(ems_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -87,7 +87,7 @@ static int gaff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -95,12 +95,12 @@ static int gaff_init(struct hid_device *hid)
|
|||
|
||||
report = list_entry(report_ptr, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "no fields in the report\n");
|
||||
hid_err(hid, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 6) {
|
||||
dev_err(&hid->dev, "not enough values in the field\n");
|
||||
hid_err(hid, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -128,8 +128,7 @@ static int gaff_init(struct hid_device *hid)
|
|||
|
||||
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
|
||||
" devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
|
||||
hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,13 +147,13 @@ static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,12 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244
|
||||
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239
|
||||
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a
|
||||
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
|
||||
|
@ -156,6 +162,7 @@
|
|||
#define USB_VENDOR_ID_CHICONY 0x04f2
|
||||
#define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
|
||||
#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d
|
||||
#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
|
||||
|
||||
#define USB_VENDOR_ID_CIDC 0x1677
|
||||
|
||||
|
@ -208,6 +215,9 @@
|
|||
#define USB_VENDOR_ID_ELO 0x04E7
|
||||
#define USB_DEVICE_ID_ELO_TS2700 0x0020
|
||||
|
||||
#define USB_VENDOR_ID_EMS 0x2006
|
||||
#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
|
||||
|
||||
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
|
||||
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
|
||||
|
||||
|
@ -480,6 +490,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_ROCCAT 0x1e7d
|
||||
#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
|
||||
#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
|
||||
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
|
||||
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
|
||||
|
||||
|
|
|
@ -319,21 +319,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
|
||||
switch (field->application) {
|
||||
case HID_GD_MOUSE:
|
||||
case HID_GD_POINTER: code += 0x110; break;
|
||||
case HID_GD_POINTER: code += BTN_MOUSE; break;
|
||||
case HID_GD_JOYSTICK:
|
||||
if (code <= 0xf)
|
||||
code += BTN_JOYSTICK;
|
||||
else
|
||||
code += BTN_TRIGGER_HAPPY;
|
||||
break;
|
||||
case HID_GD_GAMEPAD: code += 0x130; break;
|
||||
case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break;
|
||||
default:
|
||||
switch (field->physical) {
|
||||
case HID_GD_MOUSE:
|
||||
case HID_GD_POINTER: code += 0x110; break;
|
||||
case HID_GD_JOYSTICK: code += 0x120; break;
|
||||
case HID_GD_GAMEPAD: code += 0x130; break;
|
||||
default: code += 0x100;
|
||||
case HID_GD_POINTER: code += BTN_MOUSE; break;
|
||||
case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break;
|
||||
case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break;
|
||||
default: code += BTN_MISC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,14 +817,14 @@ static int hidinput_open(struct input_dev *dev)
|
|||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
|
||||
return hid->ll_driver->open(hid);
|
||||
return hid_hw_open(hid);
|
||||
}
|
||||
|
||||
static void hidinput_close(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
|
||||
hid->ll_driver->close(hid);
|
||||
hid_hw_close(hid);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -871,7 +871,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
|||
if (!hidinput || !input_dev) {
|
||||
kfree(hidinput);
|
||||
input_free_device(input_dev);
|
||||
err_hid("Out of memory during hid input probe");
|
||||
hid_err(hid, "Out of memory during hid input probe\n");
|
||||
goto out_unwind;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
|
||||
rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
|
||||
rdesc[73] == 0x95 && rdesc[74] == 0x01) {
|
||||
dev_info(&hdev->dev, "fixing up Kye/Genius Ergo Mouse report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up Kye/Genius Ergo Mouse report descriptor\n");
|
||||
rdesc[62] = 0x09;
|
||||
rdesc[64] = 0x04;
|
||||
rdesc[66] = 0x07;
|
||||
|
|
|
@ -53,23 +53,22 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
|
||||
rdesc[84] == 0x8c && rdesc[85] == 0x02) {
|
||||
dev_info(&hdev->dev, "fixing up Logitech keyboard report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up Logitech keyboard report descriptor\n");
|
||||
rdesc[84] = rdesc[89] = 0x4d;
|
||||
rdesc[85] = rdesc[90] = 0x10;
|
||||
}
|
||||
if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
|
||||
rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
|
||||
rdesc[49] == 0x81 && rdesc[50] == 0x06) {
|
||||
dev_info(&hdev->dev, "fixing up rel/abs in Logitech "
|
||||
"report descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up rel/abs in Logitech report descriptor\n");
|
||||
rdesc[33] = rdesc[50] = 0x02;
|
||||
}
|
||||
if ((quirks & LG_FF4) && *rsize >= 101 &&
|
||||
rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
|
||||
rdesc[47] == 0x05 && rdesc[48] == 0x09) {
|
||||
dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless "
|
||||
"button descriptor\n");
|
||||
hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
|
||||
rdesc[41] = 0x05;
|
||||
rdesc[42] = 0x09;
|
||||
rdesc[47] = 0x95;
|
||||
|
@ -288,7 +287,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -297,7 +296,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_hw_start(hdev, connect_mask);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,18 +72,18 @@ int lg2ff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output report found\n");
|
||||
hid_err(hid, "no output report found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "output report is empty\n");
|
||||
hid_err(hid, "output report is empty\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (report->field[0]->report_count < 7) {
|
||||
dev_err(&hid->dev, "not enough values in the field\n");
|
||||
hid_err(hid, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -110,8 +110,7 @@ int lg2ff_init(struct hid_device *hid)
|
|||
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "Force feedback for Logitech RumblePad/Rumblepad 2 by "
|
||||
"Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -141,20 +141,20 @@ int lg3ff_init(struct hid_device *hid)
|
|||
|
||||
/* Find the report to use */
|
||||
if (list_empty(report_list)) {
|
||||
err_hid("No output report found");
|
||||
hid_err(hid, "No output report found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that the report looks ok */
|
||||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
if (!report) {
|
||||
err_hid("NULL output report");
|
||||
hid_err(hid, "NULL output report\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
field = report->field[0];
|
||||
if (!field) {
|
||||
err_hid("NULL field");
|
||||
hid_err(hid, "NULL field\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -169,8 +169,7 @@ int lg3ff_init(struct hid_device *hid)
|
|||
if (test_bit(FF_AUTOCENTER, dev->ffbit))
|
||||
dev->ff->set_autocenter = hid_lg3ff_set_autocenter;
|
||||
|
||||
dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by "
|
||||
"Gary Stein <LordCnidarian@gmail.com>\n");
|
||||
hid_info(hid, "Force feedback for Logitech Flight System G940 by Gary Stein <LordCnidarian@gmail.com>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,20 +101,20 @@ int lg4ff_init(struct hid_device *hid)
|
|||
|
||||
/* Find the report to use */
|
||||
if (list_empty(report_list)) {
|
||||
err_hid("No output report found");
|
||||
hid_err(hid, "No output report found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that the report looks ok */
|
||||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
if (!report) {
|
||||
err_hid("NULL output report");
|
||||
hid_err(hid, "NULL output report\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
field = report->field[0];
|
||||
if (!field) {
|
||||
err_hid("NULL field");
|
||||
hid_err(hid, "NULL field\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -129,8 +129,7 @@ int lg4ff_init(struct hid_device *hid)
|
|||
if (test_bit(FF_AUTOCENTER, dev->ffbit))
|
||||
dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
|
||||
|
||||
dev_info(&hid->dev, "Force feedback for Logitech Speed Force Wireless by "
|
||||
"Simon Wood <simon@mungewell.org>\n");
|
||||
hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
* e-mail - mail your message to <johann.deneux@it.uu.se>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/hid.h>
|
||||
|
@ -146,7 +148,7 @@ int lgff_init(struct hid_device* hid)
|
|||
|
||||
/* Find the report to use */
|
||||
if (list_empty(report_list)) {
|
||||
err_hid("No output report found");
|
||||
hid_err(hid, "No output report found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -154,7 +156,7 @@ int lgff_init(struct hid_device* hid)
|
|||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
field = report->field[0];
|
||||
if (!field) {
|
||||
err_hid("NULL field");
|
||||
hid_err(hid, "NULL field\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -176,7 +178,7 @@ int lgff_init(struct hid_device* hid)
|
|||
if ( test_bit(FF_AUTOCENTER, dev->ffbit) )
|
||||
dev->ff->set_autocenter = hid_lgff_set_autocenter;
|
||||
|
||||
printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
|
||||
pr_info("Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
* any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -433,6 +435,11 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
|
|||
if (!msc->input)
|
||||
msc->input = hi->input;
|
||||
|
||||
/* Magic Trackpad does not give relative data after switching to MT */
|
||||
if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD &&
|
||||
field->flags & HID_MAIN_ITEM_RELATIVE)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -446,7 +453,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
|||
|
||||
msc = kzalloc(sizeof(*msc), GFP_KERNEL);
|
||||
if (msc == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n");
|
||||
hid_err(hdev, "can't alloc magicmouse descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -459,13 +466,13 @@ static int magicmouse_probe(struct hid_device *hdev,
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "magicmouse hid parse failed\n");
|
||||
hid_err(hdev, "magicmouse hid parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "magicmouse hw start failed\n");
|
||||
hid_err(hdev, "magicmouse hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -486,7 +493,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
|||
}
|
||||
|
||||
if (!report) {
|
||||
dev_err(&hdev->dev, "unable to register touch report\n");
|
||||
hid_err(hdev, "unable to register touch report\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_stop_hw;
|
||||
}
|
||||
|
@ -495,8 +502,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
|||
ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
|
||||
HID_FEATURE_REPORT);
|
||||
if (ret != sizeof(feature)) {
|
||||
dev_err(&hdev->dev, "unable to request touch data (%d)\n",
|
||||
ret);
|
||||
hid_err(hdev, "unable to request touch data (%d)\n", ret);
|
||||
goto err_stop_hw;
|
||||
}
|
||||
|
||||
|
@ -540,7 +546,7 @@ static int __init magicmouse_init(void)
|
|||
|
||||
ret = hid_register_driver(&magicmouse_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "can't register magicmouse driver\n");
|
||||
pr_err("can't register magicmouse driver\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
|
||||
rdesc[559] == 0x29) {
|
||||
dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
|
||||
"Model 1028 report descriptor\n");
|
||||
hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
|
||||
rdesc[557] = 0x35;
|
||||
rdesc[559] = 0x45;
|
||||
}
|
||||
|
@ -155,14 +154,14 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
|
||||
HID_CONNECT_HIDINPUT_FORCE : 0));
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
unsigned int *rsize)
|
||||
{
|
||||
if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
|
||||
dev_info(&hdev->dev, "fixing up button/consumer in HID report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev, "fixing up button/consumer in HID report descriptor\n");
|
||||
rdesc[30] = 0x0c;
|
||||
}
|
||||
return rdesc;
|
||||
|
|
|
@ -90,6 +90,10 @@ static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
case 0xff000000:
|
||||
/* ignore HID features */
|
||||
return -1;
|
||||
|
||||
case HID_UP_BUTTON:
|
||||
/* ignore buttons */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -199,7 +203,7 @@ static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
dev_err(&hdev->dev, "cannot allocate MosArt data\n");
|
||||
hid_err(hdev, "cannot allocate MosArt data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
td->valid = false;
|
||||
|
@ -230,6 +234,19 @@ static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mosart_reset_resume(struct hid_device *hdev)
|
||||
{
|
||||
struct hid_report_enum *re = hdev->report_enum
|
||||
+ HID_FEATURE_REPORT;
|
||||
struct hid_report *r = re->report_id_hash[7];
|
||||
|
||||
r->field[0]->value[0] = 0x02;
|
||||
usbhid_submit_report(hdev, r, USB_DIR_OUT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mosart_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
|
@ -258,6 +275,9 @@ static struct hid_driver mosart_driver = {
|
|||
.input_mapped = mosart_input_mapped,
|
||||
.usage_table = mosart_grabbed_usages,
|
||||
.event = mosart_event,
|
||||
#ifdef CONFIG_PM
|
||||
.reset_resume = mosart_reset_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init mosart_init(void)
|
||||
|
|
|
@ -130,8 +130,7 @@ static void ntrig_report_version(struct hid_device *hdev)
|
|||
if (ret == 8) {
|
||||
ret = ntrig_version_string(&data[2], buf);
|
||||
|
||||
dev_info(&hdev->dev,
|
||||
"Firmware version: %s (%02x%02x %02x%02x)\n",
|
||||
hid_info(hdev, "Firmware version: %s (%02x%02x %02x%02x)\n",
|
||||
buf, data[2], data[3], data[4], data[5]);
|
||||
}
|
||||
|
||||
|
@ -831,7 +830,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
|
||||
if (!nd) {
|
||||
dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
|
||||
hid_err(hdev, "cannot allocate N-Trig data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -850,13 +849,13 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
unsigned int *rsize)
|
||||
{
|
||||
if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
|
||||
dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 "
|
||||
"report descriptor.\n");
|
||||
hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n");
|
||||
rdesc[55] = 0x92;
|
||||
}
|
||||
return rdesc;
|
||||
|
|
|
@ -29,8 +29,7 @@ static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
|
||||
rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
|
||||
rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
|
||||
dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n");
|
||||
rdesc[60] = 0xfa;
|
||||
rdesc[40] = 0xfa;
|
||||
}
|
||||
|
@ -77,13 +76,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int di
|
|||
if (report->id == id)
|
||||
return report;
|
||||
}
|
||||
dev_warn(&hdev->dev, "No report with id 0x%x found\n", id);
|
||||
hid_warn(hdev, "No report with id 0x%x found\n", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1329,7 +1329,7 @@ static int picolcd_check_version(struct hid_device *hdev)
|
|||
|
||||
verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
|
||||
if (!verinfo) {
|
||||
dev_err(&hdev->dev, "no version response from PicoLCD");
|
||||
hid_err(hdev, "no version response from PicoLCD\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1337,14 +1337,14 @@ static int picolcd_check_version(struct hid_device *hdev)
|
|||
data->version[0] = verinfo->raw_data[1];
|
||||
data->version[1] = verinfo->raw_data[0];
|
||||
if (data->status & PICOLCD_BOOTLOADER) {
|
||||
dev_info(&hdev->dev, "PicoLCD, bootloader version %d.%d\n",
|
||||
verinfo->raw_data[1], verinfo->raw_data[0]);
|
||||
hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
|
||||
verinfo->raw_data[1], verinfo->raw_data[0]);
|
||||
} else {
|
||||
dev_info(&hdev->dev, "PicoLCD, firmware version %d.%d\n",
|
||||
verinfo->raw_data[1], verinfo->raw_data[0]);
|
||||
hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
|
||||
verinfo->raw_data[1], verinfo->raw_data[0]);
|
||||
}
|
||||
} else {
|
||||
dev_err(&hdev->dev, "confused, got unexpected version response from PicoLCD\n");
|
||||
hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
kfree(verinfo);
|
||||
|
@ -1544,7 +1544,7 @@ static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
|
|||
|
||||
/* prepare buffer with info about what we want to read (addr & len) */
|
||||
raw_data[0] = *off & 0xff;
|
||||
raw_data[1] = (*off >> 8) && 0xff;
|
||||
raw_data[1] = (*off >> 8) & 0xff;
|
||||
raw_data[2] = s < 20 ? s : 20;
|
||||
if (*off + raw_data[2] > 0xff)
|
||||
raw_data[2] = 0x100 - *off;
|
||||
|
@ -1583,7 +1583,7 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
|
|||
|
||||
memset(raw_data, 0, sizeof(raw_data));
|
||||
raw_data[0] = *off & 0xff;
|
||||
raw_data[1] = (*off >> 8) && 0xff;
|
||||
raw_data[1] = (*off >> 8) & 0xff;
|
||||
raw_data[2] = s < 20 ? s : 20;
|
||||
if (*off + raw_data[2] > 0xff)
|
||||
raw_data[2] = 0x100 - *off;
|
||||
|
@ -1867,6 +1867,7 @@ static void picolcd_debug_out_report(struct picolcd_data *data,
|
|||
report->id, raw_size);
|
||||
hid_debug_event(hdev, buff);
|
||||
if (raw_size + 5 > sizeof(raw_data)) {
|
||||
kfree(buff);
|
||||
hid_debug_event(hdev, " TOO BIG\n");
|
||||
return;
|
||||
} else {
|
||||
|
@ -2328,8 +2329,7 @@ static void picolcd_init_devfs(struct picolcd_data *data,
|
|||
(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
|
||||
hdev->debug_dir, data, &picolcd_debug_flash_fops);
|
||||
} else if (flash_r || flash_w)
|
||||
dev_warn(&hdev->dev, "Unexpected FLASH access reports, "
|
||||
"please submit rdesc for review\n");
|
||||
hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
|
||||
}
|
||||
|
||||
static void picolcd_exit_devfs(struct picolcd_data *data)
|
||||
|
@ -2457,13 +2457,13 @@ static int picolcd_init_keys(struct picolcd_data *data,
|
|||
return -ENODEV;
|
||||
if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
|
||||
report->field[0]->report_size != 8) {
|
||||
dev_err(&hdev->dev, "unsupported KEY_STATE report");
|
||||
hid_err(hdev, "unsupported KEY_STATE report\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
idev = input_allocate_device();
|
||||
if (idev == NULL) {
|
||||
dev_err(&hdev->dev, "failed to allocate input device");
|
||||
hid_err(hdev, "failed to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
input_set_drvdata(idev, hdev);
|
||||
|
@ -2485,7 +2485,7 @@ static int picolcd_init_keys(struct picolcd_data *data,
|
|||
input_set_capability(idev, EV_KEY, data->keycode[i]);
|
||||
error = input_register_device(idev);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "error registering the input device");
|
||||
hid_err(hdev, "error registering the input device\n");
|
||||
input_free_device(idev);
|
||||
return error;
|
||||
}
|
||||
|
@ -2522,9 +2522,8 @@ static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
|
|||
return error;
|
||||
|
||||
if (data->version[0] != 0 && data->version[1] != 3)
|
||||
dev_info(&hdev->dev, "Device with untested firmware revision, "
|
||||
"please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
|
||||
dev_name(&hdev->dev));
|
||||
hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
|
||||
dev_name(&hdev->dev));
|
||||
|
||||
/* Setup keypad input device */
|
||||
error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
|
||||
|
@ -2581,9 +2580,8 @@ static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data
|
|||
return error;
|
||||
|
||||
if (data->version[0] != 1 && data->version[1] != 0)
|
||||
dev_info(&hdev->dev, "Device with untested bootloader revision, "
|
||||
"please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
|
||||
dev_name(&hdev->dev));
|
||||
hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
|
||||
dev_name(&hdev->dev));
|
||||
|
||||
picolcd_init_devfs(data, NULL, NULL,
|
||||
picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
|
||||
|
@ -2605,7 +2603,7 @@ static int picolcd_probe(struct hid_device *hdev,
|
|||
*/
|
||||
data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
dev_err(&hdev->dev, "can't allocate space for Minibox PicoLCD device data\n");
|
||||
hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
|
||||
error = -ENOMEM;
|
||||
goto err_no_cleanup;
|
||||
}
|
||||
|
@ -2621,7 +2619,7 @@ static int picolcd_probe(struct hid_device *hdev,
|
|||
/* Parse the device reports and start it up */
|
||||
error = hid_parse(hdev);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "device report parse failed\n");
|
||||
hid_err(hdev, "device report parse failed\n");
|
||||
goto err_cleanup_data;
|
||||
}
|
||||
|
||||
|
@ -2631,25 +2629,25 @@ static int picolcd_probe(struct hid_device *hdev,
|
|||
error = hid_hw_start(hdev, 0);
|
||||
hdev->claimed = 0;
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "hardware start failed\n");
|
||||
hid_err(hdev, "hardware start failed\n");
|
||||
goto err_cleanup_data;
|
||||
}
|
||||
|
||||
error = hdev->ll_driver->open(hdev);
|
||||
error = hid_hw_open(hdev);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "failed to open input interrupt pipe for key and IR events\n");
|
||||
hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
|
||||
goto err_cleanup_hid_hw;
|
||||
}
|
||||
|
||||
error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "failed to create sysfs attributes\n");
|
||||
hid_err(hdev, "failed to create sysfs attributes\n");
|
||||
goto err_cleanup_hid_ll;
|
||||
}
|
||||
|
||||
error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
|
||||
if (error) {
|
||||
dev_err(&hdev->dev, "failed to create sysfs attributes\n");
|
||||
hid_err(hdev, "failed to create sysfs attributes\n");
|
||||
goto err_cleanup_sysfs1;
|
||||
}
|
||||
|
||||
|
@ -2668,7 +2666,7 @@ err_cleanup_sysfs2:
|
|||
err_cleanup_sysfs1:
|
||||
device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
|
||||
err_cleanup_hid_ll:
|
||||
hdev->ll_driver->close(hdev);
|
||||
hid_hw_close(hdev);
|
||||
err_cleanup_hid_hw:
|
||||
hid_hw_stop(hdev);
|
||||
err_cleanup_data:
|
||||
|
@ -2699,7 +2697,7 @@ static void picolcd_remove(struct hid_device *hdev)
|
|||
picolcd_exit_devfs(data);
|
||||
device_remove_file(&hdev->dev, &dev_attr_operation_mode);
|
||||
device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
|
||||
hdev->ll_driver->close(hdev);
|
||||
hid_hw_close(hdev);
|
||||
hid_hw_stop(hdev);
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
|
||||
|
@ -2753,7 +2751,7 @@ static void __exit picolcd_exit(void)
|
|||
{
|
||||
hid_unregister_driver(&picolcd_driver);
|
||||
#ifdef CONFIG_HID_PICOLCD_FB
|
||||
flush_scheduled_work();
|
||||
flush_work_sync(&picolcd_fb_cleanup);
|
||||
WARN_ON(fb_pending);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ static int plff_init(struct hid_device *hid)
|
|||
*/
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -112,14 +112,13 @@ static int plff_init(struct hid_device *hid)
|
|||
report_ptr = report_ptr->next;
|
||||
|
||||
if (report_ptr == report_list) {
|
||||
dev_err(&hid->dev, "required output report is "
|
||||
"missing\n");
|
||||
hid_err(hid, "required output report is missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_entry(report_ptr, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "no fields in the report\n");
|
||||
hid_err(hid, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -137,7 +136,7 @@ static int plff_init(struct hid_device *hid)
|
|||
weak = &report->field[3]->value[0];
|
||||
debug("detected 4-field device");
|
||||
} else {
|
||||
dev_err(&hid->dev, "not enough fields or values\n");
|
||||
hid_err(hid, "not enough fields or values\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -164,8 +163,7 @@ static int plff_init(struct hid_device *hid)
|
|||
usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
|
||||
}
|
||||
|
||||
dev_info(&hid->dev, "Force feedback for PantherLord/GreenAsia "
|
||||
"devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,13 +183,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
@ -130,7 +132,7 @@ static ssize_t store_channel(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(channel, S_IRUGO | S_IWUGO, show_channel,
|
||||
static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel,
|
||||
store_channel);
|
||||
|
||||
static struct device_attribute *sysfs_device_attr_channel = {
|
||||
|
@ -169,7 +171,7 @@ static ssize_t store_sustain(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(sustain, S_IRUGO | S_IWUGO, show_sustain,
|
||||
static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain,
|
||||
store_sustain);
|
||||
|
||||
static struct device_attribute *sysfs_device_attr_sustain = {
|
||||
|
@ -207,7 +209,7 @@ static ssize_t store_octave(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(octave, S_IRUGO | S_IWUGO, show_octave,
|
||||
static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave,
|
||||
store_octave);
|
||||
|
||||
static struct device_attribute *sysfs_device_attr_octave = {
|
||||
|
@ -285,11 +287,11 @@ static int pcmidi_get_output_report(struct pcmidi_snd *pm)
|
|||
continue;
|
||||
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hdev->dev, "output report is empty\n");
|
||||
hid_err(hdev, "output report is empty\n");
|
||||
break;
|
||||
}
|
||||
if (report->field[0]->report_count != 2) {
|
||||
dev_err(&hdev->dev, "field count too low\n");
|
||||
hid_err(hdev, "field count too low\n");
|
||||
break;
|
||||
}
|
||||
pm->pcmidi_report6 = report;
|
||||
|
@ -746,8 +748,8 @@ static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
if (*rsize == 178 &&
|
||||
rdesc[111] == 0x06 && rdesc[112] == 0x00 &&
|
||||
rdesc[113] == 0xff) {
|
||||
dev_info(&hdev->dev, "fixing up pc-midi keyboard report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up pc-midi keyboard report descriptor\n");
|
||||
|
||||
rdesc[144] = 0x18; /* report 4: was 0x10 report count */
|
||||
}
|
||||
|
@ -805,7 +807,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
pk = kzalloc(sizeof(*pk), GFP_KERNEL);
|
||||
if (pk == NULL) {
|
||||
dev_err(&hdev->dev, "prodikeys: can't alloc descriptor\n");
|
||||
hid_err(hdev, "can't alloc descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -813,8 +815,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
pm = kzalloc(sizeof(*pm), GFP_KERNEL);
|
||||
if (pm == NULL) {
|
||||
dev_err(&hdev->dev,
|
||||
"prodikeys: can't alloc descriptor\n");
|
||||
hid_err(hdev, "can't alloc descriptor\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_free;
|
||||
}
|
||||
|
@ -827,7 +828,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "prodikeys: hid parse failed\n");
|
||||
hid_err(hdev, "hid parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -837,7 +838,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "prodikeys: hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -896,7 +897,7 @@ static int pk_init(void)
|
|||
|
||||
ret = hid_register_driver(&pk_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "can't register prodikeys driver\n");
|
||||
pr_err("can't register prodikeys driver\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n");
|
||||
hid_err(hdev, "cannot allocate Quanta Touch data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
td->valid = false;
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
#include "hid-roccat.h"
|
||||
#include "hid-roccat-kone.h"
|
||||
|
||||
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
|
||||
|
||||
/* kone_class is used for creating sysfs attributes via roccat char device */
|
||||
static struct class *kone_class;
|
||||
|
||||
static void kone_set_settings_checksum(struct kone_settings *settings)
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
|
@ -90,8 +95,7 @@ static int kone_check_write(struct usb_device *usb_dev)
|
|||
kfree(data);
|
||||
return 0;
|
||||
} else { /* unknown answer */
|
||||
dev_err(&usb_dev->dev, "got retval %d when checking write\n",
|
||||
*data);
|
||||
hid_err(usb_dev, "got retval %d when checking write\n", *data);
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -262,7 +266,8 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
|
|||
static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct kone_settings))
|
||||
|
@ -286,7 +291,8 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
|
|||
static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0, difference;
|
||||
|
@ -319,10 +325,11 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
|
|||
return sizeof(struct kone_settings);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, int number) {
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
static ssize_t kone_sysfs_read_profilex(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count) {
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct kone_profile))
|
||||
|
@ -332,47 +339,18 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
|
|||
count = sizeof(struct kone_profile) - off;
|
||||
|
||||
mutex_lock(&kone->kone_lock);
|
||||
memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count);
|
||||
memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count);
|
||||
mutex_unlock(&kone->kone_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
|
||||
}
|
||||
|
||||
/* Writes data only if different to stored data */
|
||||
static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, int number) {
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
static ssize_t kone_sysfs_write_profilex(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count) {
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
struct kone_profile *profile;
|
||||
|
@ -382,13 +360,14 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
|
|||
if (off != 0 || count != sizeof(struct kone_profile))
|
||||
return -EINVAL;
|
||||
|
||||
profile = &kone->profiles[number - 1];
|
||||
profile = &kone->profiles[*(uint *)(attr->private)];
|
||||
|
||||
mutex_lock(&kone->kone_lock);
|
||||
difference = memcmp(buf, profile, sizeof(struct kone_profile));
|
||||
if (difference) {
|
||||
retval = kone_set_profile(usb_dev,
|
||||
(struct kone_profile const *)buf, number);
|
||||
(struct kone_profile const *)buf,
|
||||
*(uint *)(attr->private) + 1);
|
||||
if (!retval)
|
||||
memcpy(profile, buf, sizeof(struct kone_profile));
|
||||
}
|
||||
|
@ -400,47 +379,19 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
|
|||
return sizeof(struct kone_profile);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count) {
|
||||
return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct kone_device *kone =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct kone_device *kone =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
|
||||
}
|
||||
|
||||
|
@ -448,11 +399,15 @@ static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
|
|||
static ssize_t kone_sysfs_show_weight(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
struct kone_device *kone;
|
||||
struct usb_device *usb_dev;
|
||||
int weight = 0;
|
||||
int retval;
|
||||
|
||||
dev = dev->parent->parent;
|
||||
kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
|
||||
mutex_lock(&kone->kone_lock);
|
||||
retval = kone_get_weight(usb_dev, &weight);
|
||||
mutex_unlock(&kone->kone_lock);
|
||||
|
@ -465,14 +420,16 @@ static ssize_t kone_sysfs_show_weight(struct device *dev,
|
|||
static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct kone_device *kone =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_show_tcu(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct kone_device *kone =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu);
|
||||
}
|
||||
|
||||
|
@ -504,11 +461,15 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number)
|
|||
static ssize_t kone_sysfs_set_tcu(struct device *dev,
|
||||
struct device_attribute *attr, char const *buf, size_t size)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
struct kone_device *kone;
|
||||
struct usb_device *usb_dev;
|
||||
int retval;
|
||||
unsigned long state;
|
||||
|
||||
dev = dev->parent->parent;
|
||||
kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
|
||||
retval = strict_strtoul(buf, 10, &state);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
@ -556,7 +517,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
|
|||
|
||||
retval = kone_set_settings(usb_dev, &kone->settings);
|
||||
if (retval) {
|
||||
dev_err(&usb_dev->dev, "couldn't set tcu state\n");
|
||||
hid_err(usb_dev, "couldn't set tcu state\n");
|
||||
/*
|
||||
* try to reread valid settings into buffer overwriting
|
||||
* first error code
|
||||
|
@ -570,7 +531,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
|
|||
|
||||
retval = size;
|
||||
exit_no_settings:
|
||||
dev_err(&usb_dev->dev, "couldn't read settings\n");
|
||||
hid_err(usb_dev, "couldn't read settings\n");
|
||||
exit_unlock:
|
||||
mutex_unlock(&kone->kone_lock);
|
||||
return retval;
|
||||
|
@ -579,18 +540,23 @@ exit_unlock:
|
|||
static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct kone_device *kone =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile);
|
||||
}
|
||||
|
||||
static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char const *buf, size_t size)
|
||||
{
|
||||
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
struct kone_device *kone;
|
||||
struct usb_device *usb_dev;
|
||||
int retval;
|
||||
unsigned long new_startup_profile;
|
||||
|
||||
dev = dev->parent->parent;
|
||||
kone = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
|
||||
retval = strict_strtoul(buf, 10, &new_startup_profile);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
@ -617,160 +583,92 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
|
|||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read actual dpi settings.
|
||||
* Returns raw value for further processing. Refer to enum kone_polling_rates to
|
||||
* get real value.
|
||||
*/
|
||||
static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
|
||||
static struct device_attribute kone_attributes[] = {
|
||||
/*
|
||||
* Read actual dpi settings.
|
||||
* Returns raw value for further processing. Refer to enum
|
||||
* kone_polling_rates to get real value.
|
||||
*/
|
||||
__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
|
||||
__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
|
||||
|
||||
static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
|
||||
/*
|
||||
* The mouse can be equipped with one of four supplied weights from 5
|
||||
* to 20 grams which are recognized and its value can be read out.
|
||||
* This returns the raw value reported by the mouse for easy evaluation
|
||||
* by software. Refer to enum kone_weights to get corresponding real
|
||||
* weight.
|
||||
*/
|
||||
__ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
|
||||
|
||||
/*
|
||||
* The mouse can be equipped with one of four supplied weights from 5 to 20
|
||||
* grams which are recognized and its value can be read out.
|
||||
* This returns the raw value reported by the mouse for easy evaluation by
|
||||
* software. Refer to enum kone_weights to get corresponding real weight.
|
||||
*/
|
||||
static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
|
||||
/*
|
||||
* Prints firmware version stored in mouse as integer.
|
||||
* The raw value reported by the mouse is returned for easy evaluation,
|
||||
* to get the real version number the decimal point has to be shifted 2
|
||||
* positions to the left. E.g. a value of 138 means 1.38.
|
||||
*/
|
||||
__ATTR(firmware_version, 0440,
|
||||
kone_sysfs_show_firmware_version, NULL),
|
||||
|
||||
/*
|
||||
* Prints firmware version stored in mouse as integer.
|
||||
* The raw value reported by the mouse is returned for easy evaluation, to get
|
||||
* the real version number the decimal point has to be shifted 2 positions to
|
||||
* the left. E.g. a value of 138 means 1.38.
|
||||
*/
|
||||
static DEVICE_ATTR(firmware_version, 0440,
|
||||
kone_sysfs_show_firmware_version, NULL);
|
||||
/*
|
||||
* Prints state of Tracking Control Unit as number where 0 = off and
|
||||
* 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
|
||||
* activates the tcu
|
||||
*/
|
||||
__ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
|
||||
|
||||
/*
|
||||
* Prints state of Tracking Control Unit as number where 0 = off and 1 = on
|
||||
* Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu
|
||||
*/
|
||||
static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
|
||||
|
||||
/* Prints and takes the number of the profile the mouse starts with */
|
||||
static DEVICE_ATTR(startup_profile, 0660,
|
||||
kone_sysfs_show_startup_profile,
|
||||
kone_sysfs_set_startup_profile);
|
||||
|
||||
static struct attribute *kone_attributes[] = {
|
||||
&dev_attr_actual_dpi.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
&dev_attr_weight.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
&dev_attr_tcu.attr,
|
||||
&dev_attr_startup_profile.attr,
|
||||
NULL
|
||||
/* Prints and takes the number of the profile the mouse starts with */
|
||||
__ATTR(startup_profile, 0660,
|
||||
kone_sysfs_show_startup_profile,
|
||||
kone_sysfs_set_startup_profile),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static struct attribute_group kone_attribute_group = {
|
||||
.attrs = kone_attributes
|
||||
static struct bin_attribute kone_bin_attributes[] = {
|
||||
{
|
||||
.attr = { .name = "settings", .mode = 0660 },
|
||||
.size = sizeof(struct kone_settings),
|
||||
.read = kone_sysfs_read_settings,
|
||||
.write = kone_sysfs_write_settings
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profilex,
|
||||
.write = kone_sysfs_write_profilex,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_settings_attr = {
|
||||
.attr = { .name = "settings", .mode = 0660 },
|
||||
.size = sizeof(struct kone_settings),
|
||||
.read = kone_sysfs_read_settings,
|
||||
.write = kone_sysfs_write_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_profile1_attr = {
|
||||
.attr = { .name = "profile1", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profile1,
|
||||
.write = kone_sysfs_write_profile1
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_profile2_attr = {
|
||||
.attr = { .name = "profile2", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profile2,
|
||||
.write = kone_sysfs_write_profile2
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_profile3_attr = {
|
||||
.attr = { .name = "profile3", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profile3,
|
||||
.write = kone_sysfs_write_profile3
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_profile4_attr = {
|
||||
.attr = { .name = "profile4", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profile4,
|
||||
.write = kone_sysfs_write_profile4
|
||||
};
|
||||
|
||||
static struct bin_attribute kone_profile5_attr = {
|
||||
.attr = { .name = "profile5", .mode = 0660 },
|
||||
.size = sizeof(struct kone_profile),
|
||||
.read = kone_sysfs_read_profile5,
|
||||
.write = kone_sysfs_write_profile5
|
||||
};
|
||||
|
||||
static int kone_create_sysfs_attributes(struct usb_interface *intf)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group);
|
||||
if (retval)
|
||||
goto exit_1;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr);
|
||||
if (retval)
|
||||
goto exit_2;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr);
|
||||
if (retval)
|
||||
goto exit_3;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr);
|
||||
if (retval)
|
||||
goto exit_4;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr);
|
||||
if (retval)
|
||||
goto exit_5;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr);
|
||||
if (retval)
|
||||
goto exit_6;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr);
|
||||
if (retval)
|
||||
goto exit_7;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_7:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
|
||||
exit_6:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
|
||||
exit_5:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
|
||||
exit_4:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
|
||||
exit_3:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
|
||||
exit_2:
|
||||
sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
|
||||
exit_1:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void kone_remove_sysfs_attributes(struct usb_interface *intf)
|
||||
{
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
|
||||
sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
|
||||
}
|
||||
|
||||
static int kone_init_kone_device_struct(struct usb_device *usb_dev,
|
||||
struct kone_device *kone)
|
||||
{
|
||||
|
@ -818,32 +716,25 @@ static int kone_init_specials(struct hid_device *hdev)
|
|||
|
||||
kone = kzalloc(sizeof(*kone), GFP_KERNEL);
|
||||
if (!kone) {
|
||||
dev_err(&hdev->dev, "can't alloc device descriptor\n");
|
||||
hid_err(hdev, "can't alloc device descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, kone);
|
||||
|
||||
retval = kone_init_kone_device_struct(usb_dev, kone);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev,
|
||||
"couldn't init struct kone_device\n");
|
||||
hid_err(hdev, "couldn't init struct kone_device\n");
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
retval = roccat_connect(hdev);
|
||||
retval = roccat_connect(kone_class, hdev);
|
||||
if (retval < 0) {
|
||||
dev_err(&hdev->dev, "couldn't init char dev\n");
|
||||
hid_err(hdev, "couldn't init char dev\n");
|
||||
/* be tolerant about not getting chrdev */
|
||||
} else {
|
||||
kone->roccat_claimed = 1;
|
||||
kone->chrdev_minor = retval;
|
||||
}
|
||||
|
||||
retval = kone_create_sysfs_attributes(intf);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "cannot create sysfs files\n");
|
||||
goto exit_free;
|
||||
}
|
||||
} else {
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
@ -854,7 +745,6 @@ exit_free:
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static void kone_remove_specials(struct hid_device *hdev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
|
@ -862,7 +752,6 @@ static void kone_remove_specials(struct hid_device *hdev)
|
|||
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol
|
||||
== USB_INTERFACE_PROTOCOL_MOUSE) {
|
||||
kone_remove_sysfs_attributes(intf);
|
||||
kone = hid_get_drvdata(hdev);
|
||||
if (kone->roccat_claimed)
|
||||
roccat_disconnect(kone->chrdev_minor);
|
||||
|
@ -876,19 +765,19 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = kone_init_specials(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "couldn't install mouse\n");
|
||||
hid_err(hdev, "couldn't install mouse\n");
|
||||
goto exit_stop;
|
||||
}
|
||||
|
||||
|
@ -1006,11 +895,24 @@ static struct hid_driver kone_driver = {
|
|||
|
||||
static int __init kone_init(void)
|
||||
{
|
||||
return hid_register_driver(&kone_driver);
|
||||
int retval;
|
||||
|
||||
/* class name has to be same as driver name */
|
||||
kone_class = class_create(THIS_MODULE, "kone");
|
||||
if (IS_ERR(kone_class))
|
||||
return PTR_ERR(kone_class);
|
||||
kone_class->dev_attrs = kone_attributes;
|
||||
kone_class->dev_bin_attrs = kone_bin_attributes;
|
||||
|
||||
retval = hid_register_driver(&kone_driver);
|
||||
if (retval)
|
||||
class_destroy(kone_class);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit kone_exit(void)
|
||||
{
|
||||
class_destroy(kone_class);
|
||||
hid_unregister_driver(&kone_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,11 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
struct kone_keystroke {
|
||||
uint8_t key;
|
||||
uint8_t action;
|
||||
uint16_t period; /* in milliseconds */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum kone_keystroke_buttons {
|
||||
kone_keystroke_button_1 = 0xf0, /* left mouse button */
|
||||
|
@ -44,7 +41,7 @@ struct kone_button_info {
|
|||
uint8_t macro_name[16]; /* can be max 15 chars long */
|
||||
uint8_t count;
|
||||
struct kone_keystroke keystrokes[20];
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum kone_button_info_types {
|
||||
/* valid button types until firmware 1.32 */
|
||||
|
@ -95,7 +92,7 @@ struct kone_light_info {
|
|||
uint8_t red; /* range 0x00-0xff */
|
||||
uint8_t green; /* range 0x00-0xff */
|
||||
uint8_t blue; /* range 0x00-0xff */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct kone_profile {
|
||||
uint16_t size; /* always 975 */
|
||||
|
@ -130,7 +127,7 @@ struct kone_profile {
|
|||
struct kone_button_info button_infos[8];
|
||||
|
||||
uint16_t checksum; /* \brief holds checksum of struct */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum kone_polling_rates {
|
||||
kone_polling_rate_125 = 1,
|
||||
|
@ -147,7 +144,7 @@ struct kone_settings {
|
|||
uint8_t calibration_data[4];
|
||||
uint8_t unknown3[2];
|
||||
uint16_t checksum;
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/*
|
||||
* 12 byte mouse event read by interrupt_read
|
||||
|
@ -163,7 +160,7 @@ struct kone_mouse_event {
|
|||
uint8_t event;
|
||||
uint8_t value; /* press = 0, release = 1 */
|
||||
uint8_t macro_key; /* 0 to 8 */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum kone_mouse_events {
|
||||
/* osd events are thought to be display on screen */
|
||||
|
@ -191,9 +188,7 @@ struct kone_roccat_report {
|
|||
uint8_t event;
|
||||
uint8_t value; /* holds dpi or profile value */
|
||||
uint8_t key; /* macro key on overlong macro execution */
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct kone_device {
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,837 @@
|
|||
/*
|
||||
* Roccat Kone[+] driver for Linux
|
||||
*
|
||||
* Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Roccat Kone[+] is an updated/improved version of the Kone with more memory
|
||||
* and functionality and without the non-standard behaviours the Kone had.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include "hid-ids.h"
|
||||
#include "hid-roccat.h"
|
||||
#include "hid-roccat-koneplus.h"
|
||||
|
||||
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
|
||||
|
||||
static struct class *koneplus_class;
|
||||
|
||||
static void koneplus_profile_activated(struct koneplus_device *koneplus,
|
||||
uint new_profile)
|
||||
{
|
||||
koneplus->actual_profile = new_profile;
|
||||
}
|
||||
|
||||
static int koneplus_send_control(struct usb_device *usb_dev, uint value,
|
||||
enum koneplus_control_requests request)
|
||||
{
|
||||
int len;
|
||||
struct koneplus_control *control;
|
||||
|
||||
if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
|
||||
request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
|
||||
value > 4)
|
||||
return -EINVAL;
|
||||
|
||||
control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
|
||||
if (!control)
|
||||
return -ENOMEM;
|
||||
|
||||
control->command = KONEPLUS_COMMAND_CONTROL;
|
||||
control->value = value;
|
||||
control->request = request;
|
||||
|
||||
len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
|
||||
USB_REQ_SET_CONFIGURATION,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
|
||||
KONEPLUS_USB_COMMAND_CONTROL, 0, control,
|
||||
sizeof(struct koneplus_control),
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
kfree(control);
|
||||
|
||||
if (len != sizeof(struct koneplus_control))
|
||||
return len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
|
||||
void *buf, uint size) {
|
||||
int len;
|
||||
|
||||
len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
|
||||
USB_REQ_CLEAR_FEATURE,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||
usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
return (len != size) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int koneplus_receive_control_status(struct usb_device *usb_dev)
|
||||
{
|
||||
int retval;
|
||||
struct koneplus_control *control;
|
||||
|
||||
control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
|
||||
if (!control)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
|
||||
control, sizeof(struct koneplus_control));
|
||||
|
||||
/* check if we get a completely wrong answer */
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
|
||||
retval = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* indicates that hardware needs some more time to complete action */
|
||||
if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
|
||||
msleep(500); /* windows driver uses 1000 */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* seems to be critical - replug necessary */
|
||||
if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
|
||||
"unknown response value 0x%x\n", control->value);
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
|
||||
} while (1);
|
||||
out:
|
||||
kfree(control);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int koneplus_send(struct usb_device *usb_dev, uint command,
|
||||
void *buf, uint size) {
|
||||
int len;
|
||||
|
||||
len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
|
||||
USB_REQ_SET_CONFIGURATION,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
|
||||
command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
if (len != size)
|
||||
return -EIO;
|
||||
|
||||
if (koneplus_receive_control_status(usb_dev))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
|
||||
enum koneplus_control_requests request)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = koneplus_send_control(usb_dev, number, request);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* allow time to settle things - windows driver uses 500 */
|
||||
msleep(100);
|
||||
|
||||
retval = koneplus_receive_control_status(usb_dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int koneplus_get_info(struct usb_device *usb_dev,
|
||||
struct koneplus_info *buf)
|
||||
{
|
||||
return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
|
||||
buf, sizeof(struct koneplus_info));
|
||||
}
|
||||
|
||||
static int koneplus_get_profile_settings(struct usb_device *usb_dev,
|
||||
struct koneplus_profile_settings *buf, uint number)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = koneplus_select_profile(usb_dev, number,
|
||||
KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
|
||||
buf, sizeof(struct koneplus_profile_settings));
|
||||
}
|
||||
|
||||
static int koneplus_set_profile_settings(struct usb_device *usb_dev,
|
||||
struct koneplus_profile_settings const *settings)
|
||||
{
|
||||
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
|
||||
(void *)settings, sizeof(struct koneplus_profile_settings));
|
||||
}
|
||||
|
||||
static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
|
||||
struct koneplus_profile_buttons *buf, int number)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = koneplus_select_profile(usb_dev, number,
|
||||
KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
|
||||
buf, sizeof(struct koneplus_profile_buttons));
|
||||
}
|
||||
|
||||
static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
|
||||
struct koneplus_profile_buttons const *buttons)
|
||||
{
|
||||
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
|
||||
(void *)buttons, sizeof(struct koneplus_profile_buttons));
|
||||
}
|
||||
|
||||
/* retval is 0-4 on success, < 0 on error */
|
||||
static int koneplus_get_startup_profile(struct usb_device *usb_dev)
|
||||
{
|
||||
struct koneplus_startup_profile *buf;
|
||||
int retval;
|
||||
|
||||
buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
|
||||
|
||||
retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
|
||||
buf, sizeof(struct koneplus_startup_profile));
|
||||
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
retval = buf->startup_profile;
|
||||
out:
|
||||
kfree(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int koneplus_set_startup_profile(struct usb_device *usb_dev,
|
||||
int startup_profile)
|
||||
{
|
||||
struct koneplus_startup_profile buf;
|
||||
|
||||
buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE;
|
||||
buf.size = sizeof(struct koneplus_startup_profile);
|
||||
buf.startup_profile = startup_profile;
|
||||
|
||||
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
|
||||
(char *)&buf, sizeof(struct koneplus_profile_buttons));
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
|
||||
char *buf, loff_t off, size_t count,
|
||||
size_t real_size, uint command)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval;
|
||||
|
||||
if (off != 0 || count != real_size)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
retval = koneplus_receive(usb_dev, command, buf, real_size);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return real_size;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
|
||||
void const *buf, loff_t off, size_t count,
|
||||
size_t real_size, uint command)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval;
|
||||
|
||||
if (off != 0 || count != real_size)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return real_size;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write_macro(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return koneplus_sysfs_write(fp, kobj, buf, off, count,
|
||||
sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return koneplus_sysfs_read(fp, kobj, buf, off, count,
|
||||
sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return koneplus_sysfs_write(fp, kobj, buf, off, count,
|
||||
sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return koneplus_sysfs_write(fp, kobj, buf, off, count,
|
||||
sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return koneplus_sysfs_read(fp, kobj, buf, off, count,
|
||||
sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct koneplus_profile_settings))
|
||||
return 0;
|
||||
|
||||
if (off + count > sizeof(struct koneplus_profile_settings))
|
||||
count = sizeof(struct koneplus_profile_settings) - off;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
|
||||
count);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0;
|
||||
int difference;
|
||||
int profile_number;
|
||||
struct koneplus_profile_settings *profile_settings;
|
||||
|
||||
if (off != 0 || count != sizeof(struct koneplus_profile_settings))
|
||||
return -EINVAL;
|
||||
|
||||
profile_number = ((struct koneplus_profile_settings const *)buf)->number;
|
||||
profile_settings = &koneplus->profile_settings[profile_number];
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
difference = memcmp(buf, profile_settings,
|
||||
sizeof(struct koneplus_profile_settings));
|
||||
if (difference) {
|
||||
retval = koneplus_set_profile_settings(usb_dev,
|
||||
(struct koneplus_profile_settings const *)buf);
|
||||
if (!retval)
|
||||
memcpy(profile_settings, buf,
|
||||
sizeof(struct koneplus_profile_settings));
|
||||
}
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return sizeof(struct koneplus_profile_settings);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct koneplus_profile_buttons))
|
||||
return 0;
|
||||
|
||||
if (off + count > sizeof(struct koneplus_profile_buttons))
|
||||
count = sizeof(struct koneplus_profile_buttons) - off;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
|
||||
count);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0;
|
||||
int difference;
|
||||
uint profile_number;
|
||||
struct koneplus_profile_buttons *profile_buttons;
|
||||
|
||||
if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
|
||||
return -EINVAL;
|
||||
|
||||
profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
|
||||
profile_buttons = &koneplus->profile_buttons[profile_number];
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
difference = memcmp(buf, profile_buttons,
|
||||
sizeof(struct koneplus_profile_buttons));
|
||||
if (difference) {
|
||||
retval = koneplus_set_profile_buttons(usb_dev,
|
||||
(struct koneplus_profile_buttons const *)buf);
|
||||
if (!retval)
|
||||
memcpy(profile_buttons, buf,
|
||||
sizeof(struct koneplus_profile_buttons));
|
||||
}
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return sizeof(struct koneplus_profile_buttons);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct koneplus_device *koneplus =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char const *buf, size_t size)
|
||||
{
|
||||
struct koneplus_device *koneplus;
|
||||
struct usb_device *usb_dev;
|
||||
unsigned long profile;
|
||||
int retval;
|
||||
|
||||
dev = dev->parent->parent;
|
||||
koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
|
||||
retval = strict_strtoul(buf, 10, &profile);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
retval = koneplus_set_startup_profile(usb_dev, profile);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct koneplus_device *koneplus =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct koneplus_device *koneplus =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
|
||||
}
|
||||
|
||||
static struct device_attribute koneplus_attributes[] = {
|
||||
__ATTR(startup_profile, 0660,
|
||||
koneplus_sysfs_show_startup_profile,
|
||||
koneplus_sysfs_set_startup_profile),
|
||||
__ATTR(actual_profile, 0440,
|
||||
koneplus_sysfs_show_actual_profile, NULL),
|
||||
__ATTR(firmware_version, 0440,
|
||||
koneplus_sysfs_show_firmware_version, NULL),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static struct bin_attribute koneplus_bin_attributes[] = {
|
||||
{
|
||||
.attr = { .name = "sensor", .mode = 0220 },
|
||||
.size = sizeof(struct koneplus_sensor),
|
||||
.read = koneplus_sysfs_read_sensor,
|
||||
.write = koneplus_sysfs_write_sensor
|
||||
},
|
||||
{
|
||||
.attr = { .name = "tcu", .mode = 0220 },
|
||||
.size = sizeof(struct koneplus_tcu),
|
||||
.write = koneplus_sysfs_write_tcu
|
||||
},
|
||||
{
|
||||
.attr = { .name = "tcu_image", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_tcu_image),
|
||||
.read = koneplus_sysfs_read_tcu_image
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile_settings", .mode = 0220 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.write = koneplus_sysfs_write_profile_settings
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_settings", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_settings", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_settings", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_settings", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_settings", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_settings),
|
||||
.read = koneplus_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile_buttons", .mode = 0220 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.write = koneplus_sysfs_write_profile_buttons
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct koneplus_profile_buttons),
|
||||
.read = koneplus_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "macro", .mode = 0220 },
|
||||
.size = sizeof(struct koneplus_macro),
|
||||
.write = koneplus_sysfs_write_macro
|
||||
},
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
|
||||
struct koneplus_device *koneplus)
|
||||
{
|
||||
int retval, i;
|
||||
static uint wait = 70; /* device will freeze with just 60 */
|
||||
|
||||
mutex_init(&koneplus->koneplus_lock);
|
||||
|
||||
koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
|
||||
|
||||
msleep(wait);
|
||||
retval = koneplus_get_info(usb_dev, &koneplus->info);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
msleep(wait);
|
||||
retval = koneplus_get_profile_settings(usb_dev,
|
||||
&koneplus->profile_settings[i], i);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
msleep(wait);
|
||||
retval = koneplus_get_profile_buttons(usb_dev,
|
||||
&koneplus->profile_buttons[i], i);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
koneplus_profile_activated(koneplus, koneplus->startup_profile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int koneplus_init_specials(struct hid_device *hdev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct usb_device *usb_dev = interface_to_usbdev(intf);
|
||||
struct koneplus_device *koneplus;
|
||||
int retval;
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol
|
||||
== USB_INTERFACE_PROTOCOL_MOUSE) {
|
||||
|
||||
koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
|
||||
if (!koneplus) {
|
||||
dev_err(&hdev->dev, "can't alloc device descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, koneplus);
|
||||
|
||||
retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev,
|
||||
"couldn't init struct koneplus_device\n");
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
retval = roccat_connect(koneplus_class, hdev);
|
||||
if (retval < 0) {
|
||||
dev_err(&hdev->dev, "couldn't init char dev\n");
|
||||
} else {
|
||||
koneplus->chrdev_minor = retval;
|
||||
koneplus->roccat_claimed = 1;
|
||||
}
|
||||
} else {
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
exit_free:
|
||||
kfree(koneplus);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void koneplus_remove_specials(struct hid_device *hdev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct koneplus_device *koneplus;
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol
|
||||
== USB_INTERFACE_PROTOCOL_MOUSE) {
|
||||
koneplus = hid_get_drvdata(hdev);
|
||||
if (koneplus->roccat_claimed)
|
||||
roccat_disconnect(koneplus->chrdev_minor);
|
||||
kfree(koneplus);
|
||||
}
|
||||
}
|
||||
|
||||
static int koneplus_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = koneplus_init_specials(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "couldn't install mouse\n");
|
||||
goto exit_stop;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_stop:
|
||||
hid_hw_stop(hdev);
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void koneplus_remove(struct hid_device *hdev)
|
||||
{
|
||||
koneplus_remove_specials(hdev);
|
||||
hid_hw_stop(hdev);
|
||||
}
|
||||
|
||||
static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus,
|
||||
u8 const *data)
|
||||
{
|
||||
struct koneplus_mouse_report_button const *button_report;
|
||||
|
||||
switch (data[0]) {
|
||||
case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON:
|
||||
button_report = (struct koneplus_mouse_report_button const *)data;
|
||||
switch (button_report->type) {
|
||||
case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE:
|
||||
koneplus_profile_activated(koneplus, button_report->data1 - 1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
|
||||
u8 const *data)
|
||||
{
|
||||
struct koneplus_roccat_report roccat_report;
|
||||
struct koneplus_mouse_report_button const *button_report;
|
||||
|
||||
if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON)
|
||||
return;
|
||||
|
||||
button_report = (struct koneplus_mouse_report_button const *)data;
|
||||
|
||||
if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
|
||||
button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) &&
|
||||
button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS)
|
||||
return;
|
||||
|
||||
roccat_report.type = button_report->type;
|
||||
roccat_report.data1 = button_report->data1;
|
||||
roccat_report.data2 = button_report->data2;
|
||||
roccat_report.profile = koneplus->actual_profile + 1;
|
||||
roccat_report_event(koneplus->chrdev_minor,
|
||||
(uint8_t const *)&roccat_report,
|
||||
sizeof(struct koneplus_roccat_report));
|
||||
}
|
||||
|
||||
static int koneplus_raw_event(struct hid_device *hdev,
|
||||
struct hid_report *report, u8 *data, int size)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct koneplus_device *koneplus = hid_get_drvdata(hdev);
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol
|
||||
!= USB_INTERFACE_PROTOCOL_MOUSE)
|
||||
return 0;
|
||||
|
||||
koneplus_keep_values_up_to_date(koneplus, data);
|
||||
|
||||
if (koneplus->roccat_claimed)
|
||||
koneplus_report_to_chrdev(koneplus, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_device_id koneplus_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(hid, koneplus_devices);
|
||||
|
||||
static struct hid_driver koneplus_driver = {
|
||||
.name = "koneplus",
|
||||
.id_table = koneplus_devices,
|
||||
.probe = koneplus_probe,
|
||||
.remove = koneplus_remove,
|
||||
.raw_event = koneplus_raw_event
|
||||
};
|
||||
|
||||
static int __init koneplus_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/* class name has to be same as driver name */
|
||||
koneplus_class = class_create(THIS_MODULE, "koneplus");
|
||||
if (IS_ERR(koneplus_class))
|
||||
return PTR_ERR(koneplus_class);
|
||||
koneplus_class->dev_attrs = koneplus_attributes;
|
||||
koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
|
||||
|
||||
retval = hid_register_driver(&koneplus_driver);
|
||||
if (retval)
|
||||
class_destroy(koneplus_class);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit koneplus_exit(void)
|
||||
{
|
||||
class_destroy(koneplus_class);
|
||||
hid_unregister_driver(&koneplus_driver);
|
||||
}
|
||||
|
||||
module_init(koneplus_init);
|
||||
module_exit(koneplus_exit);
|
||||
|
||||
MODULE_AUTHOR("Stefan Achatz");
|
||||
MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,224 @@
|
|||
#ifndef __HID_ROCCAT_KONEPLUS_H
|
||||
#define __HID_ROCCAT_KONEPLUS_H
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* case 1: writes request 80 and reads value 1
|
||||
*
|
||||
*/
|
||||
struct koneplus_control {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_CONTROL */
|
||||
/*
|
||||
* value is profile number in range 0-4 for requesting settings and buttons
|
||||
* 1 if status ok for requesting status
|
||||
*/
|
||||
uint8_t value;
|
||||
uint8_t request;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum koneplus_control_requests {
|
||||
KONEPLUS_CONTROL_REQUEST_STATUS = 0x00,
|
||||
KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
|
||||
KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90,
|
||||
};
|
||||
|
||||
enum koneplus_control_values {
|
||||
KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0,
|
||||
KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1,
|
||||
KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3,
|
||||
};
|
||||
|
||||
struct koneplus_startup_profile {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */
|
||||
uint8_t size; /* always 3 */
|
||||
uint8_t startup_profile; /* Range 0-4! */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_profile_settings {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
|
||||
uint8_t size; /* always 43 */
|
||||
uint8_t number; /* range 0-4 */
|
||||
uint8_t advanced_sensitivity;
|
||||
uint8_t sensitivity_x;
|
||||
uint8_t sensitivity_y;
|
||||
uint8_t cpi_levels_enabled;
|
||||
uint8_t cpi_levels_x[5];
|
||||
uint8_t cpi_startup_level; /* range 0-4 */
|
||||
uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
|
||||
uint8_t unknown1;
|
||||
uint8_t polling_rate;
|
||||
uint8_t lights_enabled;
|
||||
uint8_t light_effect_mode;
|
||||
uint8_t color_flow_effect;
|
||||
uint8_t light_effect_type;
|
||||
uint8_t light_effect_speed;
|
||||
uint8_t lights[16];
|
||||
uint16_t checksum;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_profile_buttons {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
|
||||
uint8_t size; /* always 77 */
|
||||
uint8_t number; /* range 0-4 */
|
||||
uint8_t data[72];
|
||||
uint16_t checksum;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_macro {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_MACRO */
|
||||
uint16_t size; /* always 0x822 little endian */
|
||||
uint8_t profile; /* range 0-4 */
|
||||
uint8_t button; /* range 0-23 */
|
||||
uint8_t data[2075];
|
||||
uint16_t checksum;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_info {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_INFO */
|
||||
uint8_t size; /* always 6 */
|
||||
uint8_t firmware_version;
|
||||
uint8_t unknown[3];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_e {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_E */
|
||||
uint8_t size; /* always 3 */
|
||||
uint8_t unknown; /* TODO 1; 0 before firmware update */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_sensor {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_SENSOR */
|
||||
uint8_t size; /* always 6 */
|
||||
uint8_t data[4];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_firmware_write {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
|
||||
uint8_t unknown[1025];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_firmware_write_control {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
|
||||
/*
|
||||
* value is 1 on success
|
||||
* 3 means "not finished yet"
|
||||
*/
|
||||
uint8_t value;
|
||||
uint8_t unknown; /* always 0x75 */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_tcu {
|
||||
uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
|
||||
uint8_t data[2];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_tcu_image {
|
||||
uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
|
||||
uint8_t data[1024];
|
||||
uint16_t checksum;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum koneplus_commands {
|
||||
KONEPLUS_COMMAND_CONTROL = 0x4,
|
||||
KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5,
|
||||
KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
|
||||
KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
|
||||
KONEPLUS_COMMAND_MACRO = 0x8,
|
||||
KONEPLUS_COMMAND_INFO = 0x9,
|
||||
KONEPLUS_COMMAND_E = 0xe,
|
||||
KONEPLUS_COMMAND_SENSOR = 0xf,
|
||||
KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b,
|
||||
KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
|
||||
};
|
||||
|
||||
enum koneplus_usb_commands {
|
||||
KONEPLUS_USB_COMMAND_CONTROL = 0x304,
|
||||
KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305,
|
||||
KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
|
||||
KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
|
||||
KONEPLUS_USB_COMMAND_MACRO = 0x308,
|
||||
KONEPLUS_USB_COMMAND_INFO = 0x309,
|
||||
KONEPLUS_USB_COMMAND_TCU = 0x30c,
|
||||
KONEPLUS_USB_COMMAND_E = 0x30e,
|
||||
KONEPLUS_USB_COMMAND_SENSOR = 0x30f,
|
||||
KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b,
|
||||
KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c,
|
||||
};
|
||||
|
||||
enum koneplus_mouse_report_numbers {
|
||||
KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1,
|
||||
KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
|
||||
KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
|
||||
};
|
||||
|
||||
struct koneplus_mouse_report_button {
|
||||
uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */
|
||||
uint8_t zero1;
|
||||
uint8_t type;
|
||||
uint8_t data1;
|
||||
uint8_t data2;
|
||||
uint8_t zero2;
|
||||
uint8_t unknown[2];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum koneplus_mouse_report_button_types {
|
||||
/* data1 = new profile range 1-5 */
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20,
|
||||
|
||||
/* data1 = button number range 1-24; data2 = action */
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
|
||||
|
||||
/* data1 = button number range 1-24; data2 = action */
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
|
||||
|
||||
/* data1 = setting number range 1-5 */
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
|
||||
|
||||
/* data1 and data2 = range 0x1-0xb */
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
|
||||
|
||||
/* data1 = 22 = next track...
|
||||
* data2 = action
|
||||
*/
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
|
||||
};
|
||||
|
||||
enum koneplus_mouse_report_button_action {
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
|
||||
KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
|
||||
};
|
||||
|
||||
struct koneplus_roccat_report {
|
||||
uint8_t type;
|
||||
uint8_t data1;
|
||||
uint8_t data2;
|
||||
uint8_t profile;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_device {
|
||||
int actual_profile;
|
||||
|
||||
int roccat_claimed;
|
||||
int chrdev_minor;
|
||||
|
||||
struct mutex koneplus_lock;
|
||||
|
||||
int startup_profile;
|
||||
struct koneplus_info info;
|
||||
struct koneplus_profile_settings profile_settings[5];
|
||||
struct koneplus_profile_buttons profile_buttons[5];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,6 +27,11 @@
|
|||
#include "hid-roccat.h"
|
||||
#include "hid-roccat-pyra.h"
|
||||
|
||||
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
|
||||
|
||||
/* pyra_class is used for creating sysfs attributes via roccat char device */
|
||||
static struct class *pyra_class;
|
||||
|
||||
static void profile_activated(struct pyra_device *pyra,
|
||||
unsigned int new_profile)
|
||||
{
|
||||
|
@ -87,9 +92,8 @@ static int pyra_receive_control_status(struct usb_device *usb_dev)
|
|||
control.value == 1)
|
||||
return 0;
|
||||
else {
|
||||
dev_err(&usb_dev->dev, "receive control status: "
|
||||
"unknown response 0x%x 0x%x\n",
|
||||
control.request, control.value);
|
||||
hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
|
||||
control.request, control.value);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -221,9 +225,10 @@ static int pyra_set_settings(struct usb_device *usb_dev,
|
|||
|
||||
static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, int number)
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct pyra_profile_settings))
|
||||
|
@ -233,58 +238,19 @@ static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
|
|||
count = sizeof(struct pyra_profile_settings) - off;
|
||||
|
||||
mutex_lock(&pyra->pyra_lock);
|
||||
memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off,
|
||||
memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off,
|
||||
count);
|
||||
mutex_unlock(&pyra->pyra_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_settings(fp, kobj,
|
||||
attr, buf, off, count, 0);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_settings(fp, kobj,
|
||||
attr, buf, off, count, 1);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_settings(fp, kobj,
|
||||
attr, buf, off, count, 2);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_settings(fp, kobj,
|
||||
attr, buf, off, count, 3);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_settings(fp, kobj,
|
||||
attr, buf, off, count, 4);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, int number)
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct pyra_profile_buttons))
|
||||
|
@ -294,58 +260,19 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
|
|||
count = sizeof(struct pyra_profile_buttons) - off;
|
||||
|
||||
mutex_lock(&pyra->pyra_lock);
|
||||
memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off,
|
||||
memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off,
|
||||
count);
|
||||
mutex_unlock(&pyra->pyra_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_buttons(fp, kobj,
|
||||
attr, buf, off, count, 0);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_buttons(fp, kobj,
|
||||
attr, buf, off, count, 1);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_buttons(fp, kobj,
|
||||
attr, buf, off, count, 2);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_buttons(fp, kobj,
|
||||
attr, buf, off, count, 3);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pyra_sysfs_read_profilex_buttons(fp, kobj,
|
||||
attr, buf, off, count, 4);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_write_profile_settings(struct file *fp,
|
||||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0;
|
||||
|
@ -381,7 +308,8 @@ static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp,
|
|||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0;
|
||||
|
@ -417,7 +345,8 @@ static ssize_t pyra_sysfs_read_settings(struct file *fp,
|
|||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
|
||||
if (off >= sizeof(struct pyra_settings))
|
||||
|
@ -437,7 +366,8 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
|
|||
struct kobject *kobj, struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev =
|
||||
container_of(kobj, struct device, kobj)->parent->parent;
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
|
||||
int retval = 0;
|
||||
|
@ -469,255 +399,125 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
|
|||
static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct pyra_device *pyra =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct pyra_device *pyra =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct pyra_device *pyra =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
|
||||
}
|
||||
|
||||
static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
struct pyra_device *pyra =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
|
||||
|
||||
static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
|
||||
|
||||
static DEVICE_ATTR(firmware_version, 0440,
|
||||
pyra_sysfs_show_firmware_version, NULL);
|
||||
|
||||
static DEVICE_ATTR(startup_profile, 0440,
|
||||
pyra_sysfs_show_startup_profile, NULL);
|
||||
|
||||
static struct attribute *pyra_attributes[] = {
|
||||
&dev_attr_actual_cpi.attr,
|
||||
&dev_attr_actual_profile.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
&dev_attr_startup_profile.attr,
|
||||
NULL
|
||||
static struct device_attribute pyra_attributes[] = {
|
||||
__ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL),
|
||||
__ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL),
|
||||
__ATTR(firmware_version, 0440,
|
||||
pyra_sysfs_show_firmware_version, NULL),
|
||||
__ATTR(startup_profile, 0440,
|
||||
pyra_sysfs_show_startup_profile, NULL),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static struct attribute_group pyra_attribute_group = {
|
||||
.attrs = pyra_attributes
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile_settings_attr = {
|
||||
static struct bin_attribute pyra_bin_attributes[] = {
|
||||
{
|
||||
.attr = { .name = "profile_settings", .mode = 0220 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.write = pyra_sysfs_write_profile_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile1_settings_attr = {
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_settings", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.read = pyra_sysfs_read_profile1_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile2_settings_attr = {
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_settings", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.read = pyra_sysfs_read_profile2_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile3_settings_attr = {
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_settings", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.read = pyra_sysfs_read_profile3_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile4_settings_attr = {
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_settings", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.read = pyra_sysfs_read_profile4_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile5_settings_attr = {
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_settings", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_settings),
|
||||
.read = pyra_sysfs_read_profile5_settings
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile_buttons_attr = {
|
||||
.read = pyra_sysfs_read_profilex_settings,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile_buttons", .mode = 0220 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.write = pyra_sysfs_write_profile_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile1_buttons_attr = {
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile1_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.read = pyra_sysfs_read_profile1_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile2_buttons_attr = {
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[0]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile2_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.read = pyra_sysfs_read_profile2_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile3_buttons_attr = {
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[1]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile3_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.read = pyra_sysfs_read_profile3_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile4_buttons_attr = {
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[2]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile4_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.read = pyra_sysfs_read_profile4_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_profile5_buttons_attr = {
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[3]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "profile5_buttons", .mode = 0440 },
|
||||
.size = sizeof(struct pyra_profile_buttons),
|
||||
.read = pyra_sysfs_read_profile5_buttons
|
||||
};
|
||||
|
||||
static struct bin_attribute pyra_settings_attr = {
|
||||
.read = pyra_sysfs_read_profilex_buttons,
|
||||
.private = &profile_numbers[4]
|
||||
},
|
||||
{
|
||||
.attr = { .name = "settings", .mode = 0660 },
|
||||
.size = sizeof(struct pyra_settings),
|
||||
.read = pyra_sysfs_read_settings,
|
||||
.write = pyra_sysfs_write_settings
|
||||
},
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static int pyra_create_sysfs_attributes(struct usb_interface *intf)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group);
|
||||
if (retval)
|
||||
goto exit_1;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile_settings_attr);
|
||||
if (retval)
|
||||
goto exit_2;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile1_settings_attr);
|
||||
if (retval)
|
||||
goto exit_3;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile2_settings_attr);
|
||||
if (retval)
|
||||
goto exit_4;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile3_settings_attr);
|
||||
if (retval)
|
||||
goto exit_5;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile4_settings_attr);
|
||||
if (retval)
|
||||
goto exit_6;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile5_settings_attr);
|
||||
if (retval)
|
||||
goto exit_7;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_8;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile1_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_9;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile2_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_10;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile3_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_11;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile4_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_12;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_profile5_buttons_attr);
|
||||
if (retval)
|
||||
goto exit_13;
|
||||
|
||||
retval = sysfs_create_bin_file(&intf->dev.kobj,
|
||||
&pyra_settings_attr);
|
||||
if (retval)
|
||||
goto exit_14;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_14:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
|
||||
exit_13:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
|
||||
exit_12:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
|
||||
exit_11:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
|
||||
exit_10:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
|
||||
exit_9:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
|
||||
exit_8:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
|
||||
exit_7:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
|
||||
exit_6:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
|
||||
exit_5:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
|
||||
exit_4:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
|
||||
exit_3:
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
|
||||
exit_2:
|
||||
sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
|
||||
exit_1:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pyra_remove_sysfs_attributes(struct usb_interface *intf)
|
||||
{
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
|
||||
sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
|
||||
sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
|
||||
}
|
||||
|
||||
static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
|
||||
struct pyra_device *pyra)
|
||||
{
|
||||
|
@ -770,31 +570,24 @@ static int pyra_init_specials(struct hid_device *hdev)
|
|||
|
||||
pyra = kzalloc(sizeof(*pyra), GFP_KERNEL);
|
||||
if (!pyra) {
|
||||
dev_err(&hdev->dev, "can't alloc device descriptor\n");
|
||||
hid_err(hdev, "can't alloc device descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, pyra);
|
||||
|
||||
retval = pyra_init_pyra_device_struct(usb_dev, pyra);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev,
|
||||
"couldn't init struct pyra_device\n");
|
||||
hid_err(hdev, "couldn't init struct pyra_device\n");
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
retval = roccat_connect(hdev);
|
||||
retval = roccat_connect(pyra_class, hdev);
|
||||
if (retval < 0) {
|
||||
dev_err(&hdev->dev, "couldn't init char dev\n");
|
||||
hid_err(hdev, "couldn't init char dev\n");
|
||||
} else {
|
||||
pyra->chrdev_minor = retval;
|
||||
pyra->roccat_claimed = 1;
|
||||
}
|
||||
|
||||
retval = pyra_create_sysfs_attributes(intf);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "cannot create sysfs files\n");
|
||||
goto exit_free;
|
||||
}
|
||||
} else {
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
@ -812,7 +605,6 @@ static void pyra_remove_specials(struct hid_device *hdev)
|
|||
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol
|
||||
== USB_INTERFACE_PROTOCOL_MOUSE) {
|
||||
pyra_remove_sysfs_attributes(intf);
|
||||
pyra = hid_get_drvdata(hdev);
|
||||
if (pyra->roccat_claimed)
|
||||
roccat_disconnect(pyra->chrdev_minor);
|
||||
|
@ -826,19 +618,19 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = pyra_init_specials(hdev);
|
||||
if (retval) {
|
||||
dev_err(&hdev->dev, "couldn't install mouse\n");
|
||||
hid_err(hdev, "couldn't install mouse\n");
|
||||
goto exit_stop;
|
||||
}
|
||||
return 0;
|
||||
|
@ -952,11 +744,24 @@ static struct hid_driver pyra_driver = {
|
|||
|
||||
static int __init pyra_init(void)
|
||||
{
|
||||
return hid_register_driver(&pyra_driver);
|
||||
int retval;
|
||||
|
||||
/* class name has to be same as driver name */
|
||||
pyra_class = class_create(THIS_MODULE, "pyra");
|
||||
if (IS_ERR(pyra_class))
|
||||
return PTR_ERR(pyra_class);
|
||||
pyra_class->dev_attrs = pyra_attributes;
|
||||
pyra_class->dev_bin_attrs = pyra_bin_attributes;
|
||||
|
||||
retval = hid_register_driver(&pyra_driver);
|
||||
if (retval)
|
||||
class_destroy(pyra_class);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit pyra_exit(void)
|
||||
{
|
||||
class_destroy(pyra_class);
|
||||
hid_unregister_driver(&pyra_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,11 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
struct pyra_b {
|
||||
uint8_t command; /* PYRA_COMMAND_B */
|
||||
uint8_t size; /* always 3 */
|
||||
uint8_t unknown; /* 1 */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_control {
|
||||
uint8_t command; /* PYRA_COMMAND_CONTROL */
|
||||
|
@ -31,7 +28,7 @@ struct pyra_control {
|
|||
*/
|
||||
uint8_t value; /* Range 0-4 */
|
||||
uint8_t request;
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum pyra_control_requests {
|
||||
PYRA_CONTROL_REQUEST_STATUS = 0x00,
|
||||
|
@ -43,7 +40,7 @@ struct pyra_settings {
|
|||
uint8_t command; /* PYRA_COMMAND_SETTINGS */
|
||||
uint8_t size; /* always 3 */
|
||||
uint8_t startup_profile; /* Range 0-4! */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_profile_settings {
|
||||
uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */
|
||||
|
@ -58,7 +55,7 @@ struct pyra_profile_settings {
|
|||
uint8_t light_effect;
|
||||
uint8_t handedness;
|
||||
uint16_t checksum; /* byte sum */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_profile_buttons {
|
||||
uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
|
||||
|
@ -66,7 +63,7 @@ struct pyra_profile_buttons {
|
|||
uint8_t number; /* Range 0-4 */
|
||||
uint8_t buttons[14];
|
||||
uint16_t checksum; /* byte sum */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_info {
|
||||
uint8_t command; /* PYRA_COMMAND_INFO */
|
||||
|
@ -75,7 +72,7 @@ struct pyra_info {
|
|||
uint8_t unknown1; /* always 0 */
|
||||
uint8_t unknown2; /* always 1 */
|
||||
uint8_t unknown3; /* always 0 */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum pyra_commands {
|
||||
PYRA_COMMAND_CONTROL = 0x4,
|
||||
|
@ -107,13 +104,13 @@ struct pyra_mouse_event_button {
|
|||
uint8_t type;
|
||||
uint8_t data1;
|
||||
uint8_t data2;
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_mouse_event_audio {
|
||||
uint8_t report_number; /* always 2 */
|
||||
uint8_t type;
|
||||
uint8_t unused; /* always 0 */
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* hid audio controls */
|
||||
enum pyra_mouse_event_audio_types {
|
||||
|
@ -167,9 +164,7 @@ struct pyra_roccat_report {
|
|||
uint8_t type;
|
||||
uint8_t value;
|
||||
uint8_t key;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct pyra_device {
|
||||
int actual_profile;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
* It is inspired by hidraw, but uses only one circular buffer for all readers.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -65,7 +67,6 @@ struct roccat_reader {
|
|||
};
|
||||
|
||||
static int roccat_major;
|
||||
static struct class *roccat_class;
|
||||
static struct cdev roccat_cdev;
|
||||
|
||||
static struct roccat_device *devices[ROCCAT_MAX_DEVICES];
|
||||
|
@ -165,27 +166,22 @@ static int roccat_open(struct inode *inode, struct file *file)
|
|||
mutex_lock(&device->readers_lock);
|
||||
|
||||
if (!device) {
|
||||
printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
|
||||
minor);
|
||||
pr_emerg("roccat device with minor %d doesn't exist\n", minor);
|
||||
error = -ENODEV;
|
||||
goto exit_err;
|
||||
}
|
||||
|
||||
if (!device->open++) {
|
||||
/* power on device on adding first reader */
|
||||
if (device->hid->ll_driver->power) {
|
||||
error = device->hid->ll_driver->power(device->hid,
|
||||
PM_HINT_FULLON);
|
||||
if (error < 0) {
|
||||
--device->open;
|
||||
goto exit_err;
|
||||
}
|
||||
}
|
||||
error = device->hid->ll_driver->open(device->hid);
|
||||
error = hid_hw_power(device->hid, PM_HINT_FULLON);
|
||||
if (error < 0) {
|
||||
if (device->hid->ll_driver->power)
|
||||
device->hid->ll_driver->power(device->hid,
|
||||
PM_HINT_NORMAL);
|
||||
--device->open;
|
||||
goto exit_err;
|
||||
}
|
||||
|
||||
error = hid_hw_open(device->hid);
|
||||
if (error < 0) {
|
||||
hid_hw_power(device->hid, PM_HINT_NORMAL);
|
||||
--device->open;
|
||||
goto exit_err;
|
||||
}
|
||||
|
@ -218,8 +214,7 @@ static int roccat_release(struct inode *inode, struct file *file)
|
|||
device = devices[minor];
|
||||
if (!device) {
|
||||
mutex_unlock(&devices_lock);
|
||||
printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
|
||||
minor);
|
||||
pr_emerg("roccat device with minor %d doesn't exist\n", minor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -231,10 +226,8 @@ static int roccat_release(struct inode *inode, struct file *file)
|
|||
if (!--device->open) {
|
||||
/* removing last reader */
|
||||
if (device->exist) {
|
||||
if (device->hid->ll_driver->power)
|
||||
device->hid->ll_driver->power(device->hid,
|
||||
PM_HINT_NORMAL);
|
||||
device->hid->ll_driver->close(device->hid);
|
||||
hid_hw_power(device->hid, PM_HINT_NORMAL);
|
||||
hid_hw_close(device->hid);
|
||||
} else {
|
||||
kfree(device);
|
||||
}
|
||||
|
@ -295,12 +288,14 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
|
|||
|
||||
/*
|
||||
* roccat_connect() - create a char device for special event output
|
||||
* @class: the class thats used to create the device. Meant to hold device
|
||||
* specific sysfs attributes.
|
||||
* @hid: the hid device the char device should be connected to.
|
||||
*
|
||||
* Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
|
||||
* success, a negative error code on failure.
|
||||
*/
|
||||
int roccat_connect(struct hid_device *hid)
|
||||
int roccat_connect(struct class *klass, struct hid_device *hid)
|
||||
{
|
||||
unsigned int minor;
|
||||
struct roccat_device *device;
|
||||
|
@ -326,7 +321,7 @@ int roccat_connect(struct hid_device *hid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
device->dev = device_create(roccat_class, &hid->dev,
|
||||
device->dev = device_create(klass, &hid->dev,
|
||||
MKDEV(roccat_major, minor), NULL,
|
||||
"%s%s%d", "roccat", hid->driver->name, minor);
|
||||
|
||||
|
@ -367,10 +362,10 @@ void roccat_disconnect(int minor)
|
|||
|
||||
device->exist = 0; /* TODO exist maybe not needed */
|
||||
|
||||
device_destroy(roccat_class, MKDEV(roccat_major, minor));
|
||||
device_destroy(device->dev->class, MKDEV(roccat_major, minor));
|
||||
|
||||
if (device->open) {
|
||||
device->hid->ll_driver->close(device->hid);
|
||||
hid_hw_close(device->hid);
|
||||
wake_up_interruptible(&device->wait);
|
||||
} else {
|
||||
kfree(device);
|
||||
|
@ -398,14 +393,7 @@ static int __init roccat_init(void)
|
|||
roccat_major = MAJOR(dev_id);
|
||||
|
||||
if (retval < 0) {
|
||||
printk(KERN_WARNING "roccat: can't get major number\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
roccat_class = class_create(THIS_MODULE, "roccat");
|
||||
if (IS_ERR(roccat_class)) {
|
||||
retval = PTR_ERR(roccat_class);
|
||||
unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
|
||||
pr_warn("can't get major number\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -420,7 +408,6 @@ static void __exit roccat_exit(void)
|
|||
dev_t dev_id = MKDEV(roccat_major, 0);
|
||||
|
||||
cdev_del(&roccat_cdev);
|
||||
class_destroy(roccat_class);
|
||||
unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
#if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE)
|
||||
int roccat_connect(struct hid_device *hid);
|
||||
int roccat_connect(struct class *klass, struct hid_device *hid);
|
||||
void roccat_disconnect(int minor);
|
||||
int roccat_report_event(int minor, u8 const *data, int len);
|
||||
#else
|
||||
static inline int roccat_connect(struct hid_device *hid) { return -1; }
|
||||
static inline int roccat_connect(struct class *klass,
|
||||
struct hid_device *hid) { return -1; }
|
||||
static inline void roccat_disconnect(int minor) {}
|
||||
static inline int roccat_report_event(int minor, u8 const *data, int len)
|
||||
{
|
||||
|
|
|
@ -57,8 +57,8 @@
|
|||
static inline void samsung_irda_dev_trace(struct hid_device *hdev,
|
||||
unsigned int rsize)
|
||||
{
|
||||
dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
|
||||
"descriptor\n", rsize);
|
||||
hid_info(hdev, "fixing up Samsung IrDA %d byte report descriptor\n",
|
||||
rsize);
|
||||
}
|
||||
|
||||
static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
|
@ -160,7 +160,7 @@ static int samsung_probe(struct hid_device *hdev,
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ static int samsung_probe(struct hid_device *hdev,
|
|||
|
||||
ret = hid_hw_start(hdev, cmask);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,26 +74,25 @@ static int sjoyff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
hid_err(hid, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report_ptr = report_ptr->next;
|
||||
|
||||
if (report_ptr == report_list) {
|
||||
dev_err(&hid->dev, "required output report is "
|
||||
"missing\n");
|
||||
hid_err(hid, "required output report is missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_entry(report_ptr, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "no fields in the report\n");
|
||||
hid_err(hid, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 3) {
|
||||
dev_err(&hid->dev, "not enough values in the field\n");
|
||||
hid_err(hid, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -117,8 +116,7 @@ static int sjoyff_init(struct hid_device *hid)
|
|||
sjoyff->report->field[0]->value[2] = 0x00;
|
||||
usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev,
|
||||
"Force feedback for SmartJoy PLUS PS2/USB adapter\n");
|
||||
hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -135,13 +133,13 @@ static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,7 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
|
||||
*rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
|
||||
dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
|
||||
rdesc[55] = 0x06;
|
||||
}
|
||||
return rdesc;
|
||||
|
@ -89,7 +88,7 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
|
|||
(3 << 8) | 0xf2, ifnum, buf, 17,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
if (ret < 0)
|
||||
dev_err(&hdev->dev, "can't set operational mode\n");
|
||||
hid_err(hdev, "can't set operational mode\n");
|
||||
|
||||
kfree(buf);
|
||||
|
||||
|
@ -110,7 +109,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
sc = kzalloc(sizeof(*sc), GFP_KERNEL);
|
||||
if (sc == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc sony descriptor\n");
|
||||
hid_err(hdev, "can't alloc sony descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -119,14 +118,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
|
||||
HID_CONNECT_HIDDEV_FORCE);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ static int stantum_probe(struct hid_device *hdev,
|
|||
|
||||
sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
|
||||
if (!sd) {
|
||||
dev_err(&hdev->dev, "cannot allocate Stantum data\n");
|
||||
hid_err(hdev, "cannot allocate Stantum data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sd->valid = false;
|
||||
|
|
|
@ -27,8 +27,7 @@ static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
{
|
||||
if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
|
||||
rdesc[106] == 0x03) {
|
||||
dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop "
|
||||
"report descriptor\n");
|
||||
hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n");
|
||||
rdesc[105] = rdesc[110] = 0x03;
|
||||
rdesc[106] = rdesc[111] = 0x21;
|
||||
}
|
||||
|
|
|
@ -151,28 +151,23 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
|
|||
switch (field->usage[0].hid) {
|
||||
case THRUSTMASTER_USAGE_FF:
|
||||
if (field->report_count < 2) {
|
||||
dev_warn(&hid->dev, "ignoring FF field "
|
||||
"with report_count < 2\n");
|
||||
hid_warn(hid, "ignoring FF field with report_count < 2\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field->logical_maximum ==
|
||||
field->logical_minimum) {
|
||||
dev_warn(&hid->dev, "ignoring FF field "
|
||||
"with logical_maximum "
|
||||
"== logical_minimum\n");
|
||||
hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmff->report && tmff->report != report) {
|
||||
dev_warn(&hid->dev, "ignoring FF field "
|
||||
"in other report\n");
|
||||
hid_warn(hid, "ignoring FF field in other report\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmff->ff_field && tmff->ff_field != field) {
|
||||
dev_warn(&hid->dev, "ignoring "
|
||||
"duplicate FF field\n");
|
||||
hid_warn(hid, "ignoring duplicate FF field\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -185,16 +180,15 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
|
|||
break;
|
||||
|
||||
default:
|
||||
dev_warn(&hid->dev, "ignoring unknown output "
|
||||
"usage %08x\n",
|
||||
field->usage[0].hid);
|
||||
hid_warn(hid, "ignoring unknown output usage %08x\n",
|
||||
field->usage[0].hid);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tmff->report) {
|
||||
dev_err(&hid->dev, "can't find FF field in output reports\n");
|
||||
hid_err(hid, "can't find FF field in output reports\n");
|
||||
error = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -203,8 +197,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
|
|||
if (error)
|
||||
goto fail;
|
||||
|
||||
dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx "
|
||||
"Verituse <zinx@epicsol.org>");
|
||||
hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n");
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -224,13 +217,13 @@ static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ static const struct hid_device_id ts_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ts_devices);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -141,8 +143,8 @@ static void wacom_poke(struct hid_device *hdev, u8 speed)
|
|||
* Note that if the raw queries fail, it's not a hard failure and it
|
||||
* is safe to continue
|
||||
*/
|
||||
dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n",
|
||||
rep_data[0], ret);
|
||||
hid_warn(hdev, "failed to poke device, command %d, err %d\n",
|
||||
rep_data[0], ret);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -172,7 +174,7 @@ static ssize_t wacom_store_speed(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO,
|
||||
static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
wacom_show_speed, wacom_store_speed);
|
||||
|
||||
static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||
|
@ -312,7 +314,7 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
|
||||
wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
|
||||
if (wdata == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
|
||||
hid_err(hdev, "can't alloc wacom descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -321,20 +323,20 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
/* Parse the HID report now */
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = device_create_file(&hdev->dev, &dev_attr_speed);
|
||||
if (ret)
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create sysfs speed attribute err: %d\n", ret);
|
||||
hid_warn(hdev,
|
||||
"can't create sysfs speed attribute err: %d\n", ret);
|
||||
|
||||
/* Set Wacom mode 2 with high reporting speed */
|
||||
wacom_poke(hdev, 1);
|
||||
|
@ -349,8 +351,8 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
|
||||
ret = power_supply_register(&hdev->dev, &wdata->battery);
|
||||
if (ret) {
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create sysfs battery attribute, err: %d\n", ret);
|
||||
hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
|
||||
ret);
|
||||
/*
|
||||
* battery attribute is not critical for the tablet, but if it
|
||||
* failed then there is no need to create ac attribute
|
||||
|
@ -367,8 +369,8 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
|
||||
ret = power_supply_register(&hdev->dev, &wdata->ac);
|
||||
if (ret) {
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create ac battery attribute, err: %d\n", ret);
|
||||
hid_warn(hdev,
|
||||
"can't create ac battery attribute, err: %d\n", ret);
|
||||
/*
|
||||
* ac attribute is not critical for the tablet, but if it
|
||||
* failed then we don't want to battery attribute to exist
|
||||
|
@ -454,7 +456,7 @@ static int __init wacom_init(void)
|
|||
|
||||
ret = hid_register_driver(&wacom_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "can't register wacom driver\n");
|
||||
pr_err("can't register wacom driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,14 +75,14 @@ static int zpff_init(struct hid_device *hid)
|
|||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output report found\n");
|
||||
hid_err(hid, "no output report found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
|
||||
if (report->maxfield < 4) {
|
||||
dev_err(&hid->dev, "not enough fields in report\n");
|
||||
hid_err(hid, "not enough fields in report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,7 @@ static int zpff_init(struct hid_device *hid)
|
|||
zpff->report->field[3]->value[0] = 0x00;
|
||||
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "force feedback for Zeroplus based devices by "
|
||||
"Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -123,13 +122,13 @@ static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,8 @@ static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff &&
|
||||
rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff &&
|
||||
rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) {
|
||||
dev_info(&hdev->dev,
|
||||
"fixing up zydacron remote control report "
|
||||
"descriptor\n");
|
||||
hid_info(hdev,
|
||||
"fixing up zydacron remote control report descriptor\n");
|
||||
rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c;
|
||||
rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00;
|
||||
}
|
||||
|
@ -172,7 +171,7 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
zc = kzalloc(sizeof(*zc), GFP_KERNEL);
|
||||
if (zc == NULL) {
|
||||
dev_err(&hdev->dev, "zydacron: can't alloc descriptor\n");
|
||||
hid_err(hdev, "can't alloc descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -180,13 +179,13 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "zydacron: parse failed\n");
|
||||
hid_err(hdev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "zydacron: hw start failed\n");
|
||||
hid_err(hdev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
|
@ -122,15 +124,15 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
|
|||
}
|
||||
|
||||
if (count > HID_MAX_BUFFER_SIZE) {
|
||||
printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
|
||||
task_pid_nr(current));
|
||||
hid_warn(dev, "pid %d passed too large report\n",
|
||||
task_pid_nr(current));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (count < 2) {
|
||||
printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
|
||||
task_pid_nr(current));
|
||||
hid_warn(dev, "pid %d passed too short report\n",
|
||||
task_pid_nr(current));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -192,15 +194,13 @@ static int hidraw_open(struct inode *inode, struct file *file)
|
|||
|
||||
dev = hidraw_table[minor];
|
||||
if (!dev->open++) {
|
||||
if (dev->hid->ll_driver->power) {
|
||||
err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON);
|
||||
if (err < 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
err = dev->hid->ll_driver->open(dev->hid);
|
||||
err = hid_hw_power(dev->hid, PM_HINT_FULLON);
|
||||
if (err < 0)
|
||||
goto out_unlock;
|
||||
|
||||
err = hid_hw_open(dev->hid);
|
||||
if (err < 0) {
|
||||
if (dev->hid->ll_driver->power)
|
||||
dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
|
||||
hid_hw_power(dev->hid, PM_HINT_NORMAL);
|
||||
dev->open--;
|
||||
}
|
||||
}
|
||||
|
@ -229,9 +229,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
|
|||
dev = hidraw_table[minor];
|
||||
if (!--dev->open) {
|
||||
if (list->hidraw->exist) {
|
||||
if (dev->hid->ll_driver->power)
|
||||
dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
|
||||
dev->hid->ll_driver->close(dev->hid);
|
||||
hid_hw_power(dev->hid, PM_HINT_NORMAL);
|
||||
hid_hw_close(dev->hid);
|
||||
} else {
|
||||
kfree(list->hidraw);
|
||||
}
|
||||
|
@ -345,6 +344,9 @@ static const struct file_operations hidraw_ops = {
|
|||
.open = hidraw_open,
|
||||
.release = hidraw_release,
|
||||
.unlocked_ioctl = hidraw_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = hidraw_ioctl,
|
||||
#endif
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
|
@ -433,7 +435,7 @@ void hidraw_disconnect(struct hid_device *hid)
|
|||
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
|
||||
|
||||
if (hidraw->open) {
|
||||
hid->ll_driver->close(hid);
|
||||
hid_hw_close(hid);
|
||||
wake_up_interruptible(&hidraw->wait);
|
||||
} else {
|
||||
kfree(hidraw);
|
||||
|
@ -452,7 +454,7 @@ int __init hidraw_init(void)
|
|||
hidraw_major = MAJOR(dev_id);
|
||||
|
||||
if (result < 0) {
|
||||
printk(KERN_WARNING "hidraw: can't get major number\n");
|
||||
pr_warn("can't get major number\n");
|
||||
result = 0;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
#
|
||||
|
||||
# Multipart objects.
|
||||
usbhid-objs := hid-core.o hid-quirks.o
|
||||
usbhid-y := hid-core.o hid-quirks.o
|
||||
|
||||
# Optional parts of multipart objects.
|
||||
|
||||
ifeq ($(CONFIG_USB_HIDDEV),y)
|
||||
usbhid-objs += hiddev.o
|
||||
usbhid-y += hiddev.o
|
||||
endif
|
||||
ifeq ($(CONFIG_HID_PID),y)
|
||||
usbhid-objs += hid-pidff.o
|
||||
usbhid-y += hid-pidff.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid.o
|
||||
|
|
|
@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
|
|||
* Input submission and I/O error handler.
|
||||
*/
|
||||
static DEFINE_MUTEX(hid_open_mut);
|
||||
static struct workqueue_struct *resumption_waker;
|
||||
|
||||
static void hid_io_error(struct hid_device *hid);
|
||||
static int hid_submit_out(struct hid_device *hid);
|
||||
|
@ -136,10 +135,10 @@ static void hid_reset(struct work_struct *work)
|
|||
hid_io_error(hid);
|
||||
break;
|
||||
default:
|
||||
err_hid("can't reset device, %s-%s/input%d, status %d",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, rc);
|
||||
hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, rc);
|
||||
/* FALLTHROUGH */
|
||||
case -EHOSTUNREACH:
|
||||
case -ENODEV:
|
||||
|
@ -278,18 +277,18 @@ static void hid_irq_in(struct urb *urb)
|
|||
hid_io_error(hid);
|
||||
return;
|
||||
default: /* error */
|
||||
dev_warn(&urb->dev->dev, "input irq status %d "
|
||||
"received\n", urb->status);
|
||||
hid_warn(urb->dev, "input irq status %d received\n",
|
||||
urb->status);
|
||||
}
|
||||
|
||||
status = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
|
||||
if (status != -EPERM) {
|
||||
err_hid("can't resubmit intr, %s-%s/input%d, status %d",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, status);
|
||||
hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, status);
|
||||
hid_io_error(hid);
|
||||
}
|
||||
}
|
||||
|
@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_device *hid)
|
|||
struct hid_report *report;
|
||||
char *raw_report;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int r;
|
||||
|
||||
report = usbhid->out[usbhid->outtail].report;
|
||||
raw_report = usbhid->out[usbhid->outtail].raw_report;
|
||||
|
||||
r = usb_autopm_get_interface_async(usbhid->intf);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* if the device hasn't been woken, we leave the output
|
||||
* to resume()
|
||||
*/
|
||||
if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
|
||||
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
||||
usbhid->urbout->dev = hid_to_usb_dev(hid);
|
||||
|
@ -313,17 +321,11 @@ static int hid_submit_out(struct hid_device *hid)
|
|||
dbg_hid("submitting out urb\n");
|
||||
|
||||
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
|
||||
err_hid("usb_submit_urb(out) failed");
|
||||
hid_err(hid, "usb_submit_urb(out) failed\n");
|
||||
usb_autopm_put_interface_async(usbhid->intf);
|
||||
return -1;
|
||||
}
|
||||
usbhid->last_out = jiffies;
|
||||
} else {
|
||||
/*
|
||||
* queue work to wake up the device.
|
||||
* as the work queue is freezeable, this is safe
|
||||
* with respect to STD and STR
|
||||
*/
|
||||
queue_work(resumption_waker, &usbhid->restart_work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
|||
struct hid_report *report;
|
||||
unsigned char dir;
|
||||
char *raw_report;
|
||||
int len;
|
||||
int len, r;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
report = usbhid->ctrl[usbhid->ctrltail].report;
|
||||
raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
|
||||
dir = usbhid->ctrl[usbhid->ctrltail].dir;
|
||||
|
||||
r = usb_autopm_get_interface_async(usbhid->intf);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
|
||||
len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
||||
if (dir == USB_DIR_OUT) {
|
||||
|
@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
|||
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
|
||||
|
||||
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
|
||||
err_hid("usb_submit_urb(ctrl) failed");
|
||||
usb_autopm_put_interface_async(usbhid->intf);
|
||||
hid_err(hid, "usb_submit_urb(ctrl) failed\n");
|
||||
return -1;
|
||||
}
|
||||
usbhid->last_ctrl = jiffies;
|
||||
} else {
|
||||
/*
|
||||
* queue work to wake up the device.
|
||||
* as the work queue is freezeable, this is safe
|
||||
* with respect to STD and STR
|
||||
*/
|
||||
queue_work(resumption_waker, &usbhid->restart_work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -413,8 +412,8 @@ static void hid_irq_out(struct urb *urb)
|
|||
case -ENOENT:
|
||||
break;
|
||||
default: /* error */
|
||||
dev_warn(&urb->dev->dev, "output irq status %d "
|
||||
"received\n", urb->status);
|
||||
hid_warn(urb->dev, "output irq status %d received\n",
|
||||
urb->status);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&usbhid->lock, flags);
|
||||
|
@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb)
|
|||
|
||||
clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
|
||||
spin_unlock_irqrestore(&usbhid->lock, flags);
|
||||
usb_autopm_put_interface_async(usbhid->intf);
|
||||
wake_up(&usbhid->wait);
|
||||
}
|
||||
|
||||
|
@ -466,8 +466,7 @@ static void hid_ctrl(struct urb *urb)
|
|||
case -EPIPE: /* report not available */
|
||||
break;
|
||||
default: /* error */
|
||||
dev_warn(&urb->dev->dev, "ctrl urb status %d "
|
||||
"received\n", status);
|
||||
hid_warn(urb->dev, "ctrl urb status %d received\n", status);
|
||||
}
|
||||
|
||||
if (unplug)
|
||||
|
@ -481,11 +480,13 @@ static void hid_ctrl(struct urb *urb)
|
|||
wake_up(&usbhid->wait);
|
||||
}
|
||||
spin_unlock(&usbhid->lock);
|
||||
usb_autopm_put_interface_async(usbhid->intf);
|
||||
return;
|
||||
}
|
||||
|
||||
clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
|
||||
spin_unlock(&usbhid->lock);
|
||||
usb_autopm_put_interface_async(usbhid->intf);
|
||||
wake_up(&usbhid->wait);
|
||||
}
|
||||
|
||||
|
@ -501,13 +502,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
|
|||
|
||||
if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
|
||||
if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
|
||||
dev_warn(&hid->dev, "output queue full\n");
|
||||
hid_warn(hid, "output queue full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
|
||||
if (!usbhid->out[usbhid->outhead].raw_report) {
|
||||
dev_warn(&hid->dev, "output queueing failed\n");
|
||||
hid_warn(hid, "output queueing failed\n");
|
||||
return;
|
||||
}
|
||||
hid_output_report(report, usbhid->out[usbhid->outhead].raw_report);
|
||||
|
@ -532,14 +533,14 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
|
|||
}
|
||||
|
||||
if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
|
||||
dev_warn(&hid->dev, "control queue full\n");
|
||||
hid_warn(hid, "control queue full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir == USB_DIR_OUT) {
|
||||
usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
|
||||
if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
|
||||
dev_warn(&hid->dev, "control queueing failed\n");
|
||||
hid_warn(hid, "control queueing failed\n");
|
||||
return;
|
||||
}
|
||||
hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report);
|
||||
|
@ -590,7 +591,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
|
|||
return -1;
|
||||
|
||||
if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
|
||||
dev_warn(&dev->dev, "event field not found\n");
|
||||
hid_warn(dev, "event field not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -656,7 +657,7 @@ int usbhid_open(struct hid_device *hid)
|
|||
mutex_lock(&hid_open_mut);
|
||||
if (!hid->open++) {
|
||||
res = usb_autopm_get_interface(usbhid->intf);
|
||||
/* the device must be awake to reliable request remote wakeup */
|
||||
/* the device must be awake to reliably request remote wakeup */
|
||||
if (res < 0) {
|
||||
hid->open--;
|
||||
mutex_unlock(&hid_open_mut);
|
||||
|
@ -722,7 +723,7 @@ void usbhid_init_reports(struct hid_device *hid)
|
|||
}
|
||||
|
||||
if (err)
|
||||
dev_warn(&hid->dev, "timeout initializing reports\n");
|
||||
hid_warn(hid, "timeout initializing reports\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -857,18 +858,6 @@ static void usbhid_restart_queues(struct usbhid_device *usbhid)
|
|||
usbhid_restart_ctrl_queue(usbhid);
|
||||
}
|
||||
|
||||
static void __usbhid_restart_queues(struct work_struct *work)
|
||||
{
|
||||
struct usbhid_device *usbhid =
|
||||
container_of(work, struct usbhid_device, restart_work);
|
||||
int r;
|
||||
|
||||
r = usb_autopm_get_interface(usbhid->intf);
|
||||
if (r < 0)
|
||||
return;
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
}
|
||||
|
||||
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
@ -1140,8 +1129,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
|
||||
has_in++;
|
||||
if (!has_in) {
|
||||
dev_err(&intf->dev, "couldn't find an input interrupt "
|
||||
"endpoint\n");
|
||||
hid_err(intf, "couldn't find an input interrupt endpoint\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1206,14 +1194,13 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
|
||||
init_waitqueue_head(&usbhid->wait);
|
||||
INIT_WORK(&usbhid->reset_work, hid_reset);
|
||||
INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
|
||||
setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
|
||||
spin_lock_init(&usbhid->lock);
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
if (ret != -ENODEV)
|
||||
dev_err(&intf->dev, "can't add hid device: %d\n", ret);
|
||||
hid_err(intf, "can't add hid device: %d\n", ret);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1228,6 @@ static void usbhid_disconnect(struct usb_interface *intf)
|
|||
static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
|
||||
{
|
||||
del_timer_sync(&usbhid->io_retry);
|
||||
cancel_work_sync(&usbhid->restart_work);
|
||||
cancel_work_sync(&usbhid->reset_work);
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1248,6 @@ static int hid_pre_reset(struct usb_interface *intf)
|
|||
spin_lock_irq(&usbhid->lock);
|
||||
set_bit(HID_RESET_PENDING, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
cancel_work_sync(&usbhid->restart_work);
|
||||
hid_cease_io(usbhid);
|
||||
|
||||
return 0;
|
||||
|
@ -1461,9 +1446,6 @@ static int __init hid_init(void)
|
|||
{
|
||||
int retval = -ENOMEM;
|
||||
|
||||
resumption_waker = create_freezeable_workqueue("usbhid_resumer");
|
||||
if (!resumption_waker)
|
||||
goto no_queue;
|
||||
retval = hid_register_driver(&hid_usb_driver);
|
||||
if (retval)
|
||||
goto hid_register_fail;
|
||||
|
@ -1481,8 +1463,6 @@ usb_register_fail:
|
|||
usbhid_quirks_init_fail:
|
||||
hid_unregister_driver(&hid_usb_driver);
|
||||
hid_register_fail:
|
||||
destroy_workqueue(resumption_waker);
|
||||
no_queue:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1491,7 +1471,6 @@ static void __exit hid_exit(void)
|
|||
usb_deregister(&hid_driver);
|
||||
usbhid_quirks_exit();
|
||||
hid_unregister_driver(&hid_usb_driver);
|
||||
destroy_workqueue(resumption_waker);
|
||||
}
|
||||
|
||||
module_init(hid_init);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg)
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -220,7 +220,7 @@ static int pidff_rescale_signed(int i, struct hid_field *field)
|
|||
static void pidff_set(struct pidff_usage *usage, u16 value)
|
||||
{
|
||||
usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
|
||||
debug("calculated from %d to %d", value, usage->value[0]);
|
||||
pr_debug("calculated from %d to %d\n", value, usage->value[0]);
|
||||
}
|
||||
|
||||
static void pidff_set_signed(struct pidff_usage *usage, s16 value)
|
||||
|
@ -235,7 +235,7 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
|
|||
usage->value[0] =
|
||||
pidff_rescale(value, 0x7fff, usage->field);
|
||||
}
|
||||
debug("calculated from %d to %d", value, usage->value[0]);
|
||||
pr_debug("calculated from %d to %d\n", value, usage->value[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -259,8 +259,9 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
|
|||
pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
|
||||
pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
|
||||
|
||||
debug("attack %u => %d", envelope->attack_level,
|
||||
pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
|
||||
hid_dbg(pidff->hid, "attack %u => %d\n",
|
||||
envelope->attack_level,
|
||||
pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
|
||||
|
||||
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
|
||||
USB_DIR_OUT);
|
||||
|
@ -466,33 +467,33 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
|
|||
pidff->create_new_effect_type->value[0] = efnum;
|
||||
usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
|
||||
USB_DIR_OUT);
|
||||
debug("create_new_effect sent, type: %d", efnum);
|
||||
hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
|
||||
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
|
||||
pidff->block_load_status->value[0] = 0;
|
||||
usbhid_wait_io(pidff->hid);
|
||||
|
||||
for (j = 0; j < 60; j++) {
|
||||
debug("pid_block_load requested");
|
||||
hid_dbg(pidff->hid, "pid_block_load requested\n");
|
||||
usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
|
||||
USB_DIR_IN);
|
||||
usbhid_wait_io(pidff->hid);
|
||||
if (pidff->block_load_status->value[0] ==
|
||||
pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
|
||||
debug("device reported free memory: %d bytes",
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
|
||||
hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
|
||||
return 0;
|
||||
}
|
||||
if (pidff->block_load_status->value[0] ==
|
||||
pidff->status_id[PID_BLOCK_LOAD_FULL]) {
|
||||
debug("not enough memory free: %d bytes",
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
|
||||
hid_dbg(pidff->hid, "not enough memory free: %d bytes\n",
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
|
||||
pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
|
||||
return -ENOSPC;
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n");
|
||||
hid_err(pidff->hid, "pid_block_load failed 60 times\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -546,7 +547,8 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
|
|||
struct pidff_device *pidff = dev->ff->private;
|
||||
int pid_id = pidff->pid_id[effect_id];
|
||||
|
||||
debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]);
|
||||
hid_dbg(pidff->hid, "starting to erase %d/%d\n",
|
||||
effect_id, pidff->pid_id[effect_id]);
|
||||
/* Wait for the queue to clear. We do not want a full fifo to
|
||||
prevent the effect removal. */
|
||||
usbhid_wait_io(pidff->hid);
|
||||
|
@ -604,8 +606,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
|
|||
type_id = PID_SAW_DOWN;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: invalid waveform\n");
|
||||
hid_err(pidff->hid, "invalid waveform\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -696,7 +697,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
|
|||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "hid-pidff: invalid type\n");
|
||||
hid_err(pidff->hid, "invalid type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -704,7 +705,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
|
|||
pidff->pid_id[effect->id] =
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
|
||||
|
||||
debug("uploaded");
|
||||
hid_dbg(pidff->hid, "uploaded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -770,14 +771,14 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
|
|||
for (i = 0; i < report->maxfield; i++) {
|
||||
if (report->field[i]->maxusage !=
|
||||
report->field[i]->report_count) {
|
||||
debug("maxusage and report_count do not match, "
|
||||
"skipping");
|
||||
pr_debug("maxusage and report_count do not match, skipping\n");
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < report->field[i]->maxusage; j++) {
|
||||
if (report->field[i]->usage[j].hid ==
|
||||
(HID_UP_PID | table[k])) {
|
||||
debug("found %d at %d->%d", k, i, j);
|
||||
pr_debug("found %d at %d->%d\n",
|
||||
k, i, j);
|
||||
usage[k].field = report->field[i];
|
||||
usage[k].value =
|
||||
&report->field[i]->value[j];
|
||||
|
@ -789,7 +790,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
|
|||
break;
|
||||
}
|
||||
if (!found && strict) {
|
||||
debug("failed to locate %d", k);
|
||||
pr_debug("failed to locate %d\n", k);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -826,8 +827,8 @@ static void pidff_find_reports(struct hid_device *hid, int report_type,
|
|||
continue;
|
||||
ret = pidff_check_usage(report->field[0]->logical);
|
||||
if (ret != -1) {
|
||||
debug("found usage 0x%02x from field->logical",
|
||||
pidff_reports[ret]);
|
||||
hid_dbg(hid, "found usage 0x%02x from field->logical\n",
|
||||
pidff_reports[ret]);
|
||||
pidff->reports[ret] = report;
|
||||
continue;
|
||||
}
|
||||
|
@ -845,8 +846,9 @@ static void pidff_find_reports(struct hid_device *hid, int report_type,
|
|||
continue;
|
||||
ret = pidff_check_usage(hid->collection[i - 1].usage);
|
||||
if (ret != -1 && !pidff->reports[ret]) {
|
||||
debug("found usage 0x%02x from collection array",
|
||||
pidff_reports[ret]);
|
||||
hid_dbg(hid,
|
||||
"found usage 0x%02x from collection array\n",
|
||||
pidff_reports[ret]);
|
||||
pidff->reports[ret] = report;
|
||||
}
|
||||
}
|
||||
|
@ -861,7 +863,7 @@ static int pidff_reports_ok(struct pidff_device *pidff)
|
|||
|
||||
for (i = 0; i <= PID_REQUIRED_REPORTS; i++) {
|
||||
if (!pidff->reports[i]) {
|
||||
debug("%d missing", i);
|
||||
hid_dbg(pidff->hid, "%d missing\n", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -884,8 +886,7 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
|
|||
report->field[i]->logical_minimum == 1)
|
||||
return report->field[i];
|
||||
else {
|
||||
printk(KERN_ERR "hid-pidff: logical_minimum "
|
||||
"is not 1 as it should be\n");
|
||||
pr_err("logical_minimum is not 1 as it should be\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -924,7 +925,7 @@ static int pidff_find_special_keys(int *keys, struct hid_field *fld,
|
|||
*/
|
||||
static int pidff_find_special_fields(struct pidff_device *pidff)
|
||||
{
|
||||
debug("finding special fields");
|
||||
hid_dbg(pidff->hid, "finding special fields\n");
|
||||
|
||||
pidff->create_new_effect_type =
|
||||
pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
|
||||
|
@ -945,32 +946,30 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
|
|||
pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
|
||||
0x78, 1);
|
||||
|
||||
debug("search done");
|
||||
hid_dbg(pidff->hid, "search done\n");
|
||||
|
||||
if (!pidff->create_new_effect_type || !pidff->set_effect_type) {
|
||||
printk(KERN_ERR "hid-pidff: effect lists not found\n");
|
||||
hid_err(pidff->hid, "effect lists not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pidff->effect_direction) {
|
||||
printk(KERN_ERR "hid-pidff: direction field not found\n");
|
||||
hid_err(pidff->hid, "direction field not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pidff->device_control) {
|
||||
printk(KERN_ERR "hid-pidff: device control field not found\n");
|
||||
hid_err(pidff->hid, "device control field not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pidff->block_load_status) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: block load status field not found\n");
|
||||
hid_err(pidff->hid, "block load status field not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pidff->effect_operation_status) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: effect operation field not found\n");
|
||||
hid_err(pidff->hid, "effect operation field not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -982,23 +981,22 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
|
|||
|
||||
if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
|
||||
effect_types)) {
|
||||
printk(KERN_ERR "hid-pidff: no effect types found\n");
|
||||
hid_err(pidff->hid, "no effect types found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
|
||||
block_load_status) !=
|
||||
sizeof(pidff_block_load_status)) {
|
||||
printk(KERN_ERR
|
||||
"hidpidff: block load status identifiers not found\n");
|
||||
hid_err(pidff->hid,
|
||||
"block load status identifiers not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
|
||||
effect_operation_status) !=
|
||||
sizeof(pidff_effect_operation_status)) {
|
||||
printk(KERN_ERR
|
||||
"hidpidff: effect operation identifiers not found\n");
|
||||
hid_err(pidff->hid, "effect operation identifiers not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1017,8 +1015,8 @@ static int pidff_find_effects(struct pidff_device *pidff,
|
|||
int pidff_type = pidff->type_id[i];
|
||||
if (pidff->set_effect_type->usage[pidff_type].hid !=
|
||||
pidff->create_new_effect_type->usage[pidff_type].hid) {
|
||||
printk(KERN_ERR "hid-pidff: "
|
||||
"effect type number %d is invalid\n", i);
|
||||
hid_err(pidff->hid,
|
||||
"effect type number %d is invalid\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1073,27 +1071,23 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
|||
int envelope_ok = 0;
|
||||
|
||||
if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: unknown set_effect report layout\n");
|
||||
hid_err(pidff->hid, "unknown set_effect report layout\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
|
||||
if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: unknown pid_block_load report layout\n");
|
||||
hid_err(pidff->hid, "unknown pid_block_load report layout\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: unknown effect_operation report layout\n");
|
||||
hid_err(pidff->hid, "unknown effect_operation report layout\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) {
|
||||
printk(KERN_ERR
|
||||
"hid-pidff: unknown pid_block_free report layout\n");
|
||||
hid_err(pidff->hid, "unknown pid_block_free report layout\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1105,27 +1099,26 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
|||
|
||||
if (!envelope_ok) {
|
||||
if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
|
||||
printk(KERN_WARNING "hid-pidff: "
|
||||
"has constant effect but no envelope\n");
|
||||
hid_warn(pidff->hid,
|
||||
"has constant effect but no envelope\n");
|
||||
if (test_and_clear_bit(FF_RAMP, dev->ffbit))
|
||||
printk(KERN_WARNING "hid-pidff: "
|
||||
"has ramp effect but no envelope\n");
|
||||
hid_warn(pidff->hid,
|
||||
"has ramp effect but no envelope\n");
|
||||
|
||||
if (test_and_clear_bit(FF_PERIODIC, dev->ffbit))
|
||||
printk(KERN_WARNING "hid-pidff: "
|
||||
"has periodic effect but no envelope\n");
|
||||
hid_warn(pidff->hid,
|
||||
"has periodic effect but no envelope\n");
|
||||
}
|
||||
|
||||
if (test_bit(FF_CONSTANT, dev->ffbit) &&
|
||||
PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
|
||||
printk(KERN_WARNING
|
||||
"hid-pidff: unknown constant effect layout\n");
|
||||
hid_warn(pidff->hid, "unknown constant effect layout\n");
|
||||
clear_bit(FF_CONSTANT, dev->ffbit);
|
||||
}
|
||||
|
||||
if (test_bit(FF_RAMP, dev->ffbit) &&
|
||||
PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
|
||||
printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n");
|
||||
hid_warn(pidff->hid, "unknown ramp effect layout\n");
|
||||
clear_bit(FF_RAMP, dev->ffbit);
|
||||
}
|
||||
|
||||
|
@ -1134,8 +1127,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
|||
test_bit(FF_FRICTION, dev->ffbit) ||
|
||||
test_bit(FF_INERTIA, dev->ffbit)) &&
|
||||
PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
|
||||
printk(KERN_WARNING
|
||||
"hid-pidff: unknown condition effect layout\n");
|
||||
hid_warn(pidff->hid, "unknown condition effect layout\n");
|
||||
clear_bit(FF_SPRING, dev->ffbit);
|
||||
clear_bit(FF_DAMPER, dev->ffbit);
|
||||
clear_bit(FF_FRICTION, dev->ffbit);
|
||||
|
@ -1144,8 +1136,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
|||
|
||||
if (test_bit(FF_PERIODIC, dev->ffbit) &&
|
||||
PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
|
||||
printk(KERN_WARNING
|
||||
"hid-pidff: unknown periodic effect layout\n");
|
||||
hid_warn(pidff->hid, "unknown periodic effect layout\n");
|
||||
clear_bit(FF_PERIODIC, dev->ffbit);
|
||||
}
|
||||
|
||||
|
@ -1184,12 +1175,12 @@ static void pidff_reset(struct pidff_device *pidff)
|
|||
if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
|
||||
while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
|
||||
if (i++ > 20) {
|
||||
printk(KERN_WARNING "hid-pidff: device reports "
|
||||
"%d simultaneous effects\n",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
hid_warn(pidff->hid,
|
||||
"device reports %d simultaneous effects\n",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
break;
|
||||
}
|
||||
debug("pid_pool requested again");
|
||||
hid_dbg(pidff->hid, "pid_pool requested again\n");
|
||||
usbhid_submit_report(hid, pidff->reports[PID_POOL],
|
||||
USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
|
@ -1215,7 +1206,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
|
|||
|
||||
error = pidff_request_effect_upload(pidff, 1);
|
||||
if (error) {
|
||||
printk(KERN_ERR "hid-pidff: upload request failed\n");
|
||||
hid_err(pidff->hid, "upload request failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1224,8 +1215,8 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
|
|||
pidff_autocenter(pidff, 0xffff);
|
||||
set_bit(FF_AUTOCENTER, dev->ffbit);
|
||||
} else {
|
||||
printk(KERN_NOTICE "hid-pidff: "
|
||||
"device has unknown autocenter control method\n");
|
||||
hid_notice(pidff->hid,
|
||||
"device has unknown autocenter control method\n");
|
||||
}
|
||||
|
||||
pidff_erase_pid(pidff,
|
||||
|
@ -1248,10 +1239,10 @@ int hid_pidff_init(struct hid_device *hid)
|
|||
int max_effects;
|
||||
int error;
|
||||
|
||||
debug("starting pid init");
|
||||
hid_dbg(hid, "starting pid init\n");
|
||||
|
||||
if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
|
||||
debug("not a PID device, no output report");
|
||||
hid_dbg(hid, "not a PID device, no output report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1265,7 +1256,7 @@ int hid_pidff_init(struct hid_device *hid)
|
|||
pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
|
||||
|
||||
if (!pidff_reports_ok(pidff)) {
|
||||
debug("reports not ok, aborting");
|
||||
hid_dbg(hid, "reports not ok, aborting\n");
|
||||
error = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1278,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid)
|
|||
|
||||
if (test_bit(FF_GAIN, dev->ffbit)) {
|
||||
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
|
||||
usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
|
||||
USB_DIR_OUT);
|
||||
usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN],
|
||||
USB_DIR_OUT);
|
||||
}
|
||||
|
||||
error = pidff_check_autocenter(pidff, dev);
|
||||
|
@ -1290,23 +1281,23 @@ int hid_pidff_init(struct hid_device *hid)
|
|||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum -
|
||||
pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum +
|
||||
1;
|
||||
debug("max effects is %d", max_effects);
|
||||
hid_dbg(hid, "max effects is %d\n", max_effects);
|
||||
|
||||
if (max_effects > PID_EFFECTS_MAX)
|
||||
max_effects = PID_EFFECTS_MAX;
|
||||
|
||||
if (pidff->pool[PID_SIMULTANEOUS_MAX].value)
|
||||
debug("max simultaneous effects is %d",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
hid_dbg(hid, "max simultaneous effects is %d\n",
|
||||
pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
|
||||
|
||||
if (pidff->pool[PID_RAM_POOL_SIZE].value)
|
||||
debug("device memory size is %d bytes",
|
||||
pidff->pool[PID_RAM_POOL_SIZE].value[0]);
|
||||
hid_dbg(hid, "device memory size is %d bytes\n",
|
||||
pidff->pool[PID_RAM_POOL_SIZE].value[0]);
|
||||
|
||||
if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
|
||||
pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
|
||||
printk(KERN_NOTICE "hid-pidff: "
|
||||
"device does not support device managed pool\n");
|
||||
hid_notice(hid,
|
||||
"device does not support device managed pool\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1322,8 +1313,7 @@ int hid_pidff_init(struct hid_device *hid)
|
|||
ff->set_autocenter = pidff_set_autocenter;
|
||||
ff->playback = pidff_playback;
|
||||
|
||||
printk(KERN_INFO "Force feedback for USB HID PID devices by "
|
||||
"Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
|
||||
|
||||
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -585,163 +585,168 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
{
|
||||
struct hiddev_list *list = file->private_data;
|
||||
struct hiddev *hiddev = list->hiddev;
|
||||
struct hid_device *hid = hiddev->hid;
|
||||
struct usb_device *dev;
|
||||
struct hid_device *hid;
|
||||
struct hiddev_collection_info cinfo;
|
||||
struct hiddev_report_info rinfo;
|
||||
struct hiddev_field_info finfo;
|
||||
struct hiddev_devinfo dinfo;
|
||||
struct hid_report *report;
|
||||
struct hid_field *field;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
void __user *user_arg = (void __user *)arg;
|
||||
int i, r;
|
||||
int i, r = -EINVAL;
|
||||
|
||||
/* Called without BKL by compat methods so no BKL taken */
|
||||
|
||||
/* FIXME: Who or what stop this racing with a disconnect ?? */
|
||||
if (!hiddev->exist || !hid)
|
||||
return -EIO;
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!hiddev->exist) {
|
||||
r = -ENODEV;
|
||||
goto ret_unlock;
|
||||
}
|
||||
|
||||
dev = hid_to_usb_dev(hid);
|
||||
hid = hiddev->hid;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case HIDIOCGVERSION:
|
||||
return put_user(HID_VERSION, (int __user *)arg);
|
||||
r = put_user(HID_VERSION, (int __user *)arg) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
|
||||
case HIDIOCAPPLICATION:
|
||||
if (arg < 0 || arg >= hid->maxapplication)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
for (i = 0; i < hid->maxcollection; i++)
|
||||
if (hid->collection[i].type ==
|
||||
HID_COLLECTION_APPLICATION && arg-- == 0)
|
||||
break;
|
||||
|
||||
if (i == hid->maxcollection)
|
||||
return -EINVAL;
|
||||
|
||||
return hid->collection[i].usage;
|
||||
if (i < hid->maxcollection)
|
||||
r = hid->collection[i].usage;
|
||||
break;
|
||||
|
||||
case HIDIOCGDEVINFO:
|
||||
dinfo.bustype = BUS_USB;
|
||||
dinfo.busnum = dev->bus->busnum;
|
||||
dinfo.devnum = dev->devnum;
|
||||
dinfo.ifnum = usbhid->ifnum;
|
||||
dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
|
||||
dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
|
||||
dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
|
||||
dinfo.num_applications = hid->maxapplication;
|
||||
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
|
||||
return -EFAULT;
|
||||
{
|
||||
struct usb_device *dev = hid_to_usb_dev(hid);
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
return 0;
|
||||
dinfo.bustype = BUS_USB;
|
||||
dinfo.busnum = dev->bus->busnum;
|
||||
dinfo.devnum = dev->devnum;
|
||||
dinfo.ifnum = usbhid->ifnum;
|
||||
dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
|
||||
dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
|
||||
dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
|
||||
dinfo.num_applications = hid->maxapplication;
|
||||
|
||||
r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case HIDIOCGFLAG:
|
||||
if (put_user(list->flags, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
r = put_user(list->flags, (int __user *)arg) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
|
||||
case HIDIOCSFLAG:
|
||||
{
|
||||
int newflags;
|
||||
if (get_user(newflags, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(newflags, (int __user *)arg)) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((newflags & ~HIDDEV_FLAGS) != 0 ||
|
||||
((newflags & HIDDEV_FLAG_REPORT) != 0 &&
|
||||
(newflags & HIDDEV_FLAG_UREF) == 0))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
list->flags = newflags;
|
||||
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case HIDIOCGSTRING:
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist)
|
||||
r = hiddev_ioctl_string(hiddev, cmd, user_arg);
|
||||
else
|
||||
r = -ENODEV;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return r;
|
||||
r = hiddev_ioctl_string(hiddev, cmd, user_arg);
|
||||
break;
|
||||
|
||||
case HIDIOCINITREPORT:
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!hiddev->exist) {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return -ENODEV;
|
||||
}
|
||||
usbhid_init_reports(hid);
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
case HIDIOCGREPORT:
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
report = hiddev_lookup_report(hid, &rinfo);
|
||||
if (report == NULL)
|
||||
break;
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
case HIDIOCSREPORT:
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
report = hiddev_lookup_report(hid, &rinfo);
|
||||
if (report == NULL)
|
||||
break;
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
|
||||
return 0;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
case HIDIOCGREPORTINFO:
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
report = hiddev_lookup_report(hid, &rinfo);
|
||||
if (report == NULL)
|
||||
break;
|
||||
|
||||
rinfo.num_fields = report->maxfield;
|
||||
|
||||
if (copy_to_user(user_arg, &rinfo, sizeof(rinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
|
||||
case HIDIOCGFIELDINFO:
|
||||
if (copy_from_user(&finfo, user_arg, sizeof(finfo)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&finfo, user_arg, sizeof(finfo))) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
rinfo.report_type = finfo.report_type;
|
||||
rinfo.report_id = finfo.report_id;
|
||||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
report = hiddev_lookup_report(hid, &rinfo);
|
||||
if (report == NULL)
|
||||
break;
|
||||
|
||||
if (finfo.field_index >= report->maxfield)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
field = report->field[finfo.field_index];
|
||||
memset(&finfo, 0, sizeof(finfo));
|
||||
|
@ -760,10 +765,9 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
finfo.unit_exponent = field->unit_exponent;
|
||||
finfo.unit = field->unit;
|
||||
|
||||
if (copy_to_user(user_arg, &finfo, sizeof(finfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
|
||||
case HIDIOCGUCODE:
|
||||
/* fall through */
|
||||
|
@ -772,57 +776,66 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case HIDIOCGUSAGES:
|
||||
case HIDIOCSUSAGES:
|
||||
case HIDIOCGCOLLECTIONINDEX:
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist)
|
||||
r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
|
||||
else
|
||||
r = -ENODEV;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return r;
|
||||
r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
|
||||
break;
|
||||
|
||||
case HIDIOCGCOLLECTIONINFO:
|
||||
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cinfo.index >= hid->maxcollection)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
cinfo.type = hid->collection[cinfo.index].type;
|
||||
cinfo.usage = hid->collection[cinfo.index].usage;
|
||||
cinfo.level = hid->collection[cinfo.index].level;
|
||||
|
||||
if (copy_to_user(user_arg, &cinfo, sizeof(cinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ?
|
||||
-EFAULT : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
|
||||
int len;
|
||||
if (!hid->name)
|
||||
return 0;
|
||||
|
||||
if (!hid->name) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(hid->name) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->name, len) ?
|
||||
r = copy_to_user(user_arg, hid->name, len) ?
|
||||
-EFAULT : len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
|
||||
int len;
|
||||
if (!hid->phys)
|
||||
return 0;
|
||||
|
||||
if (!hid->phys) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(hid->phys) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->phys, len) ?
|
||||
r = copy_to_user(user_arg, hid->phys, len) ?
|
||||
-EFAULT : len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
|
||||
ret_unlock:
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -892,7 +905,7 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
|
|||
hiddev->exist = 1;
|
||||
retval = usb_register_dev(usbhid->intf, &hiddev_class);
|
||||
if (retval) {
|
||||
err_hid("Not able to get a minor for this device.");
|
||||
hid_err(hid, "Not able to get a minor for this device\n");
|
||||
hid->hiddev = NULL;
|
||||
kfree(hiddev);
|
||||
return -1;
|
||||
|
|
|
@ -95,7 +95,6 @@ struct usbhid_device {
|
|||
unsigned long stop_retry; /* Time to give up, in jiffies */
|
||||
unsigned int retry_delay; /* Delay length in ms */
|
||||
struct work_struct reset_work; /* Task context for resets */
|
||||
struct work_struct restart_work; /* waking up for output to be done in a task */
|
||||
wait_queue_head_t wait; /* For sleeping */
|
||||
int ledcount; /* counting the number of active leds */
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -104,16 +106,18 @@ static void usb_kbd_irq(struct urb *urb)
|
|||
if (usb_kbd_keycode[kbd->old[i]])
|
||||
input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
|
||||
else
|
||||
dev_info(&urb->dev->dev,
|
||||
"Unknown key (scancode %#x) released.\n", kbd->old[i]);
|
||||
hid_info(urb->dev,
|
||||
"Unknown key (scancode %#x) released.\n",
|
||||
kbd->old[i]);
|
||||
}
|
||||
|
||||
if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
|
||||
if (usb_kbd_keycode[kbd->new[i]])
|
||||
input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
|
||||
else
|
||||
dev_info(&urb->dev->dev,
|
||||
"Unknown key (scancode %#x) released.\n", kbd->new[i]);
|
||||
hid_info(urb->dev,
|
||||
"Unknown key (scancode %#x) released.\n",
|
||||
kbd->new[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,9 +128,9 @@ static void usb_kbd_irq(struct urb *urb)
|
|||
resubmit:
|
||||
i = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (i)
|
||||
err_hid ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
kbd->usbdev->bus->bus_name,
|
||||
kbd->usbdev->devpath, i);
|
||||
hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d",
|
||||
kbd->usbdev->bus->bus_name,
|
||||
kbd->usbdev->devpath, i);
|
||||
}
|
||||
|
||||
static int usb_kbd_event(struct input_dev *dev, unsigned int type,
|
||||
|
@ -150,7 +154,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
|
|||
*(kbd->leds) = kbd->newleds;
|
||||
kbd->led->dev = kbd->usbdev;
|
||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
||||
err_hid("usb_submit_urb(leds) failed");
|
||||
pr_err("usb_submit_urb(leds) failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -160,7 +164,7 @@ static void usb_kbd_led(struct urb *urb)
|
|||
struct usb_kbd *kbd = urb->context;
|
||||
|
||||
if (urb->status)
|
||||
dev_warn(&urb->dev->dev, "led urb status %d received\n",
|
||||
hid_warn(urb->dev, "led urb status %d received\n",
|
||||
urb->status);
|
||||
|
||||
if (*(kbd->leds) == kbd->newleds)
|
||||
|
@ -169,7 +173,7 @@ static void usb_kbd_led(struct urb *urb)
|
|||
*(kbd->leds) = kbd->newleds;
|
||||
kbd->led->dev = kbd->usbdev;
|
||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
||||
err_hid("usb_submit_urb(leds) failed");
|
||||
hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
|
||||
}
|
||||
|
||||
static int usb_kbd_open(struct input_dev *dev)
|
||||
|
|
|
@ -55,6 +55,14 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
|
||||
/* MacbookAir3,2 (unibody), aka wellspring5 */
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241
|
||||
/* MacbookAir3,1 (unibody), aka wellspring4 */
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244
|
||||
|
||||
#define BCM5974_DEVICE(prod) { \
|
||||
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
||||
|
@ -80,6 +88,14 @@ static const struct usb_device_id bcm5974_table[] = {
|
|||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
|
||||
/* MacbookAir3,2 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
|
||||
/* MacbookAir3,1 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
|
||||
/* Terminating entry */
|
||||
{}
|
||||
};
|
||||
|
@ -234,6 +250,30 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||
{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
|
||||
{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
|
||||
},
|
||||
{
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
|
||||
HAS_INTEGRATED_BUTTON,
|
||||
0x84, sizeof(struct bt_data),
|
||||
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
|
||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
|
||||
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||
{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
|
||||
{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
|
||||
},
|
||||
{
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
|
||||
HAS_INTEGRATED_BUTTON,
|
||||
0x84, sizeof(struct bt_data),
|
||||
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
|
||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
|
||||
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||
{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
|
||||
{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ struct class {
|
|||
|
||||
struct class_attribute *class_attrs;
|
||||
struct device_attribute *dev_attrs;
|
||||
struct bin_attribute *dev_bin_attrs;
|
||||
struct kobject *dev_kobj;
|
||||
|
||||
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
|
||||
|
|
|
@ -820,6 +820,49 @@ static inline void hid_hw_stop(struct hid_device *hdev)
|
|||
hdev->ll_driver->stop(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_open - signal underlaying HW to start delivering events
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* Tell underlying HW to start delivering events from the device.
|
||||
* This function should be called sometime after successful call
|
||||
* to hid_hiw_start().
|
||||
*/
|
||||
static inline int __must_check hid_hw_open(struct hid_device *hdev)
|
||||
{
|
||||
return hdev->ll_driver->open(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_close - signal underlaying HW to stop delivering events
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* This function indicates that we are not interested in the events
|
||||
* from this device anymore. Delivery of events may or may not stop,
|
||||
* depending on the number of users still outstanding.
|
||||
*/
|
||||
static inline void hid_hw_close(struct hid_device *hdev)
|
||||
{
|
||||
hdev->ll_driver->close(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_power - requests underlying HW to go into given power mode
|
||||
*
|
||||
* @hdev: hid device
|
||||
* @level: requested power level (one of %PM_HINT_* defines)
|
||||
*
|
||||
* This function requests underlying hardware to enter requested power
|
||||
* mode.
|
||||
*/
|
||||
|
||||
static inline int hid_hw_power(struct hid_device *hdev, int level)
|
||||
{
|
||||
return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
|
||||
}
|
||||
|
||||
void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
|
||||
int interrupt);
|
||||
|
||||
|
@ -838,12 +881,32 @@ int hid_pidff_init(struct hid_device *hid);
|
|||
#define hid_pidff_init NULL
|
||||
#endif
|
||||
|
||||
#define dbg_hid(format, arg...) if (hid_debug) \
|
||||
printk(KERN_DEBUG "%s: " format ,\
|
||||
__FILE__ , ## arg)
|
||||
#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
|
||||
__FILE__ , ## arg)
|
||||
#endif /* HID_FF */
|
||||
#define dbg_hid(format, arg...) \
|
||||
do { \
|
||||
if (hid_debug) \
|
||||
printk(KERN_DEBUG "%s: " format, __FILE__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#define hid_printk(level, hid, fmt, arg...) \
|
||||
dev_printk(level, &(hid)->dev, fmt, ##arg)
|
||||
#define hid_emerg(hid, fmt, arg...) \
|
||||
dev_emerg(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_crit(hid, fmt, arg...) \
|
||||
dev_crit(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_alert(hid, fmt, arg...) \
|
||||
dev_alert(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_err(hid, fmt, arg...) \
|
||||
dev_err(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_notice(hid, fmt, arg...) \
|
||||
dev_notice(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_warn(hid, fmt, arg...) \
|
||||
dev_warn(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_info(hid, fmt, arg...) \
|
||||
dev_info(&(hid)->dev, fmt, ##arg)
|
||||
#define hid_dbg(hid, fmt, arg...) \
|
||||
dev_dbg(&(hid)->dev, fmt, ##arg)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue