mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Oliver Neukum <oliver@neukum.org>
To: Ondrej Zary <linux@rainbow-software.org>
Cc: linux-usb@vger.kernel.org, daniel.ritz@gmx.ch,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] [RFC] NEXIO (or iNexio) support for usbtouchscreen
Date: Wed, 18 Nov 2009 16:25:46 +0100	[thread overview]
Message-ID: <200911181625.46983.oliver@neukum.org> (raw)
In-Reply-To: <200911181318.45208.linux@rainbow-software.org>

Am Mittwoch, 18. November 2009 13:18:43 schrieb Ondrej Zary:

> > > +	/* send init command */
> > > +	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), init,
> > > +			   sizeof(init), &actual_len, NEXIO_TIMEOUT);
> >
> > DMA on the kernel stack
> 
> I don't know any details about this - what's the correct way to do this?

You must kmalloc the buffer.

> I tried moving the init[] array outside the function but that didn't work
>  at all - compiled fine but device was not reporting the name firmware
>  version. I ended up with copying it to that kmalloced buf.

That's correct.

> 
> I'm worried about nexio_ack - that shouldn't work too then. Maybe it really
> does not and the device does not care.

It works on some architectures. But it is still buggy.

> I also found another problem: when I disconnect the USB cable, kernel
>  oopses: BUG: unable to handle kernel NULL pointer dereference
> IP: [<f7c794fa>] start_unlink_async+0x63/0xfc
> 
> Call Trace:
> ehci_urb_dequeue+0x7c/0x11a [ehci_hcd]
> unlink1+0xaa/0xc7 [usbcore]
> usb_hcd_unlink_urb+0x57/0x84 [usbcore]
> usb_kill_urb+0x40/0xbe [usbcore]
> default_wake_function+0x0/0x2b
> usb_start_wait_urb+0x6e/0xb0 [usbcore]
> usb_control_msg+0x10a/0x136 [usbcore]
> hub_port_status+0x77/0xf7 [usbcore]
> hub_thread+0x56d/0xe14 [usbcore]
> autoremove_wake_function+0x0/0x4f
> hub_thread+0x0/0xe14 [usbcore]
> kthread+0x7a/0x7f
> kthread+0x0/0x7f
> 
> Are there any other problems with my code that can cause this oops?

Odd.

> +	/* read firmware version */
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	buf[buf[1]] = 0;	/* second byte is data(string) length */

You'd better check buf[1] for sanity.

> +	firmware_ver = kstrdup(&buf[2], GFP_KERNEL);

Are you sure this is safe?

> +	/* read device name */
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0) {
> +		kfree(firmware_ver);
> +		goto err_out;
> +	}
> +	buf[buf[1]] = 0;
> +	printk(KERN_INFO "Nexio device: %s, firmware version %s\n",
> +	       &buf[2], firmware_ver);
> +	kfree(firmware_ver);
> +
> +	/* prepare ACK URB */
> +	usbtouch->ack = usb_alloc_urb(0, GFP_KERNEL);
> +	if (!usbtouch->ack) {
> +		dbg("%s - usb_alloc_urb failed: ack_urb", __func__);
> +		return 0;

Are you sure this shouldn't error out?

> +	}
> +	usb_fill_bulk_urb(usbtouch->ack, usbtouch->udev,
> +			  usb_sndbulkpipe(usbtouch->udev, NEXIO_OUTPUT_EP),
> +			  nexio_ack_pkt, sizeof(nexio_ack_pkt), NULL,

DMA on the heap.

> +			  usbtouch);
> +	/* submit first IRQ URB */
> +	ret = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
> +err_out:
> +	kfree(buf);
> +err_nobuf:
> +	return ret;
> +}
> +
> +static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char
>  *pkt) +{
> +	int x, y, begin_x, begin_y, end_x, end_y, w, h, ret;
> +	struct nexio_touch_packet *packet = (void *) pkt;
> +
> +	/* got touch data? */
> +	if ((pkt[0] & 0xe0) != 0xe0)
> +		return 0;
> +
> +	/* send ACK */
> +	ret = usb_submit_urb(usbtouch->ack, GFP_KERNEL);

In interrupt context. You must use GFP_ATOMIC.

> +
> +	if (!usbtouch->type->max_xc) {
> +		usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len);
> +		input_set_abs_params(usbtouch->input, ABS_X, 0,
> +				     2 * be16_to_cpu(packet->x_len), 0, 0);
> +		usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len);
> +		input_set_abs_params(usbtouch->input, ABS_Y, 0,
> +				     2 * be16_to_cpu(packet->y_len), 0, 0);
> +	}
> +	/* The device reports state of IR sensors on X and Y axes.
> +	 * Each byte represents "darkness" percentage (0-100) of one element.
> +	 * 17" touchscreen reports only 64 x 52 bytes so the resolution is low.
> +	 * This also means that there's a limited multi-touch capability but
> +	 * it's disabled (and untested) here as there's no X driver for that.
> +	 */
> +	begin_x = end_x = begin_y = end_y = -1;
> +	for (x = 0; x < be16_to_cpu(packet->x_len); x++) {
> +		if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) {
> +			begin_x = x;
> +			continue;
> +		}
> +		if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) {
> +			end_x = x - 1;
> +			for (y = be16_to_cpu(packet->x_len);
> +			     y < be16_to_cpu(packet->data_len); y++) {
> +				if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) {
> +					begin_y = y - be16_to_cpu(packet->x_len);
> +					continue;
> +				}
> +				if (end_y == -1 &&
> +				    begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) {
> +					end_y = y - 1 - be16_to_cpu(packet->x_len);
> +					w = end_x - begin_x;
> +					h = end_y - begin_y;
> +					/* multi-touch */
> +/*					input_report_abs(usbtouch->input,
> +						    ABS_MT_TOUCH_MAJOR, max(w,h));
> +					input_report_abs(usbtouch->input,
> +						    ABS_MT_TOUCH_MINOR, min(x,h));
> +					input_report_abs(usbtouch->input,
> +						    ABS_MT_POSITION_X, 2*begin_x+w);
> +					input_report_abs(usbtouch->input,
> +						    ABS_MT_POSITION_Y, 2*begin_y+h);
> +					input_report_abs(usbtouch->input,
> +						    ABS_MT_ORIENTATION, w > h);
> +					input_mt_sync(usbtouch->input);*/
> +					/* single touch */
> +					usbtouch->x = 2 * begin_x + w;
> +					usbtouch->y = 2 * begin_y + h;
> +					usbtouch->touch = packet->flags & 0x01;
> +					begin_y = end_y = -1;
> +					return 1;
> +				}
> +			}
> +			begin_x = end_x = -1;
> +		}
> +
> +	}
> +	return 0;
> +}
> +#endif
> +

> @@ -1007,8 +1198,10 @@ static void usbtouch_disconnect(struct u
>  	dbg("%s - usbtouch is initialized, cleaning up", __func__);
>  	usb_set_intfdata(intf, NULL);
>  	usb_kill_urb(usbtouch->irq);
> +	usb_kill_urb(usbtouch->ack);

Have you checked the order is correct?

>  	input_unregister_device(usbtouch->input);
>  	usb_free_urb(usbtouch->irq);
> +	usb_free_urb(usbtouch->ack);
>  	usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
>  	kfree(usbtouch);
>  }
> 

	Regards
		Oliver


  reply	other threads:[~2009-11-18 15:25 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-16 14:14 [PATCH] " Ondrej Zary
2009-11-17 15:25 ` Oliver Neukum
2009-11-18 12:18   ` [PATCH v2] [RFC] " Ondrej Zary
2009-11-18 15:25     ` Oliver Neukum [this message]
2009-11-19 12:40       ` [PATCH v3] " Ondrej Zary
2009-11-19 16:56         ` Oliver Neukum
2009-11-20  9:21           ` [PATCH v4] " Ondrej Zary
2009-11-20 18:43             ` Oliver Neukum
2009-11-20 22:41               ` Ondrej Zary
2009-11-21  9:17                 ` Oliver Neukum
2009-11-23 10:04                   ` [PATCH 1/3] usbtouchscreen: convert from usb_device to usb_interface Ondrej Zary
2009-11-23 10:04                   ` [PATCH 2/3] usbtouchscreen: find input endpoint automatically Ondrej Zary
2009-11-23 10:05                   ` [PATCH 3/3] usbtouchscreen: add NEXIO (or iNexio) support Ondrej Zary

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200911181625.46983.oliver@neukum.org \
    --to=oliver@neukum.org \
    --cc=daniel.ritz@gmx.ch \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux@rainbow-software.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®