From patchwork Thu Jan 8 05:31:48 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?UTF-8?Q?Nam_Ph=E1=BA=A1m_Th=C3=A0nh?= X-Patchwork-Id: 1305 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 n085SDWV003306 for ; Wed, 7 Jan 2009 21:28:13 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750962AbZAHFbu (ORCPT ); Thu, 8 Jan 2009 00:31:50 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751263AbZAHFbu (ORCPT ); Thu, 8 Jan 2009 00:31:50 -0500 Received: from po-out-1718.google.com ([72.14.252.158]:15051 "EHLO po-out-1718.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750962AbZAHFbt (ORCPT ); Thu, 8 Jan 2009 00:31:49 -0500 Received: by po-out-1718.google.com with SMTP id b23so18441862poe.3 for ; Wed, 07 Jan 2009 21:31:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:cc:mime-version:content-type; bh=4qkShk7K7+fegY0xNIXfT4yj93wlgsgJ5kUAaeCYmy4=; b=Zb3iEmigf4yDQRP6Hk/IqzdTn13qXuioYEvtgSLZr1EixSMbcZXr/bc//bsh5VSYkw oPhJJheLwMmvPPa/Idc1/tXEjihERRI7QpNBk0Pb0p+DNuRwoDVj1yn1nE3q2HZ2wo20 hQQfge51z7R6hSpAQqkKu88YZ2mhpfIgGW8ZU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:mime-version:content-type; b=m6njB66uM4Pexgy0t/UDnugNdFZdyb2q+Z9zPICxb47exIuEG7Izq4BM4NqVkJq4Dw lVU2W6OLJ8JO4cNxUagbbGKdyCiwHKTB9C6/BtQNDNnZXeIpRUmYYNgUDLvMMLHs18Me gt5VZh/j1pk/EVfvsmAAuDavrVcDN8X6x1BFw= Received: by 10.140.186.20 with SMTP id j20mr11900401rvf.236.1231392708264; Wed, 07 Jan 2009 21:31:48 -0800 (PST) Received: by 10.141.3.20 with HTTP; Wed, 7 Jan 2009 21:31:48 -0800 (PST) Message-ID: <2ac79fa40901072131m10be588axb3de61ef81bb943f@mail.gmail.com> Date: Thu, 8 Jan 2009 12:31:48 +0700 From: "=?UTF-8?Q?Nam_Ph=E1=BA=A1m_Th=C3=A0nh?=" To: "Mauro Carvalho Chehab" Subject: [PATCH] pwc: add support for webcam snapshot button Cc: video4linux-list , "Linux Media Mailing List" MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org OK, resent. Hope it's OK now. This patch adds support for Philips webcam snapshot button as an event input device, for consistency with other webcam drivers. Signed-off-by: Pham Thanh Nam diff -uNr a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h --- a/linux/drivers/media/video/pwc/pwc.h 2009-01-03 20:03:43.000000000 +0700 +++ b/linux/drivers/media/video/pwc/pwc.h 2009-01-07 02:10:58.000000000 +0700 @@ -38,6 +38,7 @@ #include #include #include +#include #include "pwc-uncompress.h" #include @@ -256,6 +257,7 @@ int pan_angle; /* in degrees * 100 */ int tilt_angle; /* absolute angle; 0,0 is home position */ int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ + struct input_dev *button_dev; /* webcam snapshot button input */ /*** Misc. data ***/ wait_queue_head_t frameq; /* When waiting for a frame to finish... */ diff -uNr a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c --- a/linux/drivers/media/video/pwc/pwc-if.c 2009-01-03 20:03:43.000000000 +0700 +++ b/linux/drivers/media/video/pwc/pwc-if.c 2009-01-08 10:38:45.000000000 +0700 @@ -53,6 +53,7 @@ - Xavier Roche: QuickCam Pro 4000 ID - Jens Knudsen: QuickCam Zoom ID - J. Debert: QuickCam for Notebooks ID + - Pham Thanh Nam: webcam snapshot button as an event input device */ #include @@ -61,6 +62,11 @@ #include #include #include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#include +#else +#include +#endif #include #include #include @@ -587,6 +593,22 @@ pdev->vframe_count); } +static void pwc_snapshot_button(struct pwc_device *pdev, int down) +{ + if (down) { + PWC_TRACE("Snapshot button pressed.\n"); + pdev->snapshot_button_status = 1; + } + else { + PWC_TRACE("Snapshot button released.\n"); + } + + if (pdev->button_dev) { + input_report_key(pdev->button_dev, BTN_0, down); + input_sync(pdev->button_dev); + } +} + static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) { int awake = 0; @@ -604,13 +626,7 @@ pdev->vframes_error++; } if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) { - pdev->snapshot_button_status = 1; - PWC_TRACE("Snapshot button pressed.\n"); - } - else { - PWC_TRACE("Snapshot button released.\n"); - } + pwc_snapshot_button(pdev, ptr[0] & 0x01); } if ((ptr[0] ^ pdev->vmirror) & 0x02) { if (ptr[0] & 0x02) @@ -634,12 +650,7 @@ else if (pdev->type == 740 || pdev->type == 720) { unsigned char *ptr = (unsigned char *)fbuf->data; if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) { - pdev->snapshot_button_status = 1; - PWC_TRACE("Snapshot button pressed.\n"); - } - else - PWC_TRACE("Snapshot button released.\n"); + pwc_snapshot_button(pdev, ptr[0] & 0x01); } pdev->vmirror = ptr[0] & 0x03; } @@ -1221,6 +1232,11 @@ { pwc_remove_sysfs_files(pdev->vdev); video_unregister_device(pdev->vdev); + if (pdev->button_dev) { + input_unregister_device(pdev->button_dev); + input_free_device(pdev->button_dev); + pdev->button_dev = NULL; + } } /* Note that all cleanup is done in the reverse order as in _open */ @@ -1488,6 +1504,7 @@ int features = 0; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; + char *phys = NULL; vendor_id = le16_to_cpu(udev->descriptor.idVendor); product_id = le16_to_cpu(udev->descriptor.idProduct); @@ -1812,6 +1829,39 @@ pwc_set_leds(pdev, 0, 0); pwc_camera_power(pdev, 0); + /* register webcam snapshot button input device */ + pdev->button_dev = input_allocate_device(); + if (!pdev->button_dev) { + PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); + return -ENOMEM; + } + + pdev->button_dev->name = "PWC snapshot button"; + phys = kmalloc(6 + strlen(pdev->udev->bus->bus_name) + strlen(pdev->udev->devpath), + GFP_KERNEL); + if (phys == NULL) { + input_free_device(pdev->button_dev); + return -ENOMEM; + } + + sprintf(phys, "usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); + pdev->button_dev->phys = phys; + usb_to_input_id(pdev->udev, &pdev->button_dev->id); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + pdev->button_dev->dev.parent = &pdev->udev->dev; +#else + pdev->button_dev->cdev.dev = &pdev->udev->dev; +#endif + pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); + pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + + rc = input_register_device(pdev->button_dev); + if (rc) { + input_free_device(pdev->button_dev); + pdev->button_dev = NULL; + return rc; + } + return 0; err_unreg: