Skip to content

Commit

Permalink
V4L/DVB (10242): pwc: add support for webcam snapshot button
Browse files Browse the repository at this point in the history
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 <phamthanhnam.ptn@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Nam Phạm Thành authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent be4f4ae commit e32a7ec
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 13 deletions.
10 changes: 10 additions & 0 deletions drivers/media/video/pwc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ config USB_PWC_DEBUG
Say Y here in order to have the pwc driver generate verbose debugging
messages.
A special module options 'trace' is used to control the verbosity.

config USB_PWC_INPUT_EVDEV
bool "USB Philips Cameras input events device support"
default y
depends on USB_PWC && INPUT
---help---
This option makes USB Philips cameras register the snapshot button as
an input device to report button events.

If you are in doubt, say Y.
77 changes: 64 additions & 13 deletions drivers/media/video/pwc/pwc-if.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <linux/errno.h>
Expand All @@ -61,6 +62,9 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/usb/input.h>
#endif
#include <linux/vmalloc.h>
#include <asm/io.h>

Expand Down Expand Up @@ -586,6 +590,23 @@ static void pwc_frame_dumped(struct pwc_device *pdev)
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");
}

#ifdef CONFIG_USB_PWC_INPUT_EVDEV
if (pdev->button_dev) {
input_report_key(pdev->button_dev, BTN_0, down);
input_sync(pdev->button_dev);
}
#endif
}

static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
{
int awake = 0;
Expand All @@ -603,13 +624,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
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)
Expand All @@ -633,12 +648,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_
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;
}
Expand Down Expand Up @@ -1216,6 +1226,15 @@ static void pwc_cleanup(struct pwc_device *pdev)
{
pwc_remove_sysfs_files(pdev->vdev);
video_unregister_device(pdev->vdev);

#ifdef CONFIG_USB_PWC_INPUT_EVDEV
if (pdev->button_dev) {
input_unregister_device(pdev->button_dev);
input_free_device(pdev->button_dev);
kfree(pdev->button_dev->phys);
pdev->button_dev = NULL;
}
#endif
}

/* Note that all cleanup is done in the reverse order as in _open */
Expand Down Expand Up @@ -1483,6 +1502,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
int features = 0;
int video_nr = -1; /* default: use next available device */
char serial_number[30], *name;
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
char *phys = NULL;
#endif

vendor_id = le16_to_cpu(udev->descriptor.idVendor);
product_id = le16_to_cpu(udev->descriptor.idProduct);
Expand Down Expand Up @@ -1807,6 +1829,35 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pwc_set_leds(pdev, 0, 0);
pwc_camera_power(pdev, 0);

#ifdef CONFIG_USB_PWC_INPUT_EVDEV
/* 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 = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath);
if (!phys) {
input_free_device(pdev->button_dev);
return -ENOMEM;
}
pdev->button_dev->phys = phys;
usb_to_input_id(pdev->udev, &pdev->button_dev->id);
pdev->button_dev->dev.parent = &pdev->udev->dev;
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);
kfree(pdev->button_dev->phys);
pdev->button_dev = NULL;
return rc;
}
#endif

return 0;

err_unreg:
Expand Down
6 changes: 6 additions & 0 deletions drivers/media/video/pwc/pwc.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/input.h>
#endif

#include "pwc-uncompress.h"
#include <media/pwc-ioctl.h>
Expand Down Expand Up @@ -255,6 +258,9 @@ struct pwc_device
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 */
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
struct input_dev *button_dev; /* webcam snapshot button input */
#endif

/*** Misc. data ***/
wait_queue_head_t frameq; /* When waiting for a frame to finish... */
Expand Down

0 comments on commit e32a7ec

Please sign in to comment.