From patchwork Sun Nov 15 08:47:11 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?TsODwqltZXRoIE3Dg8KhcnRvbg==?= X-Patchwork-Id: 60084 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nAF8vFOO002627 for ; Sun, 15 Nov 2009 08:57:16 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752319AbZKOI5G (ORCPT ); Sun, 15 Nov 2009 03:57:06 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752323AbZKOI5G (ORCPT ); Sun, 15 Nov 2009 03:57:06 -0500 Received: from mail02d.mail.t-online.hu ([84.2.42.7]:60004 "EHLO mail02d.mail.t-online.hu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752319AbZKOI5F (ORCPT ); Sun, 15 Nov 2009 03:57:05 -0500 X-Greylist: delayed 592 seconds by postgrey-1.27 at vger.kernel.org; Sun, 15 Nov 2009 03:57:05 EST Received: from [192.168.1.64] (dsl5402C471.pool.t-online.hu [84.2.196.113]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail02d.mail.t-online.hu (Postfix) with ESMTPSA id D279F758A00; Sun, 15 Nov 2009 09:46:48 +0100 (CET) Message-ID: <4AFFC00F.6060704@freemail.hu> Date: Sun, 15 Nov 2009 09:47:11 +0100 From: =?ISO-8859-2?Q?N=E9meth_M=E1rton?= User-Agent: Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.8.1.21) Gecko/20090402 SeaMonkey/1.1.16 MIME-Version: 1.0 To: Jean-Francois Moine , V4L Mailing List , linux-input@vger.kernel.org Subject: [RFC, PATCH] gspca pac7302: add support for camera button X-DCC-mail.t-online.hu-Metrics: mail02d.mail.t-online.hu 32721; Body=3 Fuz1=3 Fuz2=3 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff -r 09c1284de47d linux/drivers/media/video/gspca/gspca.h --- a/linux/drivers/media/video/gspca/gspca.h Sat Nov 14 08:58:12 2009 +0100 +++ b/linux/drivers/media/video/gspca/gspca.h Sun Nov 15 10:40:54 2009 +0100 @@ -138,6 +138,7 @@ struct module *module; /* subdriver handling the device */ struct usb_device *dev; struct file *capt_file; /* file doing video capture */ + struct input_dev *input_dev; struct cam cam; /* device information */ const struct sd_desc *sd_desc; /* subdriver description */ @@ -147,6 +148,7 @@ #define USB_BUF_SZ 64 __u8 *usb_buf; /* buffer for USB exchanges */ struct urb *urb[MAX_NURBS]; + struct urb *int_urb; __u8 *frbuf; /* buffer for nframes */ struct gspca_frame frame[GSPCA_MAX_FRAMES]; diff -r 09c1284de47d linux/drivers/media/video/gspca/pac7302.c --- a/linux/drivers/media/video/gspca/pac7302.c Sat Nov 14 08:58:12 2009 +0100 +++ b/linux/drivers/media/video/gspca/pac7302.c Sun Nov 15 10:40:54 2009 +0100 @@ -68,6 +68,7 @@ #define MODULE_NAME "pac7302" +#include #include #include "gspca.h" @@ -1220,6 +1221,50 @@ } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void int_irq(struct urb *urb, struct pt_regs *regs) +#else +static void int_irq(struct urb *urb) +#endif +{ + struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; + int ret; + int i; + __u8 data0, data1; + + printk(KERN_DEBUG "int_irq()\n"); + printk(KERN_DEBUG "urb->status: %i\n", urb->status); + if (urb->status == 0) { + printk(KERN_DEBUG "urb->actual_length: %u\n", urb->actual_length); + for (i = 0; i < urb->actual_length; i++) { + printk(KERN_DEBUG "urb->transfer_buffer[%i]=0x%x\n", + i, ((__u8*)urb->transfer_buffer)[i]); + } + if (urb->actual_length == 2) { + data0 = ((__u8*)urb->transfer_buffer)[0]; + data1 = ((__u8*)urb->transfer_buffer)[1]; + if ((data0 == 0x00 && data1 == 0x11) || + (data0 == 0x22 && data1 == 0x33) || + (data0 == 0x44 && data1 == 0x55) || + (data0 == 0x66 && data1 == 0x77) || + (data0 == 0x88 && data1 == 0x99) || + (data0 == 0xaa && data1 == 0xbb) || + (data0 == 0xcc && data1 == 0xdd) || + (data0 == 0xee && data1 == 0xff)) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); + input_sync(gspca_dev->input_dev); + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + } else + printk(KERN_DEBUG "Unknown packet received\n"); + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + printk(KERN_DEBUG "resubmit urb: %i\n", ret); + } + +} + + /* sub-driver description for pac7302 */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1254,19 +1299,132 @@ }; MODULE_DEVICE_TABLE(usb, device_table); +static int init_camera_input(struct gspca_dev *gspca_dev, const struct usb_device_id *id) +{ + struct input_dev *input_dev; + int err; + + printk(KERN_DEBUG "allocating input device\n"); + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + //input_dev->name = "Camera capture button"; + //input_dev->phys = "camera"; + input_dev->id.bustype = BUS_USB; + input_dev->id.vendor = id->idVendor; + input_dev->id.product = id->idProduct; + input_dev->id.version = id->bcdDevice_hi; + //input_dev->id.version = id->bcdDevice_lo; + + input_dev->evbit[0] = BIT_MASK(EV_KEY); + input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); + //input_dev->dev.parent = ; + + printk(KERN_DEBUG "registering input device\n"); + err = input_register_device(input_dev); + if (err) { + input_dev->dev.parent = NULL; + input_free_device(input_dev); + } else { + gspca_dev->input_dev = input_dev; + } + + return err; +} + /* -- device connect -- */ static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + int ret; + struct usb_host_interface *intf_desc; + struct usb_endpoint_descriptor *ep; + int i; + + struct urb *urb; + void* buffer = NULL; + unsigned int buffer_len; + int interval; + struct gspca_dev *gspca_dev; + struct usb_device *dev; + + ret = gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), THIS_MODULE); + if (0 <= ret) { + intf_desc = intf->cur_altsetting; + for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { + ep = &intf_desc->endpoint[i].desc; + if ((ep->bEndpointAddress & USB_DIR_IN) && + ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT)) { + + buffer_len = ep->wMaxPacketSize; + interval = ep->bInterval; + printk(KERN_DEBUG "found int in endpoint: 0x%x\n", ep->bEndpointAddress); + printk(KERN_DEBUG " - buffer_len = %u\n", buffer_len); + printk(KERN_DEBUG " - interval = %u\n", interval); + + gspca_dev = usb_get_intfdata(intf); + dev = gspca_dev->dev; + gspca_dev->int_urb = NULL; + gspca_dev->input_dev = NULL; + + buffer = kmalloc(ep->wMaxPacketSize, GFP_KERNEL); + if (buffer) + urb = usb_alloc_urb(0, GFP_KERNEL); + else { + kfree(buffer); + urb = NULL; + } + if (buffer && urb) { + usb_fill_int_urb(urb, dev, + usb_rcvintpipe(dev, ep->bEndpointAddress), + buffer, buffer_len, + int_irq, (void*)gspca_dev, interval); + ret = init_camera_input(gspca_dev, id); + if (0 <= ret) { + gspca_dev->int_urb = urb; + ret = usb_submit_urb(urb, GFP_KERNEL); + printk(KERN_DEBUG "usb_submit_urb() returns %i\n", ret); + } + } + } + + } + } + return ret; +} + +static void sd_disconnect(struct usb_interface *intf) +{ + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + struct urb *urb; + struct input_dev *input_dev; + + urb = gspca_dev->int_urb; + if (urb != NULL) { + gspca_dev->int_urb = NULL; + usb_kill_urb(urb); + usb_buffer_free(gspca_dev->dev, + urb->transfer_buffer_length, + urb->transfer_buffer, + urb->transfer_dma); + usb_free_urb(urb); + } + input_dev = gspca_dev->input_dev; + if (input_dev) { + gspca_dev->input_dev = NULL; + input_unregister_device(input_dev); + } + gspca_disconnect(intf); } static struct usb_driver sd_driver = { .name = MODULE_NAME, .id_table = device_table, .probe = sd_probe, - .disconnect = gspca_disconnect, + .disconnect = sd_disconnect, #ifdef CONFIG_PM .suspend = gspca_suspend, .resume = gspca_resume,