diff options
author | Nam Phạm Thành <phamthanhnam.ptn@gmail.com> | 2009-01-12 00:50:17 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:22 -0400 |
commit | e32a7eccd7f016928dd864711ac654e6db62c5f3 (patch) | |
tree | 6eb71d883c91226c2f8dd0c7a6cc6a1c2c8e3c5f /drivers/media/video | |
parent | be4f4aecf8df39444535c9d9be2b74a8f34649b2 (diff) |
V4L/DVB (10242): pwc: add support for webcam snapshot button
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>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/pwc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 77 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 6 |
3 files changed, 80 insertions, 13 deletions
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 7298cf2e1650..8b9f0aa844a1 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig | |||
@@ -35,3 +35,13 @@ config USB_PWC_DEBUG | |||
35 | Say Y here in order to have the pwc driver generate verbose debugging | 35 | Say Y here in order to have the pwc driver generate verbose debugging |
36 | messages. | 36 | messages. |
37 | A special module options 'trace' is used to control the verbosity. | 37 | A special module options 'trace' is used to control the verbosity. |
38 | |||
39 | config USB_PWC_INPUT_EVDEV | ||
40 | bool "USB Philips Cameras input events device support" | ||
41 | default y | ||
42 | depends on USB_PWC && INPUT | ||
43 | ---help--- | ||
44 | This option makes USB Philips cameras register the snapshot button as | ||
45 | an input device to report button events. | ||
46 | |||
47 | If you are in doubt, say Y. | ||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 0d810189dd87..a7c2e7284c20 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -53,6 +53,7 @@ | |||
53 | - Xavier Roche: QuickCam Pro 4000 ID | 53 | - Xavier Roche: QuickCam Pro 4000 ID |
54 | - Jens Knudsen: QuickCam Zoom ID | 54 | - Jens Knudsen: QuickCam Zoom ID |
55 | - J. Debert: QuickCam for Notebooks ID | 55 | - J. Debert: QuickCam for Notebooks ID |
56 | - Pham Thanh Nam: webcam snapshot button as an event input device | ||
56 | */ | 57 | */ |
57 | 58 | ||
58 | #include <linux/errno.h> | 59 | #include <linux/errno.h> |
@@ -61,6 +62,9 @@ | |||
61 | #include <linux/module.h> | 62 | #include <linux/module.h> |
62 | #include <linux/poll.h> | 63 | #include <linux/poll.h> |
63 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
65 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
66 | #include <linux/usb/input.h> | ||
67 | #endif | ||
64 | #include <linux/vmalloc.h> | 68 | #include <linux/vmalloc.h> |
65 | #include <asm/io.h> | 69 | #include <asm/io.h> |
66 | 70 | ||
@@ -586,6 +590,23 @@ static void pwc_frame_dumped(struct pwc_device *pdev) | |||
586 | pdev->vframe_count); | 590 | pdev->vframe_count); |
587 | } | 591 | } |
588 | 592 | ||
593 | static void pwc_snapshot_button(struct pwc_device *pdev, int down) | ||
594 | { | ||
595 | if (down) { | ||
596 | PWC_TRACE("Snapshot button pressed.\n"); | ||
597 | pdev->snapshot_button_status = 1; | ||
598 | } else { | ||
599 | PWC_TRACE("Snapshot button released.\n"); | ||
600 | } | ||
601 | |||
602 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
603 | if (pdev->button_dev) { | ||
604 | input_report_key(pdev->button_dev, BTN_0, down); | ||
605 | input_sync(pdev->button_dev); | ||
606 | } | ||
607 | #endif | ||
608 | } | ||
609 | |||
589 | static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) | 610 | static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) |
590 | { | 611 | { |
591 | int awake = 0; | 612 | int awake = 0; |
@@ -603,13 +624,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_ | |||
603 | pdev->vframes_error++; | 624 | pdev->vframes_error++; |
604 | } | 625 | } |
605 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { | 626 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { |
606 | if (ptr[0] & 0x01) { | 627 | pwc_snapshot_button(pdev, ptr[0] & 0x01); |
607 | pdev->snapshot_button_status = 1; | ||
608 | PWC_TRACE("Snapshot button pressed.\n"); | ||
609 | } | ||
610 | else { | ||
611 | PWC_TRACE("Snapshot button released.\n"); | ||
612 | } | ||
613 | } | 628 | } |
614 | if ((ptr[0] ^ pdev->vmirror) & 0x02) { | 629 | if ((ptr[0] ^ pdev->vmirror) & 0x02) { |
615 | if (ptr[0] & 0x02) | 630 | if (ptr[0] & 0x02) |
@@ -633,12 +648,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_ | |||
633 | else if (pdev->type == 740 || pdev->type == 720) { | 648 | else if (pdev->type == 740 || pdev->type == 720) { |
634 | unsigned char *ptr = (unsigned char *)fbuf->data; | 649 | unsigned char *ptr = (unsigned char *)fbuf->data; |
635 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { | 650 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { |
636 | if (ptr[0] & 0x01) { | 651 | pwc_snapshot_button(pdev, ptr[0] & 0x01); |
637 | pdev->snapshot_button_status = 1; | ||
638 | PWC_TRACE("Snapshot button pressed.\n"); | ||
639 | } | ||
640 | else | ||
641 | PWC_TRACE("Snapshot button released.\n"); | ||
642 | } | 652 | } |
643 | pdev->vmirror = ptr[0] & 0x03; | 653 | pdev->vmirror = ptr[0] & 0x03; |
644 | } | 654 | } |
@@ -1216,6 +1226,15 @@ static void pwc_cleanup(struct pwc_device *pdev) | |||
1216 | { | 1226 | { |
1217 | pwc_remove_sysfs_files(pdev->vdev); | 1227 | pwc_remove_sysfs_files(pdev->vdev); |
1218 | video_unregister_device(pdev->vdev); | 1228 | video_unregister_device(pdev->vdev); |
1229 | |||
1230 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
1231 | if (pdev->button_dev) { | ||
1232 | input_unregister_device(pdev->button_dev); | ||
1233 | input_free_device(pdev->button_dev); | ||
1234 | kfree(pdev->button_dev->phys); | ||
1235 | pdev->button_dev = NULL; | ||
1236 | } | ||
1237 | #endif | ||
1219 | } | 1238 | } |
1220 | 1239 | ||
1221 | /* Note that all cleanup is done in the reverse order as in _open */ | 1240 | /* Note that all cleanup is done in the reverse order as in _open */ |
@@ -1483,6 +1502,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1483 | int features = 0; | 1502 | int features = 0; |
1484 | int video_nr = -1; /* default: use next available device */ | 1503 | int video_nr = -1; /* default: use next available device */ |
1485 | char serial_number[30], *name; | 1504 | char serial_number[30], *name; |
1505 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
1506 | char *phys = NULL; | ||
1507 | #endif | ||
1486 | 1508 | ||
1487 | vendor_id = le16_to_cpu(udev->descriptor.idVendor); | 1509 | vendor_id = le16_to_cpu(udev->descriptor.idVendor); |
1488 | product_id = le16_to_cpu(udev->descriptor.idProduct); | 1510 | product_id = le16_to_cpu(udev->descriptor.idProduct); |
@@ -1807,6 +1829,35 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1807 | pwc_set_leds(pdev, 0, 0); | 1829 | pwc_set_leds(pdev, 0, 0); |
1808 | pwc_camera_power(pdev, 0); | 1830 | pwc_camera_power(pdev, 0); |
1809 | 1831 | ||
1832 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
1833 | /* register webcam snapshot button input device */ | ||
1834 | pdev->button_dev = input_allocate_device(); | ||
1835 | if (!pdev->button_dev) { | ||
1836 | PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); | ||
1837 | return -ENOMEM; | ||
1838 | } | ||
1839 | |||
1840 | pdev->button_dev->name = "PWC snapshot button"; | ||
1841 | phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); | ||
1842 | if (!phys) { | ||
1843 | input_free_device(pdev->button_dev); | ||
1844 | return -ENOMEM; | ||
1845 | } | ||
1846 | pdev->button_dev->phys = phys; | ||
1847 | usb_to_input_id(pdev->udev, &pdev->button_dev->id); | ||
1848 | pdev->button_dev->dev.parent = &pdev->udev->dev; | ||
1849 | pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
1850 | pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); | ||
1851 | |||
1852 | rc = input_register_device(pdev->button_dev); | ||
1853 | if (rc) { | ||
1854 | input_free_device(pdev->button_dev); | ||
1855 | kfree(pdev->button_dev->phys); | ||
1856 | pdev->button_dev = NULL; | ||
1857 | return rc; | ||
1858 | } | ||
1859 | #endif | ||
1860 | |||
1810 | return 0; | 1861 | return 0; |
1811 | 1862 | ||
1812 | err_unreg: | 1863 | err_unreg: |
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 01411fb2337a..0be6f814f539 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -37,6 +37,9 @@ | |||
37 | #include <linux/videodev.h> | 37 | #include <linux/videodev.h> |
38 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
39 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
40 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
41 | #include <linux/input.h> | ||
42 | #endif | ||
40 | 43 | ||
41 | #include "pwc-uncompress.h" | 44 | #include "pwc-uncompress.h" |
42 | #include <media/pwc-ioctl.h> | 45 | #include <media/pwc-ioctl.h> |
@@ -255,6 +258,9 @@ struct pwc_device | |||
255 | int pan_angle; /* in degrees * 100 */ | 258 | int pan_angle; /* in degrees * 100 */ |
256 | int tilt_angle; /* absolute angle; 0,0 is home position */ | 259 | int tilt_angle; /* absolute angle; 0,0 is home position */ |
257 | int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ | 260 | int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ |
261 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | ||
262 | struct input_dev *button_dev; /* webcam snapshot button input */ | ||
263 | #endif | ||
258 | 264 | ||
259 | /*** Misc. data ***/ | 265 | /*** Misc. data ***/ |
260 | wait_queue_head_t frameq; /* When waiting for a frame to finish... */ | 266 | wait_queue_head_t frameq; /* When waiting for a frame to finish... */ |