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
next prev parent 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®