diff options
Diffstat (limited to 'drivers/media/video/gspca/pac7311.c')
-rw-r--r-- | drivers/media/video/gspca/pac7311.c | 251 |
1 files changed, 118 insertions, 133 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 42cfcdfd8f4f..44fed9686729 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -51,6 +51,7 @@ | |||
51 | 51 | ||
52 | #define MODULE_NAME "pac7311" | 52 | #define MODULE_NAME "pac7311" |
53 | 53 | ||
54 | #include <linux/input.h> | ||
54 | #include "gspca.h" | 55 | #include "gspca.h" |
55 | 56 | ||
56 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | 57 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); |
@@ -88,7 +89,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | |||
88 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
89 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 90 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
90 | 91 | ||
91 | static struct ctrl sd_ctrls[] = { | 92 | static const struct ctrl sd_ctrls[] = { |
92 | /* This control is for both the 7302 and the 7311 */ | 93 | /* This control is for both the 7302 and the 7311 */ |
93 | { | 94 | { |
94 | { | 95 | { |
@@ -200,7 +201,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
200 | .priv = 0}, | 201 | .priv = 0}, |
201 | }; | 202 | }; |
202 | 203 | ||
203 | #define LOAD_PAGE3 255 | ||
204 | #define LOAD_PAGE4 254 | 204 | #define LOAD_PAGE4 254 |
205 | #define END_OF_SEQUENCE 0 | 205 | #define END_OF_SEQUENCE 0 |
206 | 206 | ||
@@ -259,12 +259,14 @@ static const __u8 page4_7311[] = { | |||
259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 | 259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 |
260 | }; | 260 | }; |
261 | 261 | ||
262 | static int reg_w_buf(struct gspca_dev *gspca_dev, | 262 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
263 | __u8 index, | 263 | __u8 index, |
264 | const char *buffer, int len) | 264 | const char *buffer, int len) |
265 | { | 265 | { |
266 | int ret; | 266 | int ret; |
267 | 267 | ||
268 | if (gspca_dev->usb_err < 0) | ||
269 | return; | ||
268 | memcpy(gspca_dev->usb_buf, buffer, len); | 270 | memcpy(gspca_dev->usb_buf, buffer, len); |
269 | ret = usb_control_msg(gspca_dev->dev, | 271 | ret = usb_control_msg(gspca_dev->dev, |
270 | usb_sndctrlpipe(gspca_dev->dev, 0), | 272 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -273,20 +275,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, | |||
273 | 0, /* value */ | 275 | 0, /* value */ |
274 | index, gspca_dev->usb_buf, len, | 276 | index, gspca_dev->usb_buf, len, |
275 | 500); | 277 | 500); |
276 | if (ret < 0) | 278 | if (ret < 0) { |
277 | PDEBUG(D_ERR, "reg_w_buf(): " | 279 | PDEBUG(D_ERR, "reg_w_buf(): " |
278 | "Failed to write registers to index 0x%x, error %i", | 280 | "Failed to write registers to index 0x%x, error %i", |
279 | index, ret); | 281 | index, ret); |
280 | return ret; | 282 | gspca_dev->usb_err = ret; |
283 | } | ||
281 | } | 284 | } |
282 | 285 | ||
283 | 286 | ||
284 | static int reg_w(struct gspca_dev *gspca_dev, | 287 | static void reg_w(struct gspca_dev *gspca_dev, |
285 | __u8 index, | 288 | __u8 index, |
286 | __u8 value) | 289 | __u8 value) |
287 | { | 290 | { |
288 | int ret; | 291 | int ret; |
289 | 292 | ||
293 | if (gspca_dev->usb_err < 0) | ||
294 | return; | ||
290 | gspca_dev->usb_buf[0] = value; | 295 | gspca_dev->usb_buf[0] = value; |
291 | ret = usb_control_msg(gspca_dev->dev, | 296 | ret = usb_control_msg(gspca_dev->dev, |
292 | usb_sndctrlpipe(gspca_dev->dev, 0), | 297 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -294,32 +299,32 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
294 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 299 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
295 | 0, index, gspca_dev->usb_buf, 1, | 300 | 0, index, gspca_dev->usb_buf, 1, |
296 | 500); | 301 | 500); |
297 | if (ret < 0) | 302 | if (ret < 0) { |
298 | PDEBUG(D_ERR, "reg_w(): " | 303 | PDEBUG(D_ERR, "reg_w(): " |
299 | "Failed to write register to index 0x%x, value 0x%x, error %i", | 304 | "Failed to write register to index 0x%x, value 0x%x, error %i", |
300 | index, value, ret); | 305 | index, value, ret); |
301 | return ret; | 306 | gspca_dev->usb_err = ret; |
307 | } | ||
302 | } | 308 | } |
303 | 309 | ||
304 | static int reg_w_seq(struct gspca_dev *gspca_dev, | 310 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
305 | const __u8 *seq, int len) | 311 | const __u8 *seq, int len) |
306 | { | 312 | { |
307 | int ret = 0; | ||
308 | while (--len >= 0) { | 313 | while (--len >= 0) { |
309 | if (0 <= ret) | 314 | reg_w(gspca_dev, seq[0], seq[1]); |
310 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
311 | seq += 2; | 315 | seq += 2; |
312 | } | 316 | } |
313 | return ret; | ||
314 | } | 317 | } |
315 | 318 | ||
316 | /* load the beginning of a page */ | 319 | /* load the beginning of a page */ |
317 | static int reg_w_page(struct gspca_dev *gspca_dev, | 320 | static void reg_w_page(struct gspca_dev *gspca_dev, |
318 | const __u8 *page, int len) | 321 | const __u8 *page, int len) |
319 | { | 322 | { |
320 | int index; | 323 | int index; |
321 | int ret = 0; | 324 | int ret = 0; |
322 | 325 | ||
326 | if (gspca_dev->usb_err < 0) | ||
327 | return; | ||
323 | for (index = 0; index < len; index++) { | 328 | for (index = 0; index < len; index++) { |
324 | if (page[index] == SKIP) /* skip this index */ | 329 | if (page[index] == SKIP) /* skip this index */ |
325 | continue; | 330 | continue; |
@@ -335,56 +340,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, | |||
335 | "Failed to write register to index 0x%x, " | 340 | "Failed to write register to index 0x%x, " |
336 | "value 0x%x, error %i", | 341 | "value 0x%x, error %i", |
337 | index, page[index], ret); | 342 | index, page[index], ret); |
343 | gspca_dev->usb_err = ret; | ||
338 | break; | 344 | break; |
339 | } | 345 | } |
340 | } | 346 | } |
341 | return ret; | ||
342 | } | 347 | } |
343 | 348 | ||
344 | /* output a variable sequence */ | 349 | /* output a variable sequence */ |
345 | static int reg_w_var(struct gspca_dev *gspca_dev, | 350 | static void reg_w_var(struct gspca_dev *gspca_dev, |
346 | const __u8 *seq, | 351 | const __u8 *seq, |
347 | const __u8 *page3, unsigned int page3_len, | ||
348 | const __u8 *page4, unsigned int page4_len) | 352 | const __u8 *page4, unsigned int page4_len) |
349 | { | 353 | { |
350 | int index, len; | 354 | int index, len; |
351 | int ret = 0; | ||
352 | 355 | ||
353 | for (;;) { | 356 | for (;;) { |
354 | index = *seq++; | 357 | index = *seq++; |
355 | len = *seq++; | 358 | len = *seq++; |
356 | switch (len) { | 359 | switch (len) { |
357 | case END_OF_SEQUENCE: | 360 | case END_OF_SEQUENCE: |
358 | return ret; | 361 | return; |
359 | case LOAD_PAGE4: | 362 | case LOAD_PAGE4: |
360 | ret = reg_w_page(gspca_dev, page4, page4_len); | 363 | reg_w_page(gspca_dev, page4, page4_len); |
361 | break; | ||
362 | case LOAD_PAGE3: | ||
363 | ret = reg_w_page(gspca_dev, page3, page3_len); | ||
364 | break; | 364 | break; |
365 | default: | 365 | default: |
366 | if (len > USB_BUF_SZ) { | 366 | if (len > USB_BUF_SZ) { |
367 | PDEBUG(D_ERR|D_STREAM, | 367 | PDEBUG(D_ERR|D_STREAM, |
368 | "Incorrect variable sequence"); | 368 | "Incorrect variable sequence"); |
369 | return -EINVAL; | 369 | return; |
370 | } | 370 | } |
371 | while (len > 0) { | 371 | while (len > 0) { |
372 | if (len < 8) { | 372 | if (len < 8) { |
373 | ret = reg_w_buf(gspca_dev, | 373 | reg_w_buf(gspca_dev, |
374 | index, seq, len); | 374 | index, seq, len); |
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | seq += len; | 375 | seq += len; |
378 | break; | 376 | break; |
379 | } | 377 | } |
380 | ret = reg_w_buf(gspca_dev, index, seq, 8); | 378 | reg_w_buf(gspca_dev, index, seq, 8); |
381 | seq += 8; | 379 | seq += 8; |
382 | index += 8; | 380 | index += 8; |
383 | len -= 8; | 381 | len -= 8; |
384 | } | 382 | } |
385 | } | 383 | } |
386 | if (ret < 0) | ||
387 | return ret; | ||
388 | } | 384 | } |
389 | /* not reached */ | 385 | /* not reached */ |
390 | } | 386 | } |
@@ -412,46 +408,36 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
412 | } | 408 | } |
413 | 409 | ||
414 | /* This function is used by pac7311 only */ | 410 | /* This function is used by pac7311 only */ |
415 | static int setcontrast(struct gspca_dev *gspca_dev) | 411 | static void setcontrast(struct gspca_dev *gspca_dev) |
416 | { | 412 | { |
417 | struct sd *sd = (struct sd *) gspca_dev; | 413 | struct sd *sd = (struct sd *) gspca_dev; |
418 | int ret; | ||
419 | 414 | ||
420 | ret = reg_w(gspca_dev, 0xff, 0x04); | 415 | reg_w(gspca_dev, 0xff, 0x04); |
421 | if (0 <= ret) | 416 | reg_w(gspca_dev, 0x10, sd->contrast >> 4); |
422 | ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); | ||
423 | /* load registers to sensor (Bit 0, auto clear) */ | 417 | /* load registers to sensor (Bit 0, auto clear) */ |
424 | if (0 <= ret) | 418 | reg_w(gspca_dev, 0x11, 0x01); |
425 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
426 | return ret; | ||
427 | } | 419 | } |
428 | 420 | ||
429 | static int setgain(struct gspca_dev *gspca_dev) | 421 | static void setgain(struct gspca_dev *gspca_dev) |
430 | { | 422 | { |
431 | struct sd *sd = (struct sd *) gspca_dev; | 423 | struct sd *sd = (struct sd *) gspca_dev; |
432 | int gain = GAIN_MAX - sd->gain; | 424 | int gain = GAIN_MAX - sd->gain; |
433 | int ret; | ||
434 | 425 | ||
435 | if (gain < 1) | 426 | if (gain < 1) |
436 | gain = 1; | 427 | gain = 1; |
437 | else if (gain > 245) | 428 | else if (gain > 245) |
438 | gain = 245; | 429 | gain = 245; |
439 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 430 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
440 | if (0 <= ret) | 431 | reg_w(gspca_dev, 0x0e, 0x00); |
441 | ret = reg_w(gspca_dev, 0x0e, 0x00); | 432 | reg_w(gspca_dev, 0x0f, gain); |
442 | if (0 <= ret) | ||
443 | ret = reg_w(gspca_dev, 0x0f, gain); | ||
444 | 433 | ||
445 | /* load registers to sensor (Bit 0, auto clear) */ | 434 | /* load registers to sensor (Bit 0, auto clear) */ |
446 | if (0 <= ret) | 435 | reg_w(gspca_dev, 0x11, 0x01); |
447 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
448 | return ret; | ||
449 | } | 436 | } |
450 | 437 | ||
451 | static int setexposure(struct gspca_dev *gspca_dev) | 438 | static void setexposure(struct gspca_dev *gspca_dev) |
452 | { | 439 | { |
453 | struct sd *sd = (struct sd *) gspca_dev; | 440 | struct sd *sd = (struct sd *) gspca_dev; |
454 | int ret; | ||
455 | __u8 reg; | 441 | __u8 reg; |
456 | 442 | ||
457 | /* register 2 of frame 3/4 contains the clock divider configuring the | 443 | /* register 2 of frame 3/4 contains the clock divider configuring the |
@@ -463,94 +449,72 @@ static int setexposure(struct gspca_dev *gspca_dev) | |||
463 | else if (reg > 63) | 449 | else if (reg > 63) |
464 | reg = 63; | 450 | reg = 63; |
465 | 451 | ||
466 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 452 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
467 | if (0 <= ret) | 453 | reg_w(gspca_dev, 0x02, reg); |
468 | ret = reg_w(gspca_dev, 0x02, reg); | 454 | |
469 | /* Page 1 register 8 must always be 0x08 except when not in | 455 | /* Page 1 register 8 must always be 0x08 except when not in |
470 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ | 456 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ |
471 | if (0 <= ret) | 457 | reg_w(gspca_dev, 0xff, 0x01); |
472 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
473 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | 458 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && |
474 | reg <= 3) { | 459 | reg <= 3) { |
475 | if (0 <= ret) | 460 | reg_w(gspca_dev, 0x08, 0x09); |
476 | ret = reg_w(gspca_dev, 0x08, 0x09); | ||
477 | } else { | 461 | } else { |
478 | if (0 <= ret) | 462 | reg_w(gspca_dev, 0x08, 0x08); |
479 | ret = reg_w(gspca_dev, 0x08, 0x08); | ||
480 | } | 463 | } |
481 | 464 | ||
482 | /* load registers to sensor (Bit 0, auto clear) */ | 465 | /* load registers to sensor (Bit 0, auto clear) */ |
483 | if (0 <= ret) | 466 | reg_w(gspca_dev, 0x11, 0x01); |
484 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
485 | return ret; | ||
486 | } | 467 | } |
487 | 468 | ||
488 | static int sethvflip(struct gspca_dev *gspca_dev) | 469 | static void sethvflip(struct gspca_dev *gspca_dev) |
489 | { | 470 | { |
490 | struct sd *sd = (struct sd *) gspca_dev; | 471 | struct sd *sd = (struct sd *) gspca_dev; |
491 | int ret; | ||
492 | __u8 data; | 472 | __u8 data; |
493 | 473 | ||
494 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 474 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
495 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); | 475 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); |
496 | if (0 <= ret) | 476 | reg_w(gspca_dev, 0x21, data); |
497 | ret = reg_w(gspca_dev, 0x21, data); | 477 | |
498 | /* load registers to sensor (Bit 0, auto clear) */ | 478 | /* load registers to sensor (Bit 0, auto clear) */ |
499 | if (0 <= ret) | 479 | reg_w(gspca_dev, 0x11, 0x01); |
500 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
501 | return ret; | ||
502 | } | 480 | } |
503 | 481 | ||
504 | /* this function is called at probe and resume time for pac7311 */ | 482 | /* this function is called at probe and resume time for pac7311 */ |
505 | static int sd_init(struct gspca_dev *gspca_dev) | 483 | static int sd_init(struct gspca_dev *gspca_dev) |
506 | { | 484 | { |
507 | return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); | 485 | reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); |
486 | return gspca_dev->usb_err; | ||
508 | } | 487 | } |
509 | 488 | ||
510 | static int sd_start(struct gspca_dev *gspca_dev) | 489 | static int sd_start(struct gspca_dev *gspca_dev) |
511 | { | 490 | { |
512 | struct sd *sd = (struct sd *) gspca_dev; | 491 | struct sd *sd = (struct sd *) gspca_dev; |
513 | int ret; | ||
514 | 492 | ||
515 | sd->sof_read = 0; | 493 | sd->sof_read = 0; |
516 | 494 | ||
517 | ret = reg_w_var(gspca_dev, start_7311, | 495 | reg_w_var(gspca_dev, start_7311, |
518 | NULL, 0, | ||
519 | page4_7311, sizeof(page4_7311)); | 496 | page4_7311, sizeof(page4_7311)); |
520 | if (0 <= ret) | 497 | setcontrast(gspca_dev); |
521 | ret = setcontrast(gspca_dev); | 498 | setgain(gspca_dev); |
522 | if (0 <= ret) | 499 | setexposure(gspca_dev); |
523 | ret = setgain(gspca_dev); | 500 | sethvflip(gspca_dev); |
524 | if (0 <= ret) | ||
525 | ret = setexposure(gspca_dev); | ||
526 | if (0 <= ret) | ||
527 | ret = sethvflip(gspca_dev); | ||
528 | 501 | ||
529 | /* set correct resolution */ | 502 | /* set correct resolution */ |
530 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { | 503 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
531 | case 2: /* 160x120 pac7311 */ | 504 | case 2: /* 160x120 pac7311 */ |
532 | if (0 <= ret) | 505 | reg_w(gspca_dev, 0xff, 0x01); |
533 | ret = reg_w(gspca_dev, 0xff, 0x01); | 506 | reg_w(gspca_dev, 0x17, 0x20); |
534 | if (0 <= ret) | 507 | reg_w(gspca_dev, 0x87, 0x10); |
535 | ret = reg_w(gspca_dev, 0x17, 0x20); | ||
536 | if (0 <= ret) | ||
537 | ret = reg_w(gspca_dev, 0x87, 0x10); | ||
538 | break; | 508 | break; |
539 | case 1: /* 320x240 pac7311 */ | 509 | case 1: /* 320x240 pac7311 */ |
540 | if (0 <= ret) | 510 | reg_w(gspca_dev, 0xff, 0x01); |
541 | ret = reg_w(gspca_dev, 0xff, 0x01); | 511 | reg_w(gspca_dev, 0x17, 0x30); |
542 | if (0 <= ret) | 512 | reg_w(gspca_dev, 0x87, 0x11); |
543 | ret = reg_w(gspca_dev, 0x17, 0x30); | ||
544 | if (0 <= ret) | ||
545 | ret = reg_w(gspca_dev, 0x87, 0x11); | ||
546 | break; | 513 | break; |
547 | case 0: /* 640x480 */ | 514 | case 0: /* 640x480 */ |
548 | if (0 <= ret) | 515 | reg_w(gspca_dev, 0xff, 0x01); |
549 | ret = reg_w(gspca_dev, 0xff, 0x01); | 516 | reg_w(gspca_dev, 0x17, 0x00); |
550 | if (0 <= ret) | 517 | reg_w(gspca_dev, 0x87, 0x12); |
551 | ret = reg_w(gspca_dev, 0x17, 0x00); | ||
552 | if (0 <= ret) | ||
553 | ret = reg_w(gspca_dev, 0x87, 0x12); | ||
554 | break; | 518 | break; |
555 | } | 519 | } |
556 | 520 | ||
@@ -559,37 +523,24 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
559 | atomic_set(&sd->avg_lum, -1); | 523 | atomic_set(&sd->avg_lum, -1); |
560 | 524 | ||
561 | /* start stream */ | 525 | /* start stream */ |
562 | if (0 <= ret) | 526 | reg_w(gspca_dev, 0xff, 0x01); |
563 | ret = reg_w(gspca_dev, 0xff, 0x01); | 527 | reg_w(gspca_dev, 0x78, 0x05); |
564 | if (0 <= ret) | ||
565 | ret = reg_w(gspca_dev, 0x78, 0x05); | ||
566 | 528 | ||
567 | return ret; | 529 | return gspca_dev->usb_err; |
568 | } | 530 | } |
569 | 531 | ||
570 | static void sd_stopN(struct gspca_dev *gspca_dev) | 532 | static void sd_stopN(struct gspca_dev *gspca_dev) |
571 | { | 533 | { |
572 | int ret; | 534 | reg_w(gspca_dev, 0xff, 0x04); |
573 | 535 | reg_w(gspca_dev, 0x27, 0x80); | |
574 | ret = reg_w(gspca_dev, 0xff, 0x04); | 536 | reg_w(gspca_dev, 0x28, 0xca); |
575 | if (0 <= ret) | 537 | reg_w(gspca_dev, 0x29, 0x53); |
576 | ret = reg_w(gspca_dev, 0x27, 0x80); | 538 | reg_w(gspca_dev, 0x2a, 0x0e); |
577 | if (0 <= ret) | 539 | reg_w(gspca_dev, 0xff, 0x01); |
578 | ret = reg_w(gspca_dev, 0x28, 0xca); | 540 | reg_w(gspca_dev, 0x3e, 0x20); |
579 | if (0 <= ret) | 541 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
580 | ret = reg_w(gspca_dev, 0x29, 0x53); | 542 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
581 | if (0 <= ret) | 543 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
582 | ret = reg_w(gspca_dev, 0x2a, 0x0e); | ||
583 | if (0 <= ret) | ||
584 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
585 | if (0 <= ret) | ||
586 | ret = reg_w(gspca_dev, 0x3e, 0x20); | ||
587 | if (0 <= ret) | ||
588 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
589 | if (0 <= ret) | ||
590 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
591 | if (0 <= ret) | ||
592 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
593 | } | 544 | } |
594 | 545 | ||
595 | /* called on streamoff with alt 0 and on disconnect for 7311 */ | 546 | /* called on streamoff with alt 0 and on disconnect for 7311 */ |
@@ -734,7 +685,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
734 | if (gspca_dev->streaming) { | 685 | if (gspca_dev->streaming) { |
735 | setcontrast(gspca_dev); | 686 | setcontrast(gspca_dev); |
736 | } | 687 | } |
737 | return 0; | 688 | return gspca_dev->usb_err; |
738 | } | 689 | } |
739 | 690 | ||
740 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 691 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -752,7 +703,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |||
752 | sd->gain = val; | 703 | sd->gain = val; |
753 | if (gspca_dev->streaming) | 704 | if (gspca_dev->streaming) |
754 | setgain(gspca_dev); | 705 | setgain(gspca_dev); |
755 | return 0; | 706 | return gspca_dev->usb_err; |
756 | } | 707 | } |
757 | 708 | ||
758 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 709 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -770,7 +721,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
770 | sd->exposure = val; | 721 | sd->exposure = val; |
771 | if (gspca_dev->streaming) | 722 | if (gspca_dev->streaming) |
772 | setexposure(gspca_dev); | 723 | setexposure(gspca_dev); |
773 | return 0; | 724 | return gspca_dev->usb_err; |
774 | } | 725 | } |
775 | 726 | ||
776 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 727 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -801,7 +752,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
801 | } | 752 | } |
802 | } | 753 | } |
803 | 754 | ||
804 | return 0; | 755 | return gspca_dev->usb_err; |
805 | } | 756 | } |
806 | 757 | ||
807 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 758 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -819,7 +770,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
819 | sd->hflip = val; | 770 | sd->hflip = val; |
820 | if (gspca_dev->streaming) | 771 | if (gspca_dev->streaming) |
821 | sethvflip(gspca_dev); | 772 | sethvflip(gspca_dev); |
822 | return 0; | 773 | return gspca_dev->usb_err; |
823 | } | 774 | } |
824 | 775 | ||
825 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 776 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -837,7 +788,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
837 | sd->vflip = val; | 788 | sd->vflip = val; |
838 | if (gspca_dev->streaming) | 789 | if (gspca_dev->streaming) |
839 | sethvflip(gspca_dev); | 790 | sethvflip(gspca_dev); |
840 | return 0; | 791 | return gspca_dev->usb_err; |
841 | } | 792 | } |
842 | 793 | ||
843 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 794 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -848,8 +799,39 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
848 | return 0; | 799 | return 0; |
849 | } | 800 | } |
850 | 801 | ||
802 | #ifdef CONFIG_INPUT | ||
803 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
804 | u8 *data, /* interrupt packet data */ | ||
805 | int len) /* interrupt packet length */ | ||
806 | { | ||
807 | int ret = -EINVAL; | ||
808 | u8 data0, data1; | ||
809 | |||
810 | if (len == 2) { | ||
811 | data0 = data[0]; | ||
812 | data1 = data[1]; | ||
813 | if ((data0 == 0x00 && data1 == 0x11) || | ||
814 | (data0 == 0x22 && data1 == 0x33) || | ||
815 | (data0 == 0x44 && data1 == 0x55) || | ||
816 | (data0 == 0x66 && data1 == 0x77) || | ||
817 | (data0 == 0x88 && data1 == 0x99) || | ||
818 | (data0 == 0xaa && data1 == 0xbb) || | ||
819 | (data0 == 0xcc && data1 == 0xdd) || | ||
820 | (data0 == 0xee && data1 == 0xff)) { | ||
821 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
822 | input_sync(gspca_dev->input_dev); | ||
823 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
824 | input_sync(gspca_dev->input_dev); | ||
825 | ret = 0; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | return ret; | ||
830 | } | ||
831 | #endif | ||
832 | |||
851 | /* sub-driver description for pac7311 */ | 833 | /* sub-driver description for pac7311 */ |
852 | static struct sd_desc sd_desc = { | 834 | static const struct sd_desc sd_desc = { |
853 | .name = MODULE_NAME, | 835 | .name = MODULE_NAME, |
854 | .ctrls = sd_ctrls, | 836 | .ctrls = sd_ctrls, |
855 | .nctrls = ARRAY_SIZE(sd_ctrls), | 837 | .nctrls = ARRAY_SIZE(sd_ctrls), |
@@ -860,6 +842,9 @@ static struct sd_desc sd_desc = { | |||
860 | .stop0 = sd_stop0, | 842 | .stop0 = sd_stop0, |
861 | .pkt_scan = sd_pkt_scan, | 843 | .pkt_scan = sd_pkt_scan, |
862 | .dq_callback = do_autogain, | 844 | .dq_callback = do_autogain, |
845 | #ifdef CONFIG_INPUT | ||
846 | .int_pkt_scan = sd_int_pkt_scan, | ||
847 | #endif | ||
863 | }; | 848 | }; |
864 | 849 | ||
865 | /* -- module initialisation -- */ | 850 | /* -- module initialisation -- */ |