digimend-devel Mailing List for DIGImend (Page 9)
Brought to you by:
spb_nick
You can subscribe to this list here.
| 2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(8) |
Jun
(27) |
Jul
(54) |
Aug
(54) |
Sep
(13) |
Oct
(20) |
Nov
(7) |
Dec
(4) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2013 |
Jan
(3) |
Feb
(3) |
Mar
(6) |
Apr
(1) |
May
(8) |
Jun
(5) |
Jul
(4) |
Aug
(10) |
Sep
(44) |
Oct
(12) |
Nov
(5) |
Dec
(14) |
| 2014 |
Jan
(16) |
Feb
(3) |
Mar
(3) |
Apr
(5) |
May
(2) |
Jun
(14) |
Jul
(38) |
Aug
(15) |
Sep
(15) |
Oct
(12) |
Nov
(38) |
Dec
(31) |
| 2015 |
Jan
(73) |
Feb
(71) |
Mar
(57) |
Apr
(36) |
May
(33) |
Jun
(20) |
Jul
(4) |
Aug
(5) |
Sep
(1) |
Oct
(11) |
Nov
(2) |
Dec
(6) |
| 2016 |
Jan
(7) |
Feb
(3) |
Mar
(6) |
Apr
(2) |
May
(7) |
Jun
(5) |
Jul
(3) |
Aug
(5) |
Sep
(5) |
Oct
(8) |
Nov
(13) |
Dec
|
|
From: Benjamin T. <ben...@re...> - 2015-03-13 21:28:41
|
No need to retrieve the USB handle in input_mapping() when we already do that in probe. It also allows to use the quirk without having to add the product ID matching. Sent upstream as: https://patchwork.kernel.org/patch/6006271/ --- hid-uclogic.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hid-uclogic.c b/hid-uclogic.c index 51333fa..88c0914 100644 --- a/hid-uclogic.c +++ b/hid-uclogic.c @@ -627,6 +627,7 @@ struct uclogic_drvdata { __u8 *rdesc; unsigned int rsize; bool invert_pen_inrange; + bool ignore_pen_interface; }; static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -719,16 +720,12 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - struct usb_interface *intf; - - if (hdev->product == USB_DEVICE_ID_HUION_TABLET) { - intf = to_usb_interface(hdev->dev.parent); + struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); - /* discard the unused pen interface */ - if ((intf->cur_altsetting->desc.bInterfaceNumber != 0) && - (field->application == HID_DG_PEN)) - return -1; - } + /* discard the unused pen interface */ + if ((drvdata->ignore_pen_interface) && + (field->application == HID_DG_PEN)) + return -1; /* let hid-core decide what to do */ return 0; @@ -910,6 +907,8 @@ static int uclogic_probe(struct hid_device *hdev, return rc; } drvdata->invert_pen_inrange = true; + } else { + drvdata->ignore_pen_interface = true; } break; case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60: -- 2.3.1 |
|
From: Benjamin T. <ben...@re...> - 2015-03-13 21:28:41
|
Based on a patch from: Nikolai Kondrashov <Nik...@re...>
Enable abstract keyboard mode for Huion tablets, which makes them report
frame buttons using the pen interface and report ID. Divert these
reports to a virtual report ID describing them.
This makes the tablet compatible with xf86-input-wacom and libinput,
but stops the frame buttons from reporting keyboard events.
---
Sorry it took so long to actually propose this patch. I am fixing at the moment
gnome-control-center, gnome-settings-daemon and libwacom to be able to handle
also the generic devices like the Huion ones.
I need to go through all the Huion known device and see what they answer when
querying the string 0x7b, but I believe checking if "HK On" is returned should
allow us to prevent activating a pad interface if the device does not support
it.
I am quite tempted to send this one upstream directly too. So please, test it
and report if there are obvious problems.
Cheers,
Benjamin
hid-uclogic.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 98 insertions(+), 5 deletions(-)
diff --git a/hid-uclogic.c b/hid-uclogic.c
index 88c0914..ea57d9f 100644
--- a/hid-uclogic.c
+++ b/hid-uclogic.c
@@ -613,6 +613,27 @@ static const __u8 uclogic_tablet_rdesc_template[] = {
0xC0 /* End Collection */
};
+/* Fixed report descriptor template */
+static const __u8 uclogic_buttonpad_rdesc_template[] = {
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x07, /* Usage (Keypad), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0xF7, /* Report ID (247), */
+ 0x05, 0x0D, /* Usage Page (Digitizers), */
+ 0x09, 0x39, /* Usage (Tablet Function Keys), */
+ 0xA0, /* Collection (Physical), */
+ 0x05, 0x09, /* Usage Page (Button), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x18, /* Report Count (24), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x19, 0x01, /* Usage Minimum (01h), */
+ 0x29, 0x08, /* Usage Maximum (08h), */
+ 0x95, 0x08, /* Report Count (8), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection */
+ 0xC0 /* End Collection */
+};
+
/* Parameter indices */
enum uclogic_prm {
UCLOGIC_PRM_X_LM = 1,
@@ -628,6 +649,7 @@ struct uclogic_drvdata {
unsigned int rsize;
bool invert_pen_inrange;
bool ignore_pen_interface;
+ bool has_virtual_pad_interface;
};
static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -874,6 +896,70 @@ cleanup:
return rc;
}
+/**
+ * Enable actual button mode.
+ *
+ * @hdev: HID device
+ */
+static int uclogic_button_enable(struct hid_device *hdev)
+{
+ int rc;
+ struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+ struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
+ char *str_buf;
+ size_t str_len = 16;
+ unsigned char *rdesc;
+ size_t rdesc_len;
+
+ str_buf = kzalloc(str_len, GFP_KERNEL);
+ if (str_buf == NULL) {
+ hid_err(hdev, "failed to allocate string buffer\n");
+ rc = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* Enable abstract keyboard mode */
+ rc = usb_string(usb_dev, 0x7b, str_buf, str_len);
+ if (rc == -EPIPE) {
+ hid_info(hdev, "button mode setting not found\n");
+ rc = 0;
+ goto cleanup;
+ } else if (rc < 0) {
+ hid_err(hdev, "failed to enable abstract keyboard\n");
+ goto cleanup;
+ } else if (strncmp(str_buf, "HK On", rc)) {
+ hid_info(hdev, "invalid answer when requesting buttons: '%s'\n",
+ str_buf);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ /* Re-allocate fixed report descriptor */
+ rdesc_len = drvdata->rsize + sizeof(uclogic_buttonpad_rdesc_template);
+ rdesc = devm_kzalloc(&hdev->dev, rdesc_len, GFP_KERNEL);
+ if (!rdesc) {
+ rc = -ENOMEM;
+ goto cleanup;
+ }
+
+ memcpy(rdesc, drvdata->rdesc, drvdata->rsize);
+
+ /* Append the buttonpad descriptor */
+ memcpy(rdesc + drvdata->rsize, uclogic_buttonpad_rdesc_template,
+ sizeof(uclogic_buttonpad_rdesc_template));
+
+ /* clean up old rdesc and use the new one */
+ drvdata->rsize = rdesc_len;
+ devm_kfree(&hdev->dev, drvdata->rdesc);
+ drvdata->rdesc = rdesc;
+
+ rc = 0;
+
+cleanup:
+ kfree(str_buf);
+ return rc;
+}
+
static int uclogic_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -907,6 +993,9 @@ static int uclogic_probe(struct hid_device *hdev,
return rc;
}
drvdata->invert_pen_inrange = true;
+
+ rc = uclogic_button_enable(hdev);
+ drvdata->has_virtual_pad_interface = !rc;
} else {
drvdata->ignore_pen_interface = true;
}
@@ -947,12 +1036,16 @@ static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report,
{
struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
- if ((drvdata->invert_pen_inrange) &&
- (report->type == HID_INPUT_REPORT) &&
+ if ((report->type == HID_INPUT_REPORT) &&
(report->id == UCLOGIC_PEN_REPORT_ID) &&
- (size >= 2))
- /* Invert the in-range bit */
- data[1] ^= 0x40;
+ (size >= 2)) {
+ if (drvdata->has_virtual_pad_interface && (data[1] & 0x20))
+ /* Change to virtual frame button report ID */
+ data[0] = 0xf7;
+ else if (drvdata->invert_pen_inrange)
+ /* Invert the in-range bit */
+ data[1] ^= 0x40;
+ }
return 0;
}
--
2.3.1
|
|
From: Yann V. <yan...@or...> - 2015-03-07 19:35:29
|
Nikolai Kondrashov <sp...@gm...> wrote: > I would prefer the latter. I.e. have the lower side button report middle click > and the upper one report right click to match other tablets. Okay, doing that. > >> Is the actual physical drawing area square? > > > > No. I believe it's meant to be 16:10 proportions. > > A quick measurement by the printed border shows: > > X: inner 103.65mm, outer 105mm > > Y: inner 65.6mm, outer 66.45mm > > This gives an aspect ratio somewhere from 1.56 to 1.60. Measuring the firmware limits > > would be a bit harder (for instance, it doesn't measure the tip but the coil position). > > I guess 105.6*66mm would be a reasonable approximation. > > This would be awfully low resolution and most likely scaled by firmware for > compatibility. The oldest tablet I have (UC-Logic WP8060U) has higher > resolution, I think. There's very little chance a non-square tablet would > report equal coordinate range for both axes in hardware. There might be a way > to get it to report real ranges over USB. I would try poking at those features > in the report descriptor. There should have been a driver for this tablet > doing that. Perhaps we can find it and take a look at the USB traffic. We can > postpone it for later, though. It is definitely scaled by firmware; the non-square area is reported as a full 12 bit range. This works out to roughly 4096/(105.6/25.4)=985cpi. The soft buttons are outside of this reported area and handled entirely in firmware. Obviously the resolution runs out as this hits 4k monitors; quantisation errors may be notable before that. In mouse mode, it reports a higher resolution at 16 bits, but takes steps of about 7 counts, which works out to roughly 2200cpi. The tablet was designed to work with Windows default drivers, and did not come with any drivers. I have no idea how to request raw data out of it. > BTW, the original descriptor for interface 2 seems to have the correct range > and physical extents. You can take the extents from there at least, which seem > to be 4x2.5 inches. I find the HID encoding of units rather confusing. The descriptor seems to read 4x2.5 English inches, with a mistaken unit of cubic inches. If I have managed to figure out the system of HID correctly, the nibble value says what the exponent is for a unit in that position, so the inches should be 0x31. The only reason I didn't make the same mistake was that centimeters just happened to be written under column 1 in the nearly unreadable table. > Speaking of which, I think you need to make the report descriptor as simple as > possible to make it easier to get into the kernel. Strip it down to the > absolute minimum required to work. Remove unused report IDs and collections. Okay, stripping it down. > You can replace the multiplier fields with constant fields, if they're unused. > Also get rid of nested collections and repeated report IDs, if you can. I was mistaken about the resolution multiplier fields; the tablet really does use one of them for scrolling events. The other looks like it's horisontal scrolling, which there isn't a control for. > I would disable interface #2 here, if we can't make it work, with something > like this: Done. > BTW, can you make pull requests to digimend-kernel-drivers instead of sending > files? I think I may have figured it out. https://github.com/DIGImend/digimend-kernel-drivers/pull/11 |
|
From: Jiri K. <jk...@su...> - 2015-03-04 16:34:24
|
On Wed, 4 Mar 2015, Benjamin Tissoires wrote: > In commit 08177f4 (HID: uclogic: merge hid-huion driver in hid-uclogic) > HID_HUION depends explicitely on USB_HID because it contained quite some > USB-isms. > > Now that hid-uclogic is the new home of Huion tablets, we need to also > add the dependency on USB_HID to this driver. > > Reported-by: Jiri Kosina <jk...@su...> > Signed-off-by: Benjamin Tissoires <ben...@re...> > --- > > [CCing the DIGImend folks as a followup, this one is for upstream only] Applied to for-4.1/huion-uclogic-merge branch, thanks. -- Jiri Kosina SUSE Labs |
|
From: Nikolai K. <sp...@gm...> - 2015-03-04 16:27:14
|
On 03/04/2015 06:24 PM, Benjamin Tissoires wrote: > In commit 08177f4 (HID: uclogic: merge hid-huion driver in hid-uclogic) > HID_HUION depends explicitely on USB_HID because it contained quite some > USB-isms. > > Now that hid-uclogic is the new home of Huion tablets, we need to also > add the dependency on USB_HID to this driver. > > Reported-by: Jiri Kosina <jk...@su...> > Signed-off-by: Benjamin Tissoires <ben...@re...> Thanks, Benjamin, I wasn't fast enough. Nick |
|
From: Benjamin T. <ben...@re...> - 2015-03-04 16:25:06
|
In commit 08177f4 (HID: uclogic: merge hid-huion driver in hid-uclogic) HID_HUION depends explicitely on USB_HID because it contained quite some USB-isms. Now that hid-uclogic is the new home of Huion tablets, we need to also add the dependency on USB_HID to this driver. Reported-by: Jiri Kosina <jk...@su...> Signed-off-by: Benjamin Tissoires <ben...@re...> --- [CCing the DIGImend folks as a followup, this one is for upstream only] drivers/hid/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 8a55fd7..60c34cc 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -306,7 +306,7 @@ config HID_KYE config HID_UCLOGIC tristate "UC-Logic" - depends on HID + depends on USB_HID ---help--- Support for UC-Logic and Huion tablets. -- 2.1.0 |
|
From: Benjamin T. <ben...@re...> - 2015-03-04 16:16:28
|
On Mar 04 2015 or thereabouts, Jiri Kosina wrote: > On Tue, 3 Mar 2015, Benjamin Tissoires wrote: > > > From: Nikolai Kondrashov <Nik...@re...> > > > > Merge the hid-huion driver into hid-uclogic as all the devices supported > > by hid-huion are in fact UC-Logic devices. > > > > Signed-off-by: Nikolai Kondrashov <Nik...@re...> > > Signed-off-by: Benjamin Tissoires <ben...@re...> > > --- > > > > no changes in v3 > > no changes in v2 > > > > drivers/hid/Kconfig | 8 +- > > drivers/hid/Makefile | 1 - > > drivers/hid/hid-huion.c | 290 ---------------------------------------------- > > drivers/hid/hid-uclogic.c | 229 +++++++++++++++++++++++++++++++++++- > > 4 files changed, 229 insertions(+), 299 deletions(-) > > delete mode 100644 drivers/hid/hid-huion.c > > > > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig > > index 152b006..8a55fd7 100644 > > --- a/drivers/hid/Kconfig > > +++ b/drivers/hid/Kconfig > > @@ -286,12 +286,6 @@ config HID_GT683R > > Currently the following devices are know to be supported: > > - MSI GT683R > > > > -config HID_HUION > > - tristate "Huion tablets" > > - depends on USB_HID > > - ---help--- > > - Support for Huion 580 tablet. > > - > > The dependency on USB_HID was there actually on purpose, as the huion > driver contained quite some USB-isms. Those now got merged to uclogic, but > uclogic doesn't have USB_HID dependency. Oops, my bad. > > Could you guys please sort this out? Sure, I'll send a fix ASAP. Cheers, Benjamin |
|
From: Jiri K. <jk...@su...> - 2015-03-04 15:44:57
|
On Tue, 3 Mar 2015, Benjamin Tissoires wrote: > From: Nikolai Kondrashov <Nik...@re...> > > Merge the hid-huion driver into hid-uclogic as all the devices supported > by hid-huion are in fact UC-Logic devices. > > Signed-off-by: Nikolai Kondrashov <Nik...@re...> > Signed-off-by: Benjamin Tissoires <ben...@re...> > --- > > no changes in v3 > no changes in v2 > > drivers/hid/Kconfig | 8 +- > drivers/hid/Makefile | 1 - > drivers/hid/hid-huion.c | 290 ---------------------------------------------- > drivers/hid/hid-uclogic.c | 229 +++++++++++++++++++++++++++++++++++- > 4 files changed, 229 insertions(+), 299 deletions(-) > delete mode 100644 drivers/hid/hid-huion.c > > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig > index 152b006..8a55fd7 100644 > --- a/drivers/hid/Kconfig > +++ b/drivers/hid/Kconfig > @@ -286,12 +286,6 @@ config HID_GT683R > Currently the following devices are know to be supported: > - MSI GT683R > > -config HID_HUION > - tristate "Huion tablets" > - depends on USB_HID > - ---help--- > - Support for Huion 580 tablet. > - The dependency on USB_HID was there actually on purpose, as the huion driver contained quite some USB-isms. Those now got merged to uclogic, but uclogic doesn't have USB_HID dependency. Could you guys please sort this out? Thanks, -- Jiri Kosina SUSE Labs |
|
From: Nikolai K. <sp...@gm...> - 2015-03-03 23:19:57
|
On 03/03/2015 11:33 PM, Benjamin Tissoires wrote: > Hi Nick, > > I am not sure which way you prefer to merge changes in your trees, > so here is a classic pull request for digimend-kernel-drivers: > > The following changes since commit ba59fea4cfa67a70d26d803d7a423213b0863807: > > Bump module versions (2015-03-02 12:41:02 +0200) > > are available in the git repository at: > > https://github.com/bentiss/digimend-kernel-drivers input-names > > for you to fetch changes up to a1064d30eee56580c08f1d788155c5d8f22a3132: > > uclogic: actually invert the in-range bit for huion tablets only (2015-03-03 16:19:35 -0500) > > ---------------------------------------------------------------- > Benjamin Tissoires (5): > uclogic: Set quirks from inside the driver > uclogic: name the input nodes based on their tool > uclogic: apply quirk NO_EMPTY_INPUT > uclogic: discard the extra Pen input node on Huion tablets > uclogic: actually invert the in-range bit for huion tablets only > > hid-uclogic.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ > 1 file changed, 88 insertions(+), 18 deletions(-) > > I tried to stick to the upstream commits in case anything shows up. This > way, a bisect will also point out to the upstream commit :) Cool, that should be convenient! Thanks a lot, again, Benjamin :) Merged now. It was taking me forever to get around to this. A classic pull request is fine. Although you might want to add your Red Hat address to your profile to have commits attributed properly. Otherwise, a GitHub pull request is also good. Nick |
|
From: Benjamin T. <ben...@gm...> - 2015-03-03 21:33:19
|
Hi Nick, I am not sure which way you prefer to merge changes in your trees, so here is a classic pull request for digimend-kernel-drivers: The following changes since commit ba59fea4cfa67a70d26d803d7a423213b0863807: Bump module versions (2015-03-02 12:41:02 +0200) are available in the git repository at: https://github.com/bentiss/digimend-kernel-drivers input-names for you to fetch changes up to a1064d30eee56580c08f1d788155c5d8f22a3132: uclogic: actually invert the in-range bit for huion tablets only (2015-03-03 16:19:35 -0500) ---------------------------------------------------------------- Benjamin Tissoires (5): uclogic: Set quirks from inside the driver uclogic: name the input nodes based on their tool uclogic: apply quirk NO_EMPTY_INPUT uclogic: discard the extra Pen input node on Huion tablets uclogic: actually invert the in-range bit for huion tablets only hid-uclogic.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 18 deletions(-) I tried to stick to the upstream commits in case anything shows up. This way, a bisect will also point out to the upstream commit :) Cheers, Benjamin |
|
From: Jiri K. <jk...@su...> - 2015-03-03 20:34:36
|
On Tue, 3 Mar 2015, Benjamin Tissoires wrote: > Resent the full series with Nick's Rev-by and fixes in 6/6. > > Again, this is the upstream patches, DIGImend-devel is just added > to inform of the progress. I finally got to go through this patchset, good work, thanks for pursuing it. Now applied to for-4.1/huion-uclogic-merge. -- Jiri Kosina SUSE Labs |
|
From: Benjamin T. <ben...@re...> - 2015-03-03 19:20:41
|
On Mar 03 2015 or thereabouts, Nikolai Kondrashov wrote:
> On 03/03/2015 07:44 PM, Benjamin Tissoires wrote:
> >This hack is only needed for Huion tablets. It does not seem to have
> >any effect on the other tablets handled by this device right now, but
> >it's better to check for the product id sooner than discovering that
> >we have messed up one tablet later.
> >
> >Signed-off-by: Benjamin Tissoires <ben...@re...>
> >---
> >
> >changes in v3:
> >- stores a flag to know when to invert the bit.
> >- add #define UCLOGIC_PEN_REPORT_ID
> >
> >new in v2
> >
> > drivers/hid/hid-uclogic.c | 13 ++++++++-----
> > 1 file changed, 8 insertions(+), 5 deletions(-)
> >
> >diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
> >index f44e72b..bdda9fd 100644
> >--- a/drivers/hid/hid-uclogic.c
> >+++ b/drivers/hid/hid-uclogic.c
> >@@ -564,6 +564,7 @@ enum uclogic_ph_id {
> >
> > /* Report descriptor template placeholder */
> > #define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
> >+#define UCLOGIC_PEN_REPORT_ID 0x07
>
> It would be nice to also use this macro in the replaced report descriptor
> itself, but this will do for now.
Yeah. I thought about that too. I was about to send it that way, but
then I realized that we do not control the report ID from the device
(it's not overwritten by raw_event()). So it feels weird to just have
this macro in the middle of the report descriptor.
I think we can just leave it as it right now and maybe change the
whole thing later if needed.
>
> Reviewed-by: Nikolai Kondrashov <sp...@gm...>
Thanks!
>
> Thanks a lot, Benjamin!
>
No worries. Thanks for the reviews. Once Jiri will pull these, I'll send
the corresponding patches to DIGImend-devel for the digimend-kernel
tree.
Cheers,
Benjamin
> Nick
>
> P.S. I like the way you describe the changes between patchset versions, will
> have to keep it in mind and use in my own.
|
|
From: Nikolai K. <sp...@gm...> - 2015-03-03 18:43:50
|
On 03/03/2015 07:44 PM, Benjamin Tissoires wrote:
> This hack is only needed for Huion tablets. It does not seem to have
> any effect on the other tablets handled by this device right now, but
> it's better to check for the product id sooner than discovering that
> we have messed up one tablet later.
>
> Signed-off-by: Benjamin Tissoires <ben...@re...>
> ---
>
> changes in v3:
> - stores a flag to know when to invert the bit.
> - add #define UCLOGIC_PEN_REPORT_ID
>
> new in v2
>
> drivers/hid/hid-uclogic.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
> index f44e72b..bdda9fd 100644
> --- a/drivers/hid/hid-uclogic.c
> +++ b/drivers/hid/hid-uclogic.c
> @@ -564,6 +564,7 @@ enum uclogic_ph_id {
>
> /* Report descriptor template placeholder */
> #define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
> +#define UCLOGIC_PEN_REPORT_ID 0x07
It would be nice to also use this macro in the replaced report descriptor
itself, but this will do for now.
Reviewed-by: Nikolai Kondrashov <sp...@gm...>
Thanks a lot, Benjamin!
Nick
P.S. I like the way you describe the changes between patchset versions, will
have to keep it in mind and use in my own.
|
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:25
|
This hack is only needed for Huion tablets. It does not seem to have
any effect on the other tablets handled by this device right now, but
it's better to check for the product id sooner than discovering that
we have messed up one tablet later.
Signed-off-by: Benjamin Tissoires <ben...@re...>
---
changes in v3:
- stores a flag to know when to invert the bit.
- add #define UCLOGIC_PEN_REPORT_ID
new in v2
drivers/hid/hid-uclogic.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index f44e72b..bdda9fd 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -564,6 +564,7 @@ enum uclogic_ph_id {
/* Report descriptor template placeholder */
#define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
+#define UCLOGIC_PEN_REPORT_ID 0x07
/* Fixed report descriptor template */
static const __u8 uclogic_tablet_rdesc_template[] = {
@@ -625,6 +626,7 @@ enum uclogic_prm {
struct uclogic_drvdata {
__u8 *rdesc;
unsigned int rsize;
+ bool invert_pen_inrange;
};
static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -905,6 +907,7 @@ static int uclogic_probe(struct hid_device *hdev,
hid_err(hdev, "tablet enabling failed\n");
return rc;
}
+ drvdata->invert_pen_inrange = true;
}
break;
}
@@ -927,12 +930,12 @@ static int uclogic_probe(struct hid_device *hdev,
static int uclogic_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 uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
- /* If this is a pen input report */
- if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
- report->type == HID_INPUT_REPORT &&
- report->id == 0x07 && size >= 2)
+ if ((drvdata->invert_pen_inrange) &&
+ (report->type == HID_INPUT_REPORT) &&
+ (report->id == UCLOGIC_PEN_REPORT_ID) &&
+ (size >= 2))
/* Invert the in-range bit */
data[1] ^= 0x40;
--
2.1.0
|
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:21
|
Some Huion tablets present 2 HID Pen interfaces. Only one is used, so
we can drop the unused one.
Reviewed-by: Nikolai Kondrashov <sp...@gm...>
Signed-off-by: Benjamin Tissoires <ben...@re...>
---
no changes in v3
new in v2
drivers/hid/hid-uclogic.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index ada8a94..f44e72b 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -713,6 +713,25 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}
+static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct usb_interface *intf;
+
+ if (hdev->product == USB_DEVICE_ID_HUION_TABLET) {
+ intf = to_usb_interface(hdev->dev.parent);
+
+ /* discard the unused pen interface */
+ if ((intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
+ (field->application == HID_DG_PEN))
+ return -1;
+ }
+
+ /* let hid-core decide what to do */
+ return 0;
+}
+
static void uclogic_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
@@ -947,6 +966,7 @@ static struct hid_driver uclogic_driver = {
.probe = uclogic_probe,
.report_fixup = uclogic_report_fixup,
.raw_event = uclogic_raw_event,
+ .input_mapping = uclogic_input_mapping,
.input_configured = uclogic_input_configured,
};
module_hid_driver(uclogic_driver);
--
2.1.0
|
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:20
|
We append "Pen", "Pad", "Mouse", "Keyboard", "Consumer Control" or
"System Control" suffix to the appropriate input node to match what
the Wacom driver does and be more convenient for the user to know
which one is which.
Reviewed-by: Nikolai Kondrashov <sp...@gm...>
Signed-off-by: Benjamin Tissoires <ben...@re...>
---
no changes in v3
changes in v2:
- completed the list with "Consumer Control" and "System Control" to
force having a suffix to each input node on the Huion H610 Pro
drivers/hid/hid-uclogic.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 397f1df..90e2612 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -713,6 +713,51 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}
+static void uclogic_input_configured(struct hid_device *hdev,
+ struct hid_input *hi)
+{
+ char *name;
+ const char *suffix = NULL;
+ struct hid_field *field;
+ size_t len;
+
+ /* no report associated (HID_QUIRK_MULTI_INPUT not set) */
+ if (!hi->report)
+ return;
+
+ field = hi->report->field[0];
+
+ switch (field->application) {
+ case HID_GD_KEYBOARD:
+ suffix = "Keyboard";
+ break;
+ case HID_GD_MOUSE:
+ suffix = "Mouse";
+ break;
+ case HID_GD_KEYPAD:
+ suffix = "Pad";
+ break;
+ case HID_DG_PEN:
+ suffix = "Pen";
+ break;
+ case HID_CP_CONSUMER_CONTROL:
+ suffix = "Consumer Control";
+ break;
+ case HID_GD_SYSTEM_CONTROL:
+ suffix = "System Control";
+ break;
+ }
+
+ if (suffix) {
+ len = strlen(hdev->name) + 2 + strlen(suffix);
+ name = devm_kzalloc(&hi->input->dev, len, GFP_KERNEL);
+ if (name) {
+ snprintf(name, len, "%s %s", hdev->name, suffix);
+ hi->input->name = name;
+ }
+ }
+}
+
/**
* Enable fully-functional tablet mode and determine device parameters.
*
@@ -901,6 +946,7 @@ static struct hid_driver uclogic_driver = {
.probe = uclogic_probe,
.report_fixup = uclogic_report_fixup,
.raw_event = uclogic_raw_event,
+ .input_configured = uclogic_input_configured,
};
module_hid_driver(uclogic_driver);
--
2.1.0
|
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:20
|
NO_EMPTY_INPUT is useful when MULTI_INPUT is set. It prevents to create empty input nodes that user space does not know what to do with. It does not seem to be required at the moment, this is just a preventive patch. This check is only made during the plug of the device, so it does not hurt to have it. Reviewed-by: Nikolai Kondrashov <sp...@gm...> Signed-off-by: Benjamin Tissoires <ben...@re...> --- no changes in v3 new in v2 drivers/hid/hid-uclogic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index 90e2612..ada8a94 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c @@ -868,6 +868,7 @@ static int uclogic_probe(struct hid_device *hdev, * than the pen, so use QUIRK_MULTI_INPUT for all tablets. */ hdev->quirks |= HID_QUIRK_MULTI_INPUT; + hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; /* Allocate and assign driver data */ drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); -- 2.1.0 |
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:19
|
Based on a patch from: Nikolai Kondrashov <Nik...@re...> Most of the tablets handled by hid-uclogic already use MULTI_INPUT. For the ones which are not quirked in usbhid/hidquirks, they have a custom report descriptor which contains only one report per HID interface. For those tablets HID_QUIRK_MULTI_INPUT is transparent. According to https://github.com/DIGImend/tablets, the only problematic tablet currently handled by hid-uclogic is the TWHA60 v3. This tablet presents different report descriptors from the ones currently quirked. This is not a problem per se, given that this tablet is not supported currently in this version (it needs the same command as a Huion to start forwarding events). Reviewed-by: Nikolai Kondrashov <sp...@gm...> Signed-off-by: Benjamin Tissoires <ben...@re...> --- no changes in v3 no changes in v2 drivers/hid/hid-uclogic.c | 27 +++++++++++++++++++++++++++ drivers/hid/usbhid/hid-quirks.c | 4 ---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index fb8b516..22dccce 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c @@ -626,6 +626,32 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } +static int uclogic_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int rc; + + /* + * libinput requires the pad interface to be on a different node + * than the pen, so use QUIRK_MULTI_INPUT for all tablets. + */ + hdev->quirks |= HID_QUIRK_MULTI_INPUT; + + rc = hid_parse(hdev); + if (rc) { + hid_err(hdev, "parse failed\n"); + return rc; + } + + rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (rc) { + hid_err(hdev, "hw start failed\n"); + return rc; + } + + return 0; +} + static const struct hid_device_id uclogic_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, @@ -648,6 +674,7 @@ MODULE_DEVICE_TABLE(hid, uclogic_devices); static struct hid_driver uclogic_driver = { .name = "uclogic", .id_table = uclogic_devices, + .probe = uclogic_probe, .report_fixup = uclogic_report_fixup, }; module_hid_driver(uclogic_driver); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 989c59a..75ca2de 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -106,12 +106,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT }, -- 2.1.0 |
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:19
|
From: Nikolai Kondrashov <Nik...@re...>
Merge the hid-huion driver into hid-uclogic as all the devices supported
by hid-huion are in fact UC-Logic devices.
Signed-off-by: Nikolai Kondrashov <Nik...@re...>
Signed-off-by: Benjamin Tissoires <ben...@re...>
---
no changes in v3
no changes in v2
drivers/hid/Kconfig | 8 +-
drivers/hid/Makefile | 1 -
drivers/hid/hid-huion.c | 290 ----------------------------------------------
drivers/hid/hid-uclogic.c | 229 +++++++++++++++++++++++++++++++++++-
4 files changed, 229 insertions(+), 299 deletions(-)
delete mode 100644 drivers/hid/hid-huion.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 152b006..8a55fd7 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -286,12 +286,6 @@ config HID_GT683R
Currently the following devices are know to be supported:
- MSI GT683R
-config HID_HUION
- tristate "Huion tablets"
- depends on USB_HID
- ---help---
- Support for Huion 580 tablet.
-
config HID_KEYTOUCH
tristate "Keytouch HID devices"
depends on HID
@@ -314,7 +308,7 @@ config HID_UCLOGIC
tristate "UC-Logic"
depends on HID
---help---
- Support for UC-Logic tablets.
+ Support for UC-Logic and Huion tablets.
config HID_WALTOP
tristate "Waltop"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6f19958..9c399fe 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
-obj-$(CONFIG_HID_HUION) += hid-huion.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c
deleted file mode 100644
index 61b68ca..0000000
--- a/drivers/hid/hid-huion.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * HID driver for Huion devices not fully compliant with HID standard
- *
- * Copyright (c) 2013 Martin Rusko
- * Copyright (c) 2014 Nikolai Kondrashov
- */
-
-/*
- * 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/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <asm/unaligned.h>
-#include "usbhid/usbhid.h"
-
-#include "hid-ids.h"
-
-/* Report descriptor template placeholder head */
-#define HUION_PH_HEAD 0xFE, 0xED, 0x1D
-
-/* Report descriptor template placeholder IDs */
-enum huion_ph_id {
- HUION_PH_ID_X_LM,
- HUION_PH_ID_X_PM,
- HUION_PH_ID_Y_LM,
- HUION_PH_ID_Y_PM,
- HUION_PH_ID_PRESSURE_LM,
- HUION_PH_ID_NUM
-};
-
-/* Report descriptor template placeholder */
-#define HUION_PH(_ID) HUION_PH_HEAD, HUION_PH_ID_##_ID
-
-/* Fixed report descriptor template */
-static const __u8 huion_tablet_rdesc_template[] = {
- 0x05, 0x0D, /* Usage Page (Digitizer), */
- 0x09, 0x02, /* Usage (Pen), */
- 0xA1, 0x01, /* Collection (Application), */
- 0x85, 0x07, /* Report ID (7), */
- 0x09, 0x20, /* Usage (Stylus), */
- 0xA0, /* Collection (Physical), */
- 0x14, /* Logical Minimum (0), */
- 0x25, 0x01, /* Logical Maximum (1), */
- 0x75, 0x01, /* Report Size (1), */
- 0x09, 0x42, /* Usage (Tip Switch), */
- 0x09, 0x44, /* Usage (Barrel Switch), */
- 0x09, 0x46, /* Usage (Tablet Pick), */
- 0x95, 0x03, /* Report Count (3), */
- 0x81, 0x02, /* Input (Variable), */
- 0x95, 0x03, /* Report Count (3), */
- 0x81, 0x03, /* Input (Constant, Variable), */
- 0x09, 0x32, /* Usage (In Range), */
- 0x95, 0x01, /* Report Count (1), */
- 0x81, 0x02, /* Input (Variable), */
- 0x95, 0x01, /* Report Count (1), */
- 0x81, 0x03, /* Input (Constant, Variable), */
- 0x75, 0x10, /* Report Size (16), */
- 0x95, 0x01, /* Report Count (1), */
- 0xA4, /* Push, */
- 0x05, 0x01, /* Usage Page (Desktop), */
- 0x65, 0x13, /* Unit (Inch), */
- 0x55, 0xFD, /* Unit Exponent (-3), */
- 0x34, /* Physical Minimum (0), */
- 0x09, 0x30, /* Usage (X), */
- 0x27, HUION_PH(X_LM), /* Logical Maximum (PLACEHOLDER), */
- 0x47, HUION_PH(X_PM), /* Physical Maximum (PLACEHOLDER), */
- 0x81, 0x02, /* Input (Variable), */
- 0x09, 0x31, /* Usage (Y), */
- 0x27, HUION_PH(Y_LM), /* Logical Maximum (PLACEHOLDER), */
- 0x47, HUION_PH(Y_PM), /* Physical Maximum (PLACEHOLDER), */
- 0x81, 0x02, /* Input (Variable), */
- 0xB4, /* Pop, */
- 0x09, 0x30, /* Usage (Tip Pressure), */
- 0x27,
- HUION_PH(PRESSURE_LM), /* Logical Maximum (PLACEHOLDER), */
- 0x81, 0x02, /* Input (Variable), */
- 0xC0, /* End Collection, */
- 0xC0 /* End Collection */
-};
-
-/* Parameter indices */
-enum huion_prm {
- HUION_PRM_X_LM = 1,
- HUION_PRM_Y_LM = 2,
- HUION_PRM_PRESSURE_LM = 4,
- HUION_PRM_RESOLUTION = 5,
- HUION_PRM_NUM
-};
-
-/* Driver data */
-struct huion_drvdata {
- __u8 *rdesc;
- unsigned int rsize;
-};
-
-static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
- unsigned int *rsize)
-{
- struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
- switch (hdev->product) {
- case USB_DEVICE_ID_HUION_TABLET:
- if (drvdata->rdesc != NULL) {
- rdesc = drvdata->rdesc;
- *rsize = drvdata->rsize;
- }
- break;
- }
- return rdesc;
-}
-
-/**
- * Enable fully-functional tablet mode and determine device parameters.
- *
- * @hdev: HID device
- */
-static int huion_tablet_enable(struct hid_device *hdev)
-{
- int rc;
- struct usb_device *usb_dev = hid_to_usb_dev(hdev);
- struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
- __le16 *buf = NULL;
- size_t len;
- s32 params[HUION_PH_ID_NUM];
- s32 resolution;
- __u8 *p;
- s32 v;
-
- /*
- * Read string descriptor containing tablet parameters. The specific
- * string descriptor and data were discovered by sniffing the Windows
- * driver traffic.
- * NOTE: This enables fully-functional tablet mode.
- */
- len = HUION_PRM_NUM * sizeof(*buf);
- buf = kmalloc(len, GFP_KERNEL);
- if (buf == NULL) {
- hid_err(hdev, "failed to allocate parameter buffer\n");
- rc = -ENOMEM;
- goto cleanup;
- }
- rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (USB_DT_STRING << 8) + 0x64,
- 0x0409, buf, len,
- USB_CTRL_GET_TIMEOUT);
- if (rc == -EPIPE) {
- hid_err(hdev, "device parameters not found\n");
- rc = -ENODEV;
- goto cleanup;
- } else if (rc < 0) {
- hid_err(hdev, "failed to get device parameters: %d\n", rc);
- rc = -ENODEV;
- goto cleanup;
- } else if (rc != len) {
- hid_err(hdev, "invalid device parameters\n");
- rc = -ENODEV;
- goto cleanup;
- }
-
- /* Extract device parameters */
- params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
- params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
- params[HUION_PH_ID_PRESSURE_LM] =
- le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
- resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
- if (resolution == 0) {
- params[HUION_PH_ID_X_PM] = 0;
- params[HUION_PH_ID_Y_PM] = 0;
- } else {
- params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
- 1000 / resolution;
- params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
- 1000 / resolution;
- }
-
- /* Allocate fixed report descriptor */
- drvdata->rdesc = devm_kmalloc(&hdev->dev,
- sizeof(huion_tablet_rdesc_template),
- GFP_KERNEL);
- if (drvdata->rdesc == NULL) {
- hid_err(hdev, "failed to allocate fixed rdesc\n");
- rc = -ENOMEM;
- goto cleanup;
- }
- drvdata->rsize = sizeof(huion_tablet_rdesc_template);
-
- /* Format fixed report descriptor */
- memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
- drvdata->rsize);
- for (p = drvdata->rdesc;
- p <= drvdata->rdesc + drvdata->rsize - 4;) {
- if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
- p[3] < sizeof(params)) {
- v = params[p[3]];
- put_unaligned(cpu_to_le32(v), (s32 *)p);
- p += 4;
- } else {
- p++;
- }
- }
-
- rc = 0;
-
-cleanup:
- kfree(buf);
- return rc;
-}
-
-static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int rc;
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct huion_drvdata *drvdata;
-
- /* Allocate and assign driver data */
- drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
- if (drvdata == NULL) {
- hid_err(hdev, "failed to allocate driver data\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, drvdata);
-
- switch (id->product) {
- case USB_DEVICE_ID_HUION_TABLET:
- /* If this is the pen interface */
- if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
- rc = huion_tablet_enable(hdev);
- if (rc) {
- hid_err(hdev, "tablet enabling failed\n");
- return rc;
- }
- }
- break;
- }
-
- rc = hid_parse(hdev);
- if (rc) {
- hid_err(hdev, "parse failed\n");
- return rc;
- }
-
- rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (rc) {
- hid_err(hdev, "hw start failed\n");
- return rc;
- }
-
- return 0;
-}
-
-static int huion_raw_event(struct hid_device *hdev, struct hid_report *report,
- u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-
- /* If this is a pen input report */
- if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
- report->type == HID_INPUT_REPORT &&
- report->id == 0x07 && size >= 2)
- /* Invert the in-range bit */
- data[1] ^= 0x40;
-
- return 0;
-}
-
-static const struct hid_device_id huion_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
- { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, huion_devices);
-
-static struct hid_driver huion_driver = {
- .name = "huion",
- .id_table = huion_devices,
- .probe = huion_probe,
- .report_fixup = huion_report_fixup,
- .raw_event = huion_raw_event,
-};
-module_hid_driver(huion_driver);
-
-MODULE_AUTHOR("Martin Rusko");
-MODULE_DESCRIPTION("Huion HID driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 22dccce..397f1df 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -1,7 +1,8 @@
/*
* HID driver for UC-Logic devices not fully compliant with HID standard
*
- * Copyright (c) 2010 Nikolai Kondrashov
+ * Copyright (c) 2010-2014 Nikolai Kondrashov
+ * Copyright (c) 2013 Martin Rusko
*/
/*
@@ -15,6 +16,8 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <asm/unaligned.h>
+#include "usbhid/usbhid.h"
#include "hid-ids.h"
@@ -546,11 +549,90 @@ static __u8 twha60_rdesc_fixed1[] = {
0xC0 /* End Collection */
};
+/* Report descriptor template placeholder head */
+#define UCLOGIC_PH_HEAD 0xFE, 0xED, 0x1D
+
+/* Report descriptor template placeholder IDs */
+enum uclogic_ph_id {
+ UCLOGIC_PH_ID_X_LM,
+ UCLOGIC_PH_ID_X_PM,
+ UCLOGIC_PH_ID_Y_LM,
+ UCLOGIC_PH_ID_Y_PM,
+ UCLOGIC_PH_ID_PRESSURE_LM,
+ UCLOGIC_PH_ID_NUM
+};
+
+/* Report descriptor template placeholder */
+#define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
+
+/* Fixed report descriptor template */
+static const __u8 uclogic_tablet_rdesc_template[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x02, /* Usage (Pen), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x07, /* Report ID (7), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x46, /* Usage (Tablet Pick), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x34, /* Physical Minimum (0), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x27, UCLOGIC_PH(X_LM), /* Logical Maximum (PLACEHOLDER), */
+ 0x47, UCLOGIC_PH(X_PM), /* Physical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x27, UCLOGIC_PH(Y_LM), /* Logical Maximum (PLACEHOLDER), */
+ 0x47, UCLOGIC_PH(Y_PM), /* Physical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x27,
+ UCLOGIC_PH(PRESSURE_LM),/* Logical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+};
+
+/* Parameter indices */
+enum uclogic_prm {
+ UCLOGIC_PRM_X_LM = 1,
+ UCLOGIC_PRM_Y_LM = 2,
+ UCLOGIC_PRM_PRESSURE_LM = 4,
+ UCLOGIC_PRM_RESOLUTION = 5,
+ UCLOGIC_PRM_NUM
+};
+
+/* Driver data */
+struct uclogic_drvdata {
+ __u8 *rdesc;
+ unsigned int rsize;
+};
+
static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+ struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
switch (hdev->product) {
case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
@@ -621,15 +703,120 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
break;
}
break;
+ default:
+ if (drvdata->rdesc != NULL) {
+ rdesc = drvdata->rdesc;
+ *rsize = drvdata->rsize;
+ }
}
return rdesc;
}
+/**
+ * Enable fully-functional tablet mode and determine device parameters.
+ *
+ * @hdev: HID device
+ */
+static int uclogic_tablet_enable(struct hid_device *hdev)
+{
+ int rc;
+ struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+ struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
+ __le16 *buf = NULL;
+ size_t len;
+ s32 params[UCLOGIC_PH_ID_NUM];
+ s32 resolution;
+ __u8 *p;
+ s32 v;
+
+ /*
+ * Read string descriptor containing tablet parameters. The specific
+ * string descriptor and data were discovered by sniffing the Windows
+ * driver traffic.
+ * NOTE: This enables fully-functional tablet mode.
+ */
+ len = UCLOGIC_PRM_NUM * sizeof(*buf);
+ buf = kmalloc(len, GFP_KERNEL);
+ if (buf == NULL) {
+ hid_err(hdev, "failed to allocate parameter buffer\n");
+ rc = -ENOMEM;
+ goto cleanup;
+ }
+ rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (USB_DT_STRING << 8) + 0x64,
+ 0x0409, buf, len,
+ USB_CTRL_GET_TIMEOUT);
+ if (rc == -EPIPE) {
+ hid_err(hdev, "device parameters not found\n");
+ rc = -ENODEV;
+ goto cleanup;
+ } else if (rc < 0) {
+ hid_err(hdev, "failed to get device parameters: %d\n", rc);
+ rc = -ENODEV;
+ goto cleanup;
+ } else if (rc != len) {
+ hid_err(hdev, "invalid device parameters\n");
+ rc = -ENODEV;
+ goto cleanup;
+ }
+
+ /* Extract device parameters */
+ params[UCLOGIC_PH_ID_X_LM] = le16_to_cpu(buf[UCLOGIC_PRM_X_LM]);
+ params[UCLOGIC_PH_ID_Y_LM] = le16_to_cpu(buf[UCLOGIC_PRM_Y_LM]);
+ params[UCLOGIC_PH_ID_PRESSURE_LM] =
+ le16_to_cpu(buf[UCLOGIC_PRM_PRESSURE_LM]);
+ resolution = le16_to_cpu(buf[UCLOGIC_PRM_RESOLUTION]);
+ if (resolution == 0) {
+ params[UCLOGIC_PH_ID_X_PM] = 0;
+ params[UCLOGIC_PH_ID_Y_PM] = 0;
+ } else {
+ params[UCLOGIC_PH_ID_X_PM] = params[UCLOGIC_PH_ID_X_LM] *
+ 1000 / resolution;
+ params[UCLOGIC_PH_ID_Y_PM] = params[UCLOGIC_PH_ID_Y_LM] *
+ 1000 / resolution;
+ }
+
+ /* Allocate fixed report descriptor */
+ drvdata->rdesc = devm_kzalloc(&hdev->dev,
+ sizeof(uclogic_tablet_rdesc_template),
+ GFP_KERNEL);
+ if (drvdata->rdesc == NULL) {
+ hid_err(hdev, "failed to allocate fixed rdesc\n");
+ rc = -ENOMEM;
+ goto cleanup;
+ }
+ drvdata->rsize = sizeof(uclogic_tablet_rdesc_template);
+
+ /* Format fixed report descriptor */
+ memcpy(drvdata->rdesc, uclogic_tablet_rdesc_template,
+ drvdata->rsize);
+ for (p = drvdata->rdesc;
+ p <= drvdata->rdesc + drvdata->rsize - 4;) {
+ if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
+ p[3] < sizeof(params)) {
+ v = params[p[3]];
+ put_unaligned(cpu_to_le32(v), (s32 *)p);
+ p += 4;
+ } else {
+ p++;
+ }
+ }
+
+ rc = 0;
+
+cleanup:
+ kfree(buf);
+ return rc;
+}
+
static int uclogic_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int rc;
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct uclogic_drvdata *drvdata;
/*
* libinput requires the pad interface to be on a different node
@@ -637,6 +824,26 @@ static int uclogic_probe(struct hid_device *hdev,
*/
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+ /* Allocate and assign driver data */
+ drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+ if (drvdata == NULL)
+ return -ENOMEM;
+
+ hid_set_drvdata(hdev, drvdata);
+
+ switch (id->product) {
+ case USB_DEVICE_ID_HUION_TABLET:
+ /* If this is the pen interface */
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+ rc = uclogic_tablet_enable(hdev);
+ if (rc) {
+ hid_err(hdev, "tablet enabling failed\n");
+ return rc;
+ }
+ }
+ break;
+ }
+
rc = hid_parse(hdev);
if (rc) {
hid_err(hdev, "parse failed\n");
@@ -652,6 +859,21 @@ static int uclogic_probe(struct hid_device *hdev,
return 0;
}
+static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+ /* If this is a pen input report */
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
+ report->type == HID_INPUT_REPORT &&
+ report->id == 0x07 && size >= 2)
+ /* Invert the in-range bit */
+ data[1] ^= 0x40;
+
+ return 0;
+}
+
static const struct hid_device_id uclogic_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
@@ -667,6 +889,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
{ }
};
MODULE_DEVICE_TABLE(hid, uclogic_devices);
@@ -676,7 +900,10 @@ static struct hid_driver uclogic_driver = {
.id_table = uclogic_devices,
.probe = uclogic_probe,
.report_fixup = uclogic_report_fixup,
+ .raw_event = uclogic_raw_event,
};
module_hid_driver(uclogic_driver);
+MODULE_AUTHOR("Martin Rusko");
+MODULE_AUTHOR("Nikolai Kondrashov");
MODULE_LICENSE("GPL");
--
2.1.0
|
|
From: Benjamin T. <ben...@re...> - 2015-03-03 17:44:17
|
Resent the full series with Nick's Rev-by and fixes in 6/6. Again, this is the upstream patches, DIGImend-devel is just added to inform of the progress. Cheers, Benjamin Benjamin Tissoires (6): HID: uclogic: Set quirks from inside the driver HID: uclogic: merge hid-huion driver in hid-uclogic HID: uclogic: name the input nodes based on their tool HID: uclogic: apply quirk NO_EMPTY_INPUT HID: uclogic: discard the extra Pen input node on Huion tablets HID: uclogic: actually invert the in-range bit for huion tablets only drivers/hid/Kconfig | 8 +- drivers/hid/Makefile | 1 - drivers/hid/hid-huion.c | 290 ----------------------------------- drivers/hid/hid-uclogic.c | 326 +++++++++++++++++++++++++++++++++++++++- drivers/hid/usbhid/hid-quirks.c | 4 - 5 files changed, 326 insertions(+), 303 deletions(-) delete mode 100644 drivers/hid/hid-huion.c -- 2.1.0 |
|
From: Nikolai K. <sp...@gm...> - 2015-03-03 10:55:06
|
On 03/03/2015 12:25 AM, Benjamin Tissoires wrote: > On Feb 28 2015 or thereabouts, Nikolai Kondrashov wrote: >> On 02/26/2015 08:57 PM, Benjamin Tissoires wrote: >>> This hack is only needed for Huion tablets. It does not seem to have >>> any effect on the other tablets handled by this device right now, but >>> it's better to check for the product id sooner than discovering that >>> we have messed up one tablet later. >>> >>> Signed-off-by: Benjamin Tissoires <ben...@re...> >>> --- >>> >>> New in v2 >>> >>> drivers/hid/hid-uclogic.c | 3 ++- >>> 1 file changed, 2 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c >>> index f44e72b..5f5c16e 100644 >>> --- a/drivers/hid/hid-uclogic.c >>> +++ b/drivers/hid/hid-uclogic.c >>> @@ -930,7 +930,8 @@ static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report, >>> struct usb_interface *intf = to_usb_interface(hdev->dev.parent); >>> >>> /* If this is a pen input report */ >>> - if (intf->cur_altsetting->desc.bInterfaceNumber == 0 && >>> + if (hdev->product == USB_DEVICE_ID_HUION_TABLET && >>> + intf->cur_altsetting->desc.bInterfaceNumber == 0 && >>> report->type == HID_INPUT_REPORT && >>> report->id == 0x07 && size >= 2) >>> /* Invert the in-range bit */ >> >> Right, I completely forgot about this. That's why it's important to put these >> things out for testing. > > yes, and no. A thorough review can help detect these while it's a pain > to ask each and every users to test every possible device :) Perhaps :) >> However, this should be inverted not just for Huion tablets, but rather for >> all "enabled" tablets. The UC-Logic TWHA60 v3 inverts that bit as well when >> enabled, IIRC. We can filter enabled tablets by drvdata->rdesc != NULL, or add >> an explicit flag. > > I like the flag. It will remove the dependency to usb in raw_event() > which is always a plus. Great! > Speaking of which. I started looking at these dependencies in the hid > subtree (like every year, in spring, these dependencies itches me). > I think we can find a preventive solution which would allow to reinject > through uhid any device even if the driver wants to talk to the usb > layer. This will require some more effort on my side but will allow us > to have at least some regressions tests in hid-uclogic too. This sounds good. I was thinking about record/replay on HID level over uhid, similar to evdev level, but as usual didn't have time to even think it through (it's not my day job). Nick |
|
From: Benjamin T. <ben...@re...> - 2015-03-02 22:25:52
|
On Feb 28 2015 or thereabouts, Nikolai Kondrashov wrote: > On 02/26/2015 08:57 PM, Benjamin Tissoires wrote: > >This hack is only needed for Huion tablets. It does not seem to have > >any effect on the other tablets handled by this device right now, but > >it's better to check for the product id sooner than discovering that > >we have messed up one tablet later. > > > >Signed-off-by: Benjamin Tissoires <ben...@re...> > >--- > > > >New in v2 > > > > drivers/hid/hid-uclogic.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > >diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c > >index f44e72b..5f5c16e 100644 > >--- a/drivers/hid/hid-uclogic.c > >+++ b/drivers/hid/hid-uclogic.c > >@@ -930,7 +930,8 @@ static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report, > > struct usb_interface *intf = to_usb_interface(hdev->dev.parent); > > > > /* If this is a pen input report */ > >- if (intf->cur_altsetting->desc.bInterfaceNumber == 0 && > >+ if (hdev->product == USB_DEVICE_ID_HUION_TABLET && > >+ intf->cur_altsetting->desc.bInterfaceNumber == 0 && > > report->type == HID_INPUT_REPORT && > > report->id == 0x07 && size >= 2) > > /* Invert the in-range bit */ > > Right, I completely forgot about this. That's why it's important to put these > things out for testing. yes, and no. A thorough review can help detect these while it's a pain to ask each and every users to test every possible device :) > > However, this should be inverted not just for Huion tablets, but rather for > all "enabled" tablets. The UC-Logic TWHA60 v3 inverts that bit as well when > enabled, IIRC. We can filter enabled tablets by drvdata->rdesc != NULL, or add > an explicit flag. I like the flag. It will remove the dependency to usb in raw_event() which is always a plus. Speaking of which. I started looking at these dependencies in the hid subtree (like every year, in spring, these dependencies itches me). I think we can find a preventive solution which would allow to reinject through uhid any device even if the driver wants to talk to the usb layer. This will require some more effort on my side but will allow us to have at least some regressions tests in hid-uclogic too. Cheers, Benjamin |
|
From: Nikolai K. <sp...@gm...> - 2015-03-01 18:13:16
|
On 02/26/2015 08:57 PM, Benjamin Tissoires wrote: > Some Huion tablets present 2 HID Pen interfaces. Only one is used, so > we can drop the unused one. > > Signed-off-by: Benjamin Tissoires <ben...@re...> This is what might have been plaguing GIMP users. Thanks, Benjamin! Reviewed-by: Nikolai Kondrashov <sp...@gm...> Nick |
|
From: Nikolai K. <sp...@gm...> - 2015-03-01 18:08:01
|
On 02/26/2015 08:57 PM, Benjamin Tissoires wrote: > NO_EMPTY_INPUT is useful when MULTI_INPUT is set. It prevents to create > empty input nodes that user space does not know what to do with. > > It does not seem to be required at the moment, this is just a preventive > patch. This check is only made during the plug of the device, so it does > not hurt to have it. > > Signed-off-by: Benjamin Tissoires <ben...@re...> > --- > > New in v2 > > drivers/hid/hid-uclogic.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c > index 90e2612..ada8a94 100644 > --- a/drivers/hid/hid-uclogic.c > +++ b/drivers/hid/hid-uclogic.c > @@ -868,6 +868,7 @@ static int uclogic_probe(struct hid_device *hdev, > * than the pen, so use QUIRK_MULTI_INPUT for all tablets. > */ > hdev->quirks |= HID_QUIRK_MULTI_INPUT; > + hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; > > /* Allocate and assign driver data */ > drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); This seems safe and fine as a preventive. Reviewed-by: Nikolai Kondrashov <sp...@gm...> Nick |
|
From: Nikolai K. <sp...@gm...> - 2015-03-01 18:04:54
|
On 02/26/2015 08:57 PM, Benjamin Tissoires wrote: > We append "Pen", "Pad", "Mouse", "Keyboard", "Consumer Control" or > "System Control" suffix to the appropriate input node to match what > the Wacom driver does and be more convenient for the user to know > which one is which. > > Signed-off-by: Benjamin Tissoires <ben...@re...> I read the kernel code and tested this a little. This looks and works fine. Reviewed-by: Nikolai Kondrashov <sp...@gm...> |