Commit 417a4d26 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e7637521
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
*/ */
#define MODULE_NAME "ov519" #define MODULE_NAME "ov519"
#include <linux/input.h>
#include "gspca.h" #include "gspca.h"
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
...@@ -70,6 +71,9 @@ struct sd { ...@@ -70,6 +71,9 @@ struct sd {
char invert_led; char invert_led;
#define BRIDGE_INVERT_LED 8 #define BRIDGE_INVERT_LED 8
char snapshot_pressed;
char snapshot_needs_reset;
/* Determined by sensor type */ /* Determined by sensor type */
__u8 sif; __u8 sif;
...@@ -2685,6 +2689,26 @@ static void ov51x_led_control(struct sd *sd, int on) ...@@ -2685,6 +2689,26 @@ static void ov51x_led_control(struct sd *sd, int on)
} }
} }
static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (!sd->snapshot_needs_reset)
return;
/* Note it is important that we clear sd->snapshot_needs_reset,
before actually clearing the snapshot state in the bridge
otherwise we might race with the pkt_scan interrupt handler */
sd->snapshot_needs_reset = 0;
switch (sd->bridge) {
case BRIDGE_OV519:
reg_w(sd, R51x_SYS_RESET, 0x40);
reg_w(sd, R51x_SYS_RESET, 0x00);
break;
}
}
static int ov51x_upload_quan_tables(struct sd *sd) static int ov51x_upload_quan_tables(struct sd *sd)
{ {
const unsigned char yQuanTable511[] = { const unsigned char yQuanTable511[] = {
...@@ -3921,6 +3945,12 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -3921,6 +3945,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
setautobrightness(sd); setautobrightness(sd);
setfreq(sd); setfreq(sd);
/* Force clear snapshot state in case the snapshot button was
pressed while we weren't streaming */
sd->snapshot_needs_reset = 1;
sd_reset_snapshot(gspca_dev);
sd->snapshot_pressed = 0;
ret = ov51x_restart(sd); ret = ov51x_restart(sd);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -4033,6 +4063,30 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -4033,6 +4063,30 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, data, len); gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
} }
static void ov519_handle_button(struct gspca_dev *gspca_dev, u8 state)
{
struct sd *sd = (struct sd *) gspca_dev;
/* This should never happen, but better to check */
if (state != 0 && state != 1)
return;
/* We may need to reset the button state multiple times, as resetting
does not work as long as the button stays pressed, so always set
snapshot_needs_reset (instead of only on a state change to 1). */
if (state)
sd->snapshot_needs_reset = 1;
if (sd->snapshot_pressed != state) {
#ifdef CONFIG_INPUT
input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
input_sync(gspca_dev->input_dev);
#endif
sd->snapshot_pressed = state;
}
}
static void ov519_pkt_scan(struct gspca_dev *gspca_dev, static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
u8 *data, /* isoc packet */ u8 *data, /* isoc packet */
int len) /* iso packet length */ int len) /* iso packet length */
...@@ -4052,6 +4106,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -4052,6 +4106,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
switch (data[3]) { switch (data[3]) {
case 0x50: /* start of frame */ case 0x50: /* start of frame */
/* Don't check the button state here, as the state
usually (always ?) changes at EOF and checking it
here leads to unnecessary snapshot state resets. */
#define HDRSZ 16 #define HDRSZ 16
data += HDRSZ; data += HDRSZ;
len -= HDRSZ; len -= HDRSZ;
...@@ -4063,6 +4120,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -4063,6 +4120,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
gspca_dev->last_packet_type = DISCARD_PACKET; gspca_dev->last_packet_type = DISCARD_PACKET;
return; return;
case 0x51: /* end of frame */ case 0x51: /* end of frame */
ov519_handle_button(gspca_dev, data[11]);
if (data[9] != 0) if (data[9] != 0)
gspca_dev->last_packet_type = DISCARD_PACKET; gspca_dev->last_packet_type = DISCARD_PACKET;
gspca_frame_add(gspca_dev, LAST_PACKET, gspca_frame_add(gspca_dev, LAST_PACKET,
...@@ -4505,9 +4563,13 @@ static const struct sd_desc sd_desc = { ...@@ -4505,9 +4563,13 @@ static const struct sd_desc sd_desc = {
.stopN = sd_stopN, .stopN = sd_stopN,
.stop0 = sd_stop0, .stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan, .pkt_scan = sd_pkt_scan,
.dq_callback = sd_reset_snapshot,
.querymenu = sd_querymenu, .querymenu = sd_querymenu,
.get_jcomp = sd_get_jcomp, .get_jcomp = sd_get_jcomp,
.set_jcomp = sd_set_jcomp, .set_jcomp = sd_set_jcomp,
#ifdef CONFIG_INPUT
.other_input = 1,
#endif
}; };
/* -- module initialisation -- */ /* -- module initialisation -- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment