diff options
author | Hans de Goede <hdegoede@redhat.com> | 2010-02-19 05:37:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:11:10 -0500 |
commit | 417a4d26591e3f2b7784791246048ed315f3fdce (patch) | |
tree | 6986a9e477413ef937610a9b845956cc91904233 /drivers/media | |
parent | e7637521ac92ce99045b8f8a9c1419bb7814ff9a (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.c | 62 |
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 | ||
43 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 44 | MODULE_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 | ||
2692 | static 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 | |||
2688 | static int ov51x_upload_quan_tables(struct sd *sd) | 2712 | static 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 | ||
4066 | static 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 | |||
4036 | static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | 4090 | static 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 -- */ |