[RFC] surface-input

5 messages, 3 authors, 2013-09-09 · open the first message on its own page

[RFC] surface-input

From: Florian Echtler <hidden>
Date: 2013-09-05 14:15:48

Hello everyone,

as mentioned earlier, I'm currently writing a multitouch input driver
for the Pixelsense (formerly Surface 2.0). It's now at a point where I'd
consider it mostly done, but a) I have very limited experience with
kernel drivers and b) there are some additional questions I have, so I'm
attaching the current state of my source code and would like to ask for
your comments.

Open question: it looks like just calling

input_mt_init_slots(poll_dev->input, MAX_CONTACTS, INPUT_MT_DIRECT);

in the initialization routine isn't enough. hid-multitouch doesn't seem
to use any other init commands, though, or did I overlook something?

Are there any other caveats of the input-mt library which I should be
aware of?

Thanks for your input, and best regards, Florian
-- 
SENT FROM MY DEC VT50 TERMINAL

Re: [RFC] surface-input

From: Benjamin Tissoires <hidden>
Date: 2013-09-06 13:25:46

Hi Florian,

On 05/09/13 16:15, Florian Echtler wrote:
Hello everyone,

as mentioned earlier, I'm currently writing a multitouch input driver
for the Pixelsense (formerly Surface 2.0). It's now at a point where I'd
consider it mostly done, but a) I have very limited experience with
kernel drivers and b) there are some additional questions I have, so I'm
attaching the current state of my source code and would like to ask for
your comments.
Thanks for sharing this with us.

I will not do a proper review right now (just coming back from some days off, so I am quickly emptying my mail box).

Some generic comments:
- please always inline the code in the message, it is *much* easier to review and comment it
- please directly use a patch format: if the code is good, Dmitry can take it directly through his tree
- add the following people for further submissions:
  * Henrik - multitouch maintainer in the kernel, and I'm sure he will be happy to see this stuff
  * Dmitry - input maintainer, the driver will go through his tree, so it's better to let him know as soon as possible of the different discussions.
- please stick to the kernel formatting guidelines (without orders: do not use C99-style ("// ..."), do not mix tabs and spaces, stick to 80 columns, etc..). The whole documentation is in Documentation/CodingStyle, and use the script scripts/checkpatch.pl to validate most of these.
- I don't think a separate ".h" will be accepted as the declarations will not be used outside of the driver. Just merge the header on top of you .c file.
Open question: it looks like just calling

input_mt_init_slots(poll_dev->input, MAX_CONTACTS, INPUT_MT_DIRECT);

in the initialization routine isn't enough. hid-multitouch doesn't seem
to use any other init commands, though, or did I overlook something?

Are there any other caveats of the input-mt library which I should be
aware of?
You need to also set up the different axes (ABS_MT_POSITION_X and others) before calling input_mt_init_slots(). See setup_events_to_report() in bcm5974.c for an example.
Thanks for your input, and best regards, Florian
Few comments inlined:
/* 
  Surface2.0/SUR40/PixelSense input driver v0.0.1
  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.
  Copyright (C) 2013 by Florian 'floe' Echtler [off-list ref]
  Derived from the USB Skeleton driver 1.1,
  Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com)
	Derived from the Apple USB BCM5974 multitouch driver,
	Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
*/
[snipped]
/*
 * this function is called when a whole contact has been processed,
 * so that it can assign it to a slot and store the data there
 */
static void report_blob(struct surface_blob *blob, struct input_dev *input)
{
	int wide, major, minor;
	int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
	if (slotnum < 0 || slotnum >= MAX_CONTACTS)
		return;
	/* FIXME: is this needed for the Pixelsense? */

I doubt. This was required in hid-multitouch because we sometimes have "blobs" without valuable information. So we drop them.
Here it looks like each blob contains information, so it should be fine without this.
	/*if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
		struct input_mt *mt = input->mt;
		struct input_mt_slot *slot = &mt->slots[slotnum];
		if (input_mt_is_active(slot) &&
				input_mt_is_used(mt, slot))
			return;
	}*/
	input_mt_slot(input, slotnum);
	input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);

looks like you never release the touch... :(
See below.
	wide = (blob->bb_size_x > blob->bb_size_y);
	major = max(blob->bb_size_x, blob->bb_size_y);
	minor = min(blob->bb_size_x, blob->bb_size_y);
	input_event(input, EV_ABS, ABS_MT_POSITION_X, blob->pos_x);
	input_event(input, EV_ABS, ABS_MT_POSITION_Y, blob->pos_y);
	input_event(input, EV_ABS, ABS_MT_TOOL_X, blob->ctr_x);
	input_event(input, EV_ABS, ABS_MT_TOOL_Y, blob->ctr_y);
	input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
	input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
	input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
}
[snipped]
/* check candidate USB interface */
static int surface_probe(struct usb_interface *interface,
				const struct usb_device_id *id)
{
	struct usb_device *usbdev = interface_to_usbdev(interface);
	struct usb_surface *surface;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	struct input_polled_dev* poll_dev;
	/* check if we really have the right interface */
	iface_desc = &interface->altsetting[0];
	if (iface_desc->desc.bInterfaceClass != 0xFF)
		return -ENODEV;
	/* allocate memory for our device state and initialize it */
	surface = kzalloc(sizeof(struct usb_surface), GFP_KERNEL);
	poll_dev = input_allocate_polled_device();
	surface->input = poll_dev;
	if (!surface || !poll_dev)
		return -ENOMEM;
	poll_dev->private = surface;
	poll_dev->poll_interval = POLL_INTERVAL;
	poll_dev->open  = surface_open;
	poll_dev->poll  = surface_poll;
	poll_dev->close = surface_close;
	poll_dev->input->name = "Samsung SUR40";
	usb_to_input_id(usbdev,&(poll_dev->input->id));
	usb_make_path(usbdev, surface->phys, sizeof(surface->phys));
	strlcat(surface->phys, "/input0", sizeof(surface->phys));
	poll_dev->input->phys = surface->phys;
	input_mt_init_slots(poll_dev->input, MAX_CONTACTS, INPUT_MT_DIRECT);

If the device always reports actual touches and discards the release information, you may need to use the flag INPUT_MT_DROP_UNUSED.
	surface->usbdev = usbdev;
	surface->interface = interface;
	/* use endpoint #4 (0x86) */
	endpoint = &iface_desc->endpoint[4].desc;
	if (endpoint->bEndpointAddress == TOUCH_ENDPOINT) {
		/* we found a bulk in endpoint */
		surface->bulk_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
		surface->bulk_in_endpointAddr = endpoint->bEndpointAddress;
		surface->bulk_in_buffer = kmalloc(2*surface->bulk_in_size, GFP_KERNEL);
		if (!surface->bulk_in_buffer) {
			pr_err("Unable to allocate input buffer.");
			surface_delete(surface);
			return -ENOMEM;
		}
	}
	if (!(surface->bulk_in_endpointAddr)) {
		pr_err("Unable to find bulk-in endpoint.");
		surface_delete(surface);
		return -ENODEV;
	}
	/* we can register the device now, as it is ready */
	usb_set_intfdata(interface, surface);
	if (input_register_polled_device(poll_dev)) {
		pr_err("Unable to register polled input device.");
		surface_delete(surface);
		return -ENODEV;
	}
	dev_info(&interface->dev,"%s now attached\n",DRIVER_DESC);
	return 0;
}
[snipped]

/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver surface_driver = {
	.name = DRIVER_SHORT,
	.probe = surface_probe,
	.disconnect = surface_disconnect,
	/*.suspend = surface_suspend,
	.resume = surface_resume,*/

if they are commented, they are not required, so just drop it :)
	.id_table = surface_table,
	/*.supports_autosuspend = 1,*/

ditto
};
module_usb_driver(surface_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");


Cheers,
Benjamin

Re: [RFC] surface-input

From: David Herrmann <hidden>
Date: 2013-09-06 13:36:13

Hi

On Thu, Sep 5, 2013 at 4:15 PM, Florian Echtler [off-list ref] wrote:
Hello everyone,

as mentioned earlier, I'm currently writing a multitouch input driver
for the Pixelsense (formerly Surface 2.0). It's now at a point where I'd
consider it mostly done, but a) I have very limited experience with
kernel drivers and b) there are some additional questions I have, so I'm
attaching the current state of my source code and would like to ask for
your comments.

Open question: it looks like just calling

input_mt_init_slots(poll_dev->input, MAX_CONTACTS, INPUT_MT_DIRECT);

in the initialization routine isn't enough. hid-multitouch doesn't seem
to use any other init commands, though, or did I overlook something?

Are there any other caveats of the input-mt library which I should be
aware of?

Thanks for your input, and best regards, Florian
Please inline the code as Benjamin noted. Otherwise, it's cumbersome
to comment on specific lines (please see "git help format-patch" and
"git help send-email").
I did review the core setup/lifetime/destruction code and it looks
good. But you need to fix several error-paths. If a core function
returns "int", you should check it for "r < 0" and then forward the
code. Don't overwrite it with EINVAL.
Furthermore, correctly free your memory. Things like this leak memory
(surface might be non-NULL):
  if (!surface || !poll_dev)
    return -ENOMEM;

I can do a more complete review for v2 if you send it inline. But
looks good overall.

Thanks
David

Re: [RFC] surface-input

From: Florian Echtler <hidden>
Date: 2013-09-09 08:25:53

On 06.09.2013 15:25, Benjamin Tissoires wrote:
Some generic comments:
- please always inline the code in the message, it is *much* easier to review and comment it
- please directly use a patch format: if the code is good, Dmitry can take it directly through his tree
- add the following people for further submissions:
  * Henrik - multitouch maintainer in the kernel, and I'm sure he will be happy to see this stuff
  * Dmitry - input maintainer, the driver will go through his tree, so it's better to let him know as soon as possible of the different discussions.
- please stick to the kernel formatting guidelines (without orders: do not use C99-style ("// ..."), do not mix tabs and spaces, stick to 80 columns, etc..). The whole documentation is in Documentation/CodingStyle, and use the script scripts/checkpatch.pl to validate most of these.
- I don't think a separate ".h" will be accepted as the declarations will not be used outside of the driver. Just merge the header on top of you .c file.
Benjamin and David, thanks for your feedback. I will integrate this and
get back to you with a proper patch ASAP.

I have one additional question which is more about "future-proofing"
this driver. The SUR40 hardware does also provide a raw video image from
the touch sensor over another USB _endpoint_. Since it's not a different
_interface_, this can only be handled in the same driver as far as I can
tell. At some point in the future, I would like to add a V4L2 interface
to also support the video endpoint - are there any issues I should
already try to watch out for in the input part?

Thanks again, and best regards, Florian
-- 
SENT FROM MY DEC VT50 TERMINAL

Re: [RFC] surface-input

From: David Herrmann <hidden>
Date: 2013-09-09 09:35:44

Hi

On Mon, Sep 9, 2013 at 10:25 AM, Florian Echtler [off-list ref] wrote:
On 06.09.2013 15:25, Benjamin Tissoires wrote:
quoted
Some generic comments:
- please always inline the code in the message, it is *much* easier to review and comment it
- please directly use a patch format: if the code is good, Dmitry can take it directly through his tree
- add the following people for further submissions:
  * Henrik - multitouch maintainer in the kernel, and I'm sure he will be happy to see this stuff
  * Dmitry - input maintainer, the driver will go through his tree, so it's better to let him know as soon as possible of the different discussions.
- please stick to the kernel formatting guidelines (without orders: do not use C99-style ("// ..."), do not mix tabs and spaces, stick to 80 columns, etc..). The whole documentation is in Documentation/CodingStyle, and use the script scripts/checkpatch.pl to validate most of these.
- I don't think a separate ".h" will be accepted as the declarations will not be used outside of the driver. Just merge the header on top of you .c file.
Benjamin and David, thanks for your feedback. I will integrate this and
get back to you with a proper patch ASAP.

I have one additional question which is more about "future-proofing"
this driver. The SUR40 hardware does also provide a raw video image from
the touch sensor over another USB _endpoint_. Since it's not a different
_interface_, this can only be handled in the same driver as far as I can
tell. At some point in the future, I would like to add a V4L2 interface
to also support the video endpoint - are there any issues I should
already try to watch out for in the input part?
Media drivers use input-devices to report input data. So no, there is
no reason to change your driver's design. Once you want
media-functionality, you simply add a v4l2 device during hid_probe()
and remove it in hid_remove(). User-space can see the relation between
both via sysfs.
It is never wrong to think about the API _now_. But as long as it's
only a single input-dev and one v4l2-dev, I'd recommend to put both
below your usb-device and you're fine.
Regarding internal driver-design, you should not bother now. Make it
work for input and make it work well.

Cheers
David
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help