aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean-François Moine <moinejf@free.fr>2010-10-01 06:54:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-20 23:06:21 -0400
commita95bd640e7e5642eca52b946f7a27481980154ac (patch)
treedf24e1ef35dcd56be42a23472e3db4e41c36ec42 /drivers
parenta067db847335207bd059f5b93bcbbb04910d8a69 (diff)
V4L/DVB: gspca - sonixj: Bad detection of the end of image
The 'end of image' block may be splitted between two ISOC packets. This case was not tested, so, some images could be lost and concatenated to previous one(s), raising 'frame overflow' errors. Signed-off-by: Jean-François Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/gspca/sonixj.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 3c699ac5233f..72f830a6572c 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -2820,38 +2820,52 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2820 struct sd *sd = (struct sd *) gspca_dev; 2820 struct sd *sd = (struct sd *) gspca_dev;
2821 int sof, avg_lum; 2821 int sof, avg_lum;
2822 2822
2823 sof = len - 64; 2823 /* the image ends on a 64 bytes block starting with
2824 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) { 2824 * ff d9 ff ff 00 c4 c4 96
2825 2825 * and followed by various information including luminosity */
2826 /* end of frame */ 2826 /* this block may be splitted between two packets */
2827 gspca_frame_add(gspca_dev, LAST_PACKET, 2827 /* a new image always starts in a new packet */
2828 data, sof + 2); 2828 switch (gspca_dev->last_packet_type) {
2829 if (sd->ag_cnt < 0) 2829 case DISCARD_PACKET: /* restart image building */
2830 return; 2830 sof = len - 64;
2831 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9)
2832 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
2833 return;
2834 case LAST_PACKET: /* put the JPEG 422 header */
2835 gspca_frame_add(gspca_dev, FIRST_PACKET,
2836 sd->jpeg_hdr, JPEG_HDR_SZ);
2837 break;
2838 }
2839 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2840
2841 data = gspca_dev->image;
2842 if (data == NULL)
2843 return;
2844 sof = gspca_dev->image_len - 64;
2845 if (data[sof] != 0xff
2846 || data[sof + 1] != 0xd9)
2847 return;
2848
2849 /* end of image found - remove the trailing data */
2850 gspca_dev->image_len = sof + 2;
2851 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
2852 if (sd->ag_cnt < 0)
2853 return;
2831/* w1 w2 w3 */ 2854/* w1 w2 w3 */
2832/* w4 w5 w6 */ 2855/* w4 w5 w6 */
2833/* w7 w8 */ 2856/* w7 w8 */
2834/* w4 */ 2857/* w4 */
2835 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6; 2858 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
2836/* w6 */ 2859/* w6 */
2837 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6; 2860 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
2838/* w2 */ 2861/* w2 */
2839 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6; 2862 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
2840/* w8 */ 2863/* w8 */
2841 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6; 2864 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
2842/* w5 */ 2865/* w5 */
2843 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4; 2866 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
2844 avg_lum >>= 4; 2867 avg_lum >>= 4;
2845 atomic_set(&sd->avg_lum, avg_lum); 2868 atomic_set(&sd->avg_lum, avg_lum);
2846 return;
2847 }
2848 if (gspca_dev->last_packet_type == LAST_PACKET) {
2849
2850 /* put the JPEG 422 header */
2851 gspca_frame_add(gspca_dev, FIRST_PACKET,
2852 sd->jpeg_hdr, JPEG_HDR_SZ);
2853 }
2854 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2855} 2869}
2856 2870
2857static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 2871static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)