* calibrating a hid device
@ 2010-05-24 20:11 Rafi Rubin
[not found] ` <4BFADD60.7020901-hkHJxBBPWjbG6jMu9gPlYQ@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Rafi Rubin @ 2010-05-24 20:11 UTC (permalink / raw)
To: linux-input, Jiri Kosina, linux-usb; +Cc: Dmitry Torokhov
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I've written a calibration tool for my touch screen that works well from user
space (just sends a few commands over usb telling the digitizer to recalibrate
and reset itself). I've been running that with the ntrig and usbhid modules
unloaded.
Now I'm trying to translate that to something in the kernel which I can run just
by poking a sysfs node. However as I sort of expected, it doesn't actually work
quite right. I've been seeing something like this:
- From user space:
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 0:2 94 = 033fbc07 0000a014 f012ce01 68010100 000c0701 00000000
00fa0096 00000b00
kernel space:
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 -2:2 0
What sort of calls should I wrap the calibration code with?
Also, the process seems to involve telling the digitizer to go off and run
calibration, and then interrupting it after a while. I've been using a number
of microseconds dumped to the sysfs node for that. Is there any harm in using
"msleep(val);"?
Once I get this sorted out, I'll clean up the code a bit and send in some
patches (and documentation for this and filtering).
Rafi
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkv63V0ACgkQwuRiAT9o609I3gCgg9ZKGqwWFsZQa2wyX270JlGq
qj4An1w776oL0CiLEZPnKFwvIT0PDKWV
=dtIw
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calibrating a hid device
[not found] ` <4BFADD60.7020901-hkHJxBBPWjbG6jMu9gPlYQ@public.gmane.org>
@ 2010-05-24 20:20 ` Jiri Kosina
2010-05-24 22:54 ` Rafi Rubin
0 siblings, 1 reply; 5+ messages in thread
From: Jiri Kosina @ 2010-05-24 20:20 UTC (permalink / raw)
To: Rafi Rubin; +Cc: linux-input, linux-usb-u79uwXL29TY76Z2rM5mHXA, Dmitry Torokhov
On Mon, 24 May 2010, Rafi Rubin wrote:
> I've written a calibration tool for my touch screen that works well from user
> space (just sends a few commands over usb telling the digitizer to recalibrate
> and reset itself). I've been running that with the ntrig and usbhid modules
> unloaded.
>
> Now I'm trying to translate that to something in the kernel which I can run just
> by poking a sysfs node. However as I sort of expected, it doesn't actually work
> quite right. I've been seeing something like this:
>
> - From user space:
> S Ii:3:002:2 -115:2 94 <
> C Ii:3:002:2 0:2 94 = 033fbc07 0000a014 f012ce01 68010100 000c0701 00000000
> 00fa0096 00000b00
>
> kernel space:
> S Ii:3:002:2 -115:2 94 <
> C Ii:3:002:2 -2:2 0
>
> What sort of calls should I wrap the calibration code with?
And what exactly are you doing from the sysfs-triggered code? I'd guess
that simply calling usb_control_msg() should be enough, but without
actually seeing the working userspace version and its (non-working)
kernel-side counterpart, it's really a little bit difficult to tell.
> Also, the process seems to involve telling the digitizer to go off and run
> calibration, and then interrupting it after a while. I've been using a number
> of microseconds dumped to the sysfs node for that. Is there any harm in using
> "msleep(val);"?
Depends on the context. If called from context that can safely sleep, it's
fine.
--
Jiri Kosina
SUSE Labs, Novell Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calibrating a hid device
2010-05-24 20:20 ` Jiri Kosina
@ 2010-05-24 22:54 ` Rafi Rubin
2010-05-25 1:59 ` Alan Stern
0 siblings, 1 reply; 5+ messages in thread
From: Rafi Rubin @ 2010-05-24 22:54 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, linux-usb, Dmitry Torokhov
[-- Attachment #1: Type: text/plain, Size: 2184 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 05/24/10 16:20, Jiri Kosina wrote:
> On Mon, 24 May 2010, Rafi Rubin wrote:
>
>> I've written a calibration tool for my touch screen that works well from user
>> space (just sends a few commands over usb telling the digitizer to recalibrate
>> and reset itself). I've been running that with the ntrig and usbhid modules
>> unloaded.
>>
>> Now I'm trying to translate that to something in the kernel which I can run just
>> by poking a sysfs node. However as I sort of expected, it doesn't actually work
>> quite right. I've been seeing something like this:
>>
>> - From user space:
>> S Ii:3:002:2 -115:2 94 <
>> C Ii:3:002:2 0:2 94 = 033fbc07 0000a014 f012ce01 68010100 000c0701 00000000
>> 00fa0096 00000b00
>>
>> kernel space:
>> S Ii:3:002:2 -115:2 94 <
>> C Ii:3:002:2 -2:2 0
>>
>> What sort of calls should I wrap the calibration code with?
>
> And what exactly are you doing from the sysfs-triggered code? I'd guess
> that simply calling usb_control_msg() should be enough, but without
> actually seeing the working userspace version and its (non-working)
> kernel-side counterpart, it's really a little bit difficult to tell.
>
>> Also, the process seems to involve telling the digitizer to go off and run
>> calibration, and then interrupting it after a while. I've been using a number
>> of microseconds dumped to the sysfs node for that. Is there any harm in using
>> "msleep(val);"?
>
> Depends on the context. If called from context that can safely sleep, it's
> fine.
>
Ok, pardon that excessive attachments. Attached is a snip of the kernel code,
just the sysfs function, the user space equivalent, and logs of both (with the
time stamps cropped out for comparison.
Also please put on slop code filter glasses before reading the code, I hold no
responsibility to damaged eyes or loss of sanity. It will be cleaned up, later.
Rafi
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkv7A7MACgkQwuRiAT9o609u/wCeO7LWUUyqr/wvbAIawpxVl5Dg
UNAAn3UYhBbaJxpTnzD+r1iM6jpopx7t
=TtOJ
-----END PGP SIGNATURE-----
[-- Attachment #2: kernel_snip.c --]
[-- Type: text/x-csrc, Size: 2585 bytes --]
static ssize_t set_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct usb_device *udev = hid_to_usb_dev(hdev);
unsigned long val;
int ret;
unsigned char data[2] = {0,0};
__u16 value = 0x402;
__u16 index = 0x100;
if (strict_strtoul(buf, 0, &val))
return -EINVAL;
if (val > 3)
return -EINVAL;
data[0] = (unsigned char) val;
ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
0xf, 0x40, value, index, data, 2, 1000);
return count;
}
static DEVICE_ATTR(mode, S_IWUSR, NULL, set_mode);
static ssize_t run_calibration(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct usb_device *udev = hid_to_usb_dev(hdev);
unsigned long val;
int ret;
unsigned char data[94];
int actual_length;
if (strict_strtoul(buf, 0, &val))
return -EINVAL;
/* Co */
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x01, 0x00, 1, 0, data,0, 1000);
msleep(val);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x0a, 0x21, 0, 1, data,0, 1000);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x0a, 0x21, 0, 0, data,0, 1000);
/* Ii */
ret = usb_interrupt_msg(udev, usb_rcvintpipe(udev,2), data, 94, &actual_length, 1000);
/*
ret = usb_interrupt_msg(udev, usb_rcvintpipe(udev,0)
void *data, int len, int *actual_length, int timeout);
*/
/* Ci */
ret = usb_control_msg (udev, usb_rcvctrlpipe(udev,0), 0x01, 0xa1, 0x030b, 1, data,4, 1000);
/* Co */
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x0a, 0x21, 0, 0, data,0, 1000);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x03, 0x00, 1, 0, data,0, 1000);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x01, 0x00, 1, 0, data,0, 1000);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x0a, 0x21, 0, 0, data,0, 1000);
ret = usb_control_msg (udev, usb_sndctrlpipe(udev,0), 0x0a, 0x21, 0, 1, data,0, 1000);
/* Ii */
ret = usb_interrupt_msg(udev, usb_rcvintpipe(udev,2), data, 94, &actual_length, 1000);
/* Ci */
ret = usb_control_msg (udev, usb_rcvctrlpipe(udev,0), 0x01, 0xa1, 0x0311, 1, data,4, 1000);
// ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0xf, 0x40, value, index, data, 2, 1000);
// usb_control_msg(usb_handle, 0x40, 0xf, value, index, buf, bytes, 1000);
return count;
}
static DEVICE_ATTR(calibrate, S_IWUSR, NULL, run_calibration);
[-- Attachment #3: calib.c --]
[-- Type: text/x-csrc, Size: 2724 bytes --]
/*
* HID driver for N-Trig touchscreens
*
* Copyright (c) 2009-2010 Rafi Rubin
* Copyright (c) 2009-2010 Stephane Chatty
*
*/
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <usb.h>
static struct usb_device **
device_init ()
{
struct usb_bus *usb_bus;
struct usb_device *dev;
/* calloc to pre-zero */
struct usb_device ** out = (struct usb_device **)calloc(8,
sizeof(struct usb_device *));
int count = 0;
usb_init ();
usb_find_busses ();
usb_find_devices ();
for (usb_bus = usb_busses ; usb_bus ; usb_bus = usb_bus->next)
{
printf("bus %lu\n",usb_bus->location);
for (dev = usb_bus->devices ; dev ; dev = dev->next)
if (dev->descriptor.idVendor == 0x1b96 && dev->descriptor.idProduct == 0x1)
out[count++] = dev;
}
return out;
}
#define BUFSIZE 1024
int main (int argc, char ** argv)
{
struct usb_device *usb_dev;
struct usb_device ** devs;
struct usb_dev_handle *usb_handle;
int retval = 1;
char buf [BUFSIZE] = {0};
int bytes=0;
int value = 0x402;
int i;
int d;
devs = device_init ();
for(d=0; devs[d] != 0 && d<8 ; d++)
{
usb_dev = devs[d];
if (!usb_dev) {
fprintf (stderr, "device not found\n");
return 0;
}
usb_handle = usb_open (usb_dev);
if (!usb_handle) {
fprintf (stderr, "could not open device\n");
return 0;
}
//printf ("ok\n"); 402 0x0300 2
//usb_control_msg (usb_handle, 0x40, 0x0f, value, 0x100, buf, bytes, 1000);
retval = usb_control_msg (usb_handle, 0x00, 0x01, 1, 0, buf,0, 1000);
sleep(5);
retval = usb_control_msg (usb_handle, 0x21, 0x0a, 0, 1, buf,0, 1000);
retval = usb_control_msg (usb_handle, 0x21, 0x0a, 0, 0, buf,0, 1000);
retval = usb_interrupt_read (usb_handle, 2, buf,94, 1000);
retval = usb_control_msg (usb_handle, 0xa1, 0x01, 0x030b, 1, buf,4, 1000);
retval = usb_control_msg (usb_handle, 0x21, 0x0a, 0, 0, buf,0, 1000);
retval = usb_control_msg (usb_handle, 0x00, 0x03, 1, 0, buf,0, 1000);
retval = usb_control_msg (usb_handle, 0x00, 0x01, 1, 0, buf,0, 1000);
retval = usb_control_msg (usb_handle, 0x21, 0x0a, 0, 0, buf,0, 1000);
retval = usb_control_msg (usb_handle, 0x21, 0x0a, 0, 1, buf,0, 1000);
retval = usb_interrupt_read (usb_handle, 2, buf,94, 1000);
retval = usb_control_msg (usb_handle, 0xa1, 0x01, 0x0311, 1, buf,4, 1000);
printf ("done\n");
usb_close (usb_handle);
}
return 0;
}
[-- Attachment #4: holly_kernel_8 --]
[-- Type: text/plain, Size: 666 bytes --]
S Co:3:002:0 s 00 01 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0001 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 -2:2 0
S Ci:3:002:0 s a1 01 030b 0001 0004 4 <
C Ci:3:002:0 0 4 = 0b000000
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 00 03 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 00 01 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0001 0000 0
C Co:3:002:0 0 0
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 -2:2 0
S Ci:3:002:0 s a1 01 0311 0001 0004 4 <
C Ci:3:002:0 0 4 = 1121422e
[-- Attachment #5: holly_user --]
[-- Type: text/plain, Size: 814 bytes --]
S Co:3:002:0 s 00 01 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0001 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 0:2 94 = 033fbc07 0000a014 f012ce01 68010100 000c0701 00000000 00fa0096 00000b00
S Ci:3:002:0 s a1 01 030b 0001 0004 4 <
C Ci:3:002:0 0 4 = 0b000000
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 00 03 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 00 01 0001 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0000 0000 0
C Co:3:002:0 0 0
S Co:3:002:0 s 21 0a 0000 0001 0000 0
C Co:3:002:0 0 0
S Ii:3:002:2 -115:2 94 <
C Ii:3:002:2 0:2 94 = 0340bc07 00007e14 e2123401 68010100 000c0701 00000000 00fa0096 00000b00
S Ci:3:002:0 s a1 01 0311 0001 0004 4 <
C Ci:3:002:0 0 4 = 11630064
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calibrating a hid device
2010-05-24 22:54 ` Rafi Rubin
@ 2010-05-25 1:59 ` Alan Stern
2010-05-25 10:15 ` Rafi Rubin
0 siblings, 1 reply; 5+ messages in thread
From: Alan Stern @ 2010-05-25 1:59 UTC (permalink / raw)
To: Rafi Rubin; +Cc: Jiri Kosina, linux-input, linux-usb, Dmitry Torokhov
On Mon, 24 May 2010, Rafi Rubin wrote:
> Ok, pardon that excessive attachments. Attached is a snip of the kernel code,
> just the sysfs function, the user space equivalent, and logs of both (with the
> time stamps cropped out for comparison.
Since the logs are the same, up to the point where the interrupt-IN
request is cancelled, it's logical to assume that the difference was
caused by something that happened before you began the usbmon traces.
Do it again, only this time start the traces before plugging in the
device. That way we'll get a complete record. And don't worry about
cropping out the timestamps; sometimes they reveal useful information.
For example, here they would have told us if the interrupt-IN request
failed because it timed out too quickly.
> Also please put on slop code filter glasses before reading the code, I hold no
> responsibility to damaged eyes or loss of sanity. It will be cleaned up, later.
Aside from not using the predefined constants for the bRequestType
values, what stands out most is that you're using I/O buffers allocated
on the stack. That's a no-no (not all architectures are capable of
doing DMA to stack-based locations); I/O buffers should be allocated
dynamically using kmalloc.
Alan Stern
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calibrating a hid device
2010-05-25 1:59 ` Alan Stern
@ 2010-05-25 10:15 ` Rafi Rubin
0 siblings, 0 replies; 5+ messages in thread
From: Rafi Rubin @ 2010-05-25 10:15 UTC (permalink / raw)
To: Alan Stern; +Cc: Jiri Kosina, linux-input, linux-usb, Dmitry Torokhov
----- Original message -----
> On Mon, 24 May 2010, Rafi Rubin wrote:
>
> > Ok, pardon that excessive attachments. Attached is a snip of the kernel code,
> > just the sysfs function, the user space equivalent, and logs of both (with the
> > time stamps cropped out for comparison.
>
> Since the logs are the same, up to the point where the interrupt-IN
> request is cancelled, it's logical to assume that the difference was
> caused by something that happened before you began the usbmon traces.
>
> Do it again, only this time start the traces before plugging in the
> device. That way we'll get a complete record. And don't worry about
> cropping out the timestamps; sometimes they reveal useful information.
> For example, here they would have told us if the interrupt-IN request
> failed because it timed out too quickly.
>
> > Also please put on slop code filter glasses before reading the code, I hold no
> > responsibility to damaged eyes or loss of sanity. It will be cleaned up,
> > later.
>
> Aside from not using the predefined constants for the bRequestType
> values, what stands out most is that you're using I/O buffers allocated
> on the stack. That's a no-no (not all architectures are capable of
> doing DMA to stack-based locations); I/O buffers should be allocated
> dynamically using kmalloc.
>
> Alan Stern
thanks for the feedback. The events are really fast on one of my digitizer, yet seem to be not returning on another. I'm also starting to think that some of the returns that I thought were erroneous on the good device, might have a different meaning, such as perhaps "already well calibrated, nothing interesting to report".
Sorry about the raw values for request types, I've been keeping them visually similar to the usbmon traffic for my benefit, until I'm comfortable that I've got it all good enough.
As for the logs, I cropped copies for inspection with a highlighting diff tool, I will make sure to send the full versions in the future.
I need to tweak it a bit more, and then should be able to give more details about what's going right and wrong.
Rafi
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-05-25 10:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-24 20:11 calibrating a hid device Rafi Rubin
[not found] ` <4BFADD60.7020901-hkHJxBBPWjbG6jMu9gPlYQ@public.gmane.org>
2010-05-24 20:20 ` Jiri Kosina
2010-05-24 22:54 ` Rafi Rubin
2010-05-25 1:59 ` Alan Stern
2010-05-25 10:15 ` Rafi Rubin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).