aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/gspca/sonixb.c160
1 files changed, 106 insertions, 54 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index bfbd8c17d28b..f47a82902fa3 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -56,6 +56,8 @@ struct sd {
56 int prev_avg_lum; 56 int prev_avg_lum;
57 int exp_too_low_cnt; 57 int exp_too_low_cnt;
58 int exp_too_high_cnt; 58 int exp_too_high_cnt;
59 int header_read;
60 u8 header[12]; /* Header without sof marker */
59 61
60 unsigned short exposure; 62 unsigned short exposure;
61 unsigned char gain; 63 unsigned char gain;
@@ -1177,13 +1179,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
1177 sd_init(gspca_dev); 1179 sd_init(gspca_dev);
1178} 1180}
1179 1181
1180static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1182static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
1181 u8 *data, /* isoc packet */
1182 int len) /* iso packet length */
1183{ 1183{
1184 int i;
1185 struct sd *sd = (struct sd *) gspca_dev; 1184 struct sd *sd = (struct sd *) gspca_dev;
1186 struct cam *cam = &gspca_dev->cam; 1185 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
1187 1186
1188 /* frames start with: 1187 /* frames start with:
1189 * ff ff 00 c4 c4 96 synchro 1188 * ff ff 00 c4 c4 96 synchro
@@ -1194,58 +1193,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1194 * ll mm brightness sum outside auto exposure 1193 * ll mm brightness sum outside auto exposure
1195 * (xx xx xx xx xx) audio values for snc103 1194 * (xx xx xx xx xx) audio values for snc103
1196 */ 1195 */
1197 if (len > 6 && len < 24) { 1196 for (i = 0; i < len; i++) {
1198 for (i = 0; i < len - 6; i++) { 1197 switch (sd->header_read) {
1199 if (data[0 + i] == 0xff 1198 case 0:
1200 && data[1 + i] == 0xff 1199 if (data[i] == 0xff)
1201 && data[2 + i] == 0x00 1200 sd->header_read++;
1202 && data[3 + i] == 0xc4 1201 break;
1203 && data[4 + i] == 0xc4 1202 case 1:
1204 && data[5 + i] == 0x96) { /* start of frame */ 1203 if (data[i] == 0xff)
1205 int lum = -1; 1204 sd->header_read++;
1206 int pkt_type = LAST_PACKET; 1205 else
1207 int fr_h_sz = (sd->bridge == BRIDGE_103) ? 1206 sd->header_read = 0;
1208 18 : 12; 1207 break;
1209 1208 case 2:
1210 if (len - i < fr_h_sz) { 1209 if (data[i] == 0x00)
1211 PDEBUG(D_STREAM, "packet too short to" 1210 sd->header_read++;
1212 " get avg brightness"); 1211 else if (data[i] != 0xff)
1213 } else if (sd->bridge == BRIDGE_103) { 1212 sd->header_read = 0;
1214 lum = data[i + 9] + 1213 break;
1215 (data[i + 10] << 8); 1214 case 3:
1216 } else { 1215 if (data[i] == 0xc4)
1217 lum = data[i + 8] + (data[i + 9] << 8); 1216 sd->header_read++;
1218 } 1217 else if (data[i] == 0xff)
1219 /* When exposure changes midway a frame we 1218 sd->header_read = 1;
1220 get a lum of 0 in this case drop 2 frames 1219 else
1221 as the frames directly after an exposure 1220 sd->header_read = 0;
1222 change have an unstable image. Sometimes lum 1221 break;
1223 *really* is 0 (cam used in low light with 1222 case 4:
1224 low exposure setting), so do not drop frames 1223 if (data[i] == 0xc4)
1225 if the previous lum was 0 too. */ 1224 sd->header_read++;
1226 if (lum == 0 && sd->prev_avg_lum != 0) { 1225 else if (data[i] == 0xff)
1227 lum = -1; 1226 sd->header_read = 1;
1228 sd->frames_to_drop = 2; 1227 else
1229 sd->prev_avg_lum = 0; 1228 sd->header_read = 0;
1230 } else 1229 break;
1231 sd->prev_avg_lum = lum; 1230 case 5:
1232 atomic_set(&sd->avg_lum, lum); 1231 if (data[i] == 0x96)
1233 1232 sd->header_read++;
1234 if (sd->frames_to_drop) { 1233 else if (data[i] == 0xff)
1235 sd->frames_to_drop--; 1234 sd->header_read = 1;
1236 pkt_type = DISCARD_PACKET; 1235 else
1237 } 1236 sd->header_read = 0;
1238 1237 break;
1239 gspca_frame_add(gspca_dev, pkt_type, 1238 default:
1240 NULL, 0); 1239 sd->header[sd->header_read - 6] = data[i];
1241 data += i + fr_h_sz; 1240 sd->header_read++;
1242 len -= i + fr_h_sz; 1241 if (sd->header_read == header_size) {
1243 gspca_frame_add(gspca_dev, FIRST_PACKET, 1242 sd->header_read = 0;
1244 data, len); 1243 return data + i + 1;
1245 return;
1246 } 1244 }
1247 } 1245 }
1248 } 1246 }
1247 return NULL;
1248}
1249
1250static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1251 u8 *data, /* isoc packet */
1252 int len) /* iso packet length */
1253{
1254 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1255 struct sd *sd = (struct sd *) gspca_dev;
1256 struct cam *cam = &gspca_dev->cam;
1257 u8 *sof;
1258
1259 sof = find_sof(gspca_dev, data, len);
1260 if (sof) {
1261 if (sd->bridge == BRIDGE_103) {
1262 fr_h_sz = 18;
1263 lum_offset = 3;
1264 } else {
1265 fr_h_sz = 12;
1266 lum_offset = 2;
1267 }
1268
1269 len_after_sof = len - (sof - data);
1270 len = (sof - data) - fr_h_sz;
1271 if (len < 0)
1272 len = 0;
1273 }
1249 1274
1250 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { 1275 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1251 /* In raw mode we sometimes get some garbage after the frame 1276 /* In raw mode we sometimes get some garbage after the frame
@@ -1259,6 +1284,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1259 } 1284 }
1260 1285
1261 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 1286 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1287
1288 if (sof) {
1289 int lum = sd->header[lum_offset] +
1290 (sd->header[lum_offset + 1] << 8);
1291
1292 /* When exposure changes midway a frame we
1293 get a lum of 0 in this case drop 2 frames
1294 as the frames directly after an exposure
1295 change have an unstable image. Sometimes lum
1296 *really* is 0 (cam used in low light with
1297 low exposure setting), so do not drop frames
1298 if the previous lum was 0 too. */
1299 if (lum == 0 && sd->prev_avg_lum != 0) {
1300 lum = -1;
1301 sd->frames_to_drop = 2;
1302 sd->prev_avg_lum = 0;
1303 } else
1304 sd->prev_avg_lum = lum;
1305 atomic_set(&sd->avg_lum, lum);
1306
1307 if (sd->frames_to_drop)
1308 sd->frames_to_drop--;
1309 else
1310 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1311
1312 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1313 }
1262} 1314}
1263 1315
1264static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 1316static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)