From: Bastien Nocera <hadess@xxxxxxxxxx> Register an input device with one button, and for the supported OV511 webcams, poll and check whether the snapshot button has been pressed on each new frame. [dtor@xxxxxxx: fix freeing of phys, plug into Kconfig, make compile] Signed-off-by: Bastien Nocera <hadess@xxxxxxxxxx> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx> --- Mauro, This is something that's been sitting in my queue for quite some time, please consider applying. Thanks! drivers/media/video/Kconfig | 8 +++ drivers/media/video/ov511.c | 109 +++++++++++++++++++++++++++++++++++++++---- drivers/media/video/ov511.h | 8 +++ 3 files changed, 116 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index dcf9fa9..42573e0 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -888,6 +888,14 @@ config USB_OV511 To compile this driver as a module, choose M here: the module will be called ov511. +config USB_OV511_SNAPSHOT_BUTTON + bool "USB OV511 Snapshot Button support" + depends on USB_OV511 + depends on INPUT + ---help--- + Say Y here if you want the driver to report snapshot button through + input layer. + config USB_SE401 tristate "USB SE401 Camera support" depends on VIDEO_V4L1 diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 0bc2cf5..484165c 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -44,6 +44,8 @@ #include <asm/processor.h> #include <linux/mm.h> #include <linux/device.h> +#include <linux/input.h> +#include <linux/usb/input.h> #if defined (__i386__) #include <asm/cpufeature.h> @@ -92,7 +94,7 @@ static int cams = 1; static int compress; static int testpat; static int dumppix; -static int led = 1; +static int led = 1; static int dump_bridge; static int dump_sensor; static int printph; @@ -352,6 +354,83 @@ rvfree(void *mem, unsigned long size) /********************************************************************** * + * Input device + * + **********************************************************************/ +#ifdef CONFIG_USB_OV511_SNAPSHOT_BUTTON + +static int ov511_input_init(struct usb_ov511 *ov) +{ + struct usb_device *udev = ov->dev; + struct input_dev *input; + int err = -ENOMEM; + + input = input_allocate_device(); + if (!input) + goto err_out; + + usb_make_path(udev, ov->key_phys, OV511_KEY_PHYS_SIZE); + strlcat(ov->key_phys, "/input0", OV511_KEY_PHYS_SIZE); + + input->name = "OV511 Snapshot Button"; + input->phys = ov->key_phys; + usb_to_input_id(udev, &input->id); + input->dev.parent = &udev->dev; + + __set_bit(EV_KEY, input->evbit); + __set_bit(KEY_CAMERA, input->keybit); + + err = input_register_device(input); + if (err) + goto err_out; + + ov->key_input = input; + return 0; + +err_out: + input_free_device(input); + return err; +} + +static void ov511_input_cleanup(struct usb_ov511 *ov) +{ + if (ov->key_input) { + input_unregister_device(ov->key_input); + ov->key_input = NULL; + } +} + +static void ov511_input_report_key(struct usb_ov511 *ov) +{ + struct input_dev *input = ov->key_input; + + if (input) { + input_report_key(input, KEY_CAMERA, 1); + input_sync(input); + input_report_key(input, KEY_CAMERA, 0); + input_sync(input); + } +} + +#else + +static inline int ov511_input_init(struct usb_ov511 *ov) +{ + return 0; +} + +static inline void ov511_input_cleanup(struct usb_ov511 *ov) +{ +} + +static inline void ov511_input_report_key(struct usb_ov511 *ov) +{ +} + +#endif /* CONFIG_USB_OV511_SNAPSHOT_BUTTON */ + +/********************************************************************** + * * Register I/O * **********************************************************************/ @@ -1105,7 +1184,6 @@ ov51x_clear_snapshot(struct usb_ov511 *ov) } } -#if 0 /* Checks the status of the snapshot button. Returns 1 if it was pressed since * it was last cleared, and zero in all other cases (including errors) */ static int @@ -1130,7 +1208,6 @@ ov51x_check_snapshot(struct usb_ov511 *ov) return status; } -#endif /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 for failure. @@ -3149,10 +3226,10 @@ ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) } /* Post-processes the specified frame. This consists of: - * 1. Decompress frame, if necessary + * 1. Decompress frame, if necessary * 2. Deinterlace frame and scale to proper size, if necessary - * 3. Convert from YUV planar to destination format, if necessary - * 4. Fix the RGB offset, if necessary + * 3. Convert from YUV planar to destination format, if necessary + * 4. Fix the RGB offset, if necessary */ static void ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame) @@ -4387,6 +4464,11 @@ redo: if ((ov->snap_enabled) && (frame->snapshot)) { frame->snapshot = 0; ov51x_clear_snapshot(ov); + } else if (!ov->snap_enabled && ov->bclass == BCL_OV511) { + if (ov51x_check_snapshot(ov) == 1) { + ov511_input_report_key(ov); + ov51x_clear_snapshot(ov); + } } /* Decompression, format conversion, etc... */ @@ -5237,7 +5319,7 @@ ov511_configure(struct usb_ov511 *ov) }; static struct ov511_regvals aRegvalsNorm511[] = { - { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, + { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, @@ -5400,7 +5482,7 @@ ov518_configure(struct usb_ov511 *ov) static struct ov511_regvals aRegvalsNorm518[] = { { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ - { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x31, 0x0f }, { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, @@ -5413,7 +5495,7 @@ ov518_configure(struct usb_ov511 *ov) static struct ov511_regvals aRegvalsNorm518Plus[] = { { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ - { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x31, 0x0f }, { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, @@ -5880,6 +5962,13 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) mutex_lock(&ov->lock); + /* Snapshot is currently only supported on OV511, + * so no need to register the input device if it's not supported */ + if (!ov->snap_enabled && ov->bclass == BCL_OV511) { + if (ov511_input_init(ov) < 0) + dev_warn(&ov->dev->dev, "Could not register input device\n"); + } + return 0; error: @@ -5928,6 +6017,8 @@ ov51x_disconnect(struct usb_interface *intf) if (ov->vdev) video_unregister_device(ov->vdev); + ov511_input_cleanup(ov); + for (n = 0; n < OV511_NUMFRAMES; n++) ov->frame[n].grabstate = FRAME_ERROR; diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index c450c92..7c0ade1 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h @@ -259,6 +259,9 @@ /* Size of usb_make_path() buffer */ #define OV511_USB_PATH_LEN 64 +/* Size of 'phys' field for the snapshot button input device */ +#define OV511_KEY_PHYS_SIZE 64 + /* Bridge types */ enum { BRG_UNKNOWN, @@ -469,6 +472,11 @@ struct usb_ov511 { int snap_enabled; /* Snapshot mode enabled */ +#ifdef CONFIG_USB_OV511_SNAPSHOT_BUTTON + struct input_dev *key_input; + char key_phys[OV511_KEY_PHYS_SIZE]; +#endif + int bridge; /* Type of bridge (BRG_*) */ int bclass; /* Class of bridge (BCL_*) */ int sensor; /* Type of image sensor chip (SEN_*) */ -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html