aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-02-19 05:37:08 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:11:10 -0500
commit417a4d26591e3f2b7784791246048ed315f3fdce (patch)
tree6986a9e477413ef937610a9b845956cc91904233 /drivers/media
parente7637521ac92ce99045b8f8a9c1419bb7814ff9a (diff)
V4L/DVB: gspca_ov519: add support for the button on ov519 based cams
Note due to hardware limitiations (no interrupt endpoint), this only works when the camera is streaming. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/gspca/ov519.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 541b8f0b0d36..d9b89a2803df 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -38,6 +38,7 @@
38 */ 38 */
39#define MODULE_NAME "ov519" 39#define MODULE_NAME "ov519"
40 40
41#include <linux/input.h>
41#include "gspca.h" 42#include "gspca.h"
42 43
43MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 44MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
@@ -70,6 +71,9 @@ struct sd {
70 char invert_led; 71 char invert_led;
71#define BRIDGE_INVERT_LED 8 72#define BRIDGE_INVERT_LED 8
72 73
74 char snapshot_pressed;
75 char snapshot_needs_reset;
76
73 /* Determined by sensor type */ 77 /* Determined by sensor type */
74 __u8 sif; 78 __u8 sif;
75 79
@@ -2685,6 +2689,26 @@ static void ov51x_led_control(struct sd *sd, int on)
2685 } 2689 }
2686} 2690}
2687 2691
2692static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
2693{
2694 struct sd *sd = (struct sd *) gspca_dev;
2695
2696 if (!sd->snapshot_needs_reset)
2697 return;
2698
2699 /* Note it is important that we clear sd->snapshot_needs_reset,
2700 before actually clearing the snapshot state in the bridge
2701 otherwise we might race with the pkt_scan interrupt handler */
2702 sd->snapshot_needs_reset = 0;
2703
2704 switch (sd->bridge) {
2705 case BRIDGE_OV519:
2706 reg_w(sd, R51x_SYS_RESET, 0x40);
2707 reg_w(sd, R51x_SYS_RESET, 0x00);
2708 break;
2709 }
2710}
2711
2688static int ov51x_upload_quan_tables(struct sd *sd) 2712static int ov51x_upload_quan_tables(struct sd *sd)
2689{ 2713{
2690 const unsigned char yQuanTable511[] = { 2714 const unsigned char yQuanTable511[] = {
@@ -3921,6 +3945,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
3921 setautobrightness(sd); 3945 setautobrightness(sd);
3922 setfreq(sd); 3946 setfreq(sd);
3923 3947
3948 /* Force clear snapshot state in case the snapshot button was
3949 pressed while we weren't streaming */
3950 sd->snapshot_needs_reset = 1;
3951 sd_reset_snapshot(gspca_dev);
3952 sd->snapshot_pressed = 0;
3953
3924 ret = ov51x_restart(sd); 3954 ret = ov51x_restart(sd);
3925 if (ret < 0) 3955 if (ret < 0)
3926 goto out; 3956 goto out;
@@ -4033,6 +4063,30 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
4033 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 4063 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4034} 4064}
4035 4065
4066static void ov519_handle_button(struct gspca_dev *gspca_dev, u8 state)
4067{
4068 struct sd *sd = (struct sd *) gspca_dev;
4069
4070 /* This should never happen, but better to check */
4071 if (state != 0 && state != 1)
4072 return;
4073
4074 /* We may need to reset the button state multiple times, as resetting
4075 does not work as long as the button stays pressed, so always set
4076 snapshot_needs_reset (instead of only on a state change to 1). */
4077 if (state)
4078 sd->snapshot_needs_reset = 1;
4079
4080 if (sd->snapshot_pressed != state) {
4081#ifdef CONFIG_INPUT
4082 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
4083 input_sync(gspca_dev->input_dev);
4084#endif
4085
4086 sd->snapshot_pressed = state;
4087 }
4088}
4089
4036static void ov519_pkt_scan(struct gspca_dev *gspca_dev, 4090static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
4037 u8 *data, /* isoc packet */ 4091 u8 *data, /* isoc packet */
4038 int len) /* iso packet length */ 4092 int len) /* iso packet length */
@@ -4052,6 +4106,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
4052 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { 4106 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
4053 switch (data[3]) { 4107 switch (data[3]) {
4054 case 0x50: /* start of frame */ 4108 case 0x50: /* start of frame */
4109 /* Don't check the button state here, as the state
4110 usually (always ?) changes at EOF and checking it
4111 here leads to unnecessary snapshot state resets. */
4055#define HDRSZ 16 4112#define HDRSZ 16
4056 data += HDRSZ; 4113 data += HDRSZ;
4057 len -= HDRSZ; 4114 len -= HDRSZ;
@@ -4063,6 +4120,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
4063 gspca_dev->last_packet_type = DISCARD_PACKET; 4120 gspca_dev->last_packet_type = DISCARD_PACKET;
4064 return; 4121 return;
4065 case 0x51: /* end of frame */ 4122 case 0x51: /* end of frame */
4123 ov519_handle_button(gspca_dev, data[11]);
4066 if (data[9] != 0) 4124 if (data[9] != 0)
4067 gspca_dev->last_packet_type = DISCARD_PACKET; 4125 gspca_dev->last_packet_type = DISCARD_PACKET;
4068 gspca_frame_add(gspca_dev, LAST_PACKET, 4126 gspca_frame_add(gspca_dev, LAST_PACKET,
@@ -4505,9 +4563,13 @@ static const struct sd_desc sd_desc = {
4505 .stopN = sd_stopN, 4563 .stopN = sd_stopN,
4506 .stop0 = sd_stop0, 4564 .stop0 = sd_stop0,
4507 .pkt_scan = sd_pkt_scan, 4565 .pkt_scan = sd_pkt_scan,
4566 .dq_callback = sd_reset_snapshot,
4508 .querymenu = sd_querymenu, 4567 .querymenu = sd_querymenu,
4509 .get_jcomp = sd_get_jcomp, 4568 .get_jcomp = sd_get_jcomp,
4510 .set_jcomp = sd_set_jcomp, 4569 .set_jcomp = sd_set_jcomp,
4570#ifdef CONFIG_INPUT
4571 .other_input = 1,
4572#endif
4511}; 4573};
4512 4574
4513/* -- module initialisation -- */ 4575/* -- module initialisation -- */