aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/pac7302.c
diff options
context:
space:
mode:
authorMárton Németh <nm127@freemail.hu>2009-11-07 03:52:02 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:41:37 -0500
commitb1784b3377bdeaeb6b9d01e651ff07bd44fec0f4 (patch)
treeae09c129021a7e1e7fa2ace0133509c0194693c2 /drivers/media/video/gspca/pac7302.c
parent67c98f72e132e191ff4db0ac7bd81ea94fa5c667 (diff)
V4L/DVB (13383): gspca - pac7311/pac7302: Propagate error to higher level software.
The usb_control_msg() can fail any time. Only continue writing sequence if there was no error with the previous write. If there was any problem stop sending URBs and propagate the error to the gspca_main. Signed-off-by: Márton Németh <nm127@freemail.hu> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/pac7302.c')
-rw-r--r--drivers/media/video/gspca/pac7302.c155
1 files changed, 102 insertions, 53 deletions
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index ae1d90a85c5c..ec2930871d1f 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -331,7 +331,7 @@ static const __u8 page3_7302[] = {
331 0x00 331 0x00
332}; 332};
333 333
334static void reg_w_buf(struct gspca_dev *gspca_dev, 334static int reg_w_buf(struct gspca_dev *gspca_dev,
335 __u8 index, 335 __u8 index,
336 const char *buffer, int len) 336 const char *buffer, int len)
337{ 337{
@@ -349,10 +349,11 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
349 PDEBUG(D_ERR, "reg_w_buf(): " 349 PDEBUG(D_ERR, "reg_w_buf(): "
350 "Failed to write registers to index 0x%x, error %i", 350 "Failed to write registers to index 0x%x, error %i",
351 index, ret); 351 index, ret);
352 return ret;
352} 353}
353 354
354 355
355static void reg_w(struct gspca_dev *gspca_dev, 356static int reg_w(struct gspca_dev *gspca_dev,
356 __u8 index, 357 __u8 index,
357 __u8 value) 358 __u8 value)
358{ 359{
@@ -369,23 +370,27 @@ static void reg_w(struct gspca_dev *gspca_dev,
369 PDEBUG(D_ERR, "reg_w(): " 370 PDEBUG(D_ERR, "reg_w(): "
370 "Failed to write register to index 0x%x, value 0x%x, error %i", 371 "Failed to write register to index 0x%x, value 0x%x, error %i",
371 index, value, ret); 372 index, value, ret);
373 return ret;
372} 374}
373 375
374static void reg_w_seq(struct gspca_dev *gspca_dev, 376static int reg_w_seq(struct gspca_dev *gspca_dev,
375 const __u8 *seq, int len) 377 const __u8 *seq, int len)
376{ 378{
379 int ret = 0;
377 while (--len >= 0) { 380 while (--len >= 0) {
378 reg_w(gspca_dev, seq[0], seq[1]); 381 if (0 <= ret)
382 ret = reg_w(gspca_dev, seq[0], seq[1]);
379 seq += 2; 383 seq += 2;
380 } 384 }
385 return ret;
381} 386}
382 387
383/* load the beginning of a page */ 388/* load the beginning of a page */
384static void reg_w_page(struct gspca_dev *gspca_dev, 389static int reg_w_page(struct gspca_dev *gspca_dev,
385 const __u8 *page, int len) 390 const __u8 *page, int len)
386{ 391{
387 int index; 392 int index;
388 int ret; 393 int ret = 0;
389 394
390 for (index = 0; index < len; index++) { 395 for (index = 0; index < len; index++) {
391 if (page[index] == SKIP) /* skip this index */ 396 if (page[index] == SKIP) /* skip this index */
@@ -397,52 +402,61 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
397 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 402 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
398 0, index, gspca_dev->usb_buf, 1, 403 0, index, gspca_dev->usb_buf, 1,
399 500); 404 500);
400 if (ret < 0) 405 if (ret < 0) {
401 PDEBUG(D_ERR, "reg_w_page(): " 406 PDEBUG(D_ERR, "reg_w_page(): "
402 "Failed to write register to index 0x%x, " 407 "Failed to write register to index 0x%x, "
403 "value 0x%x, error %i", 408 "value 0x%x, error %i",
404 index, page[index], ret); 409 index, page[index], ret);
410 break;
411 }
405 } 412 }
413 return ret;
406} 414}
407 415
408/* output a variable sequence */ 416/* output a variable sequence */
409static void reg_w_var(struct gspca_dev *gspca_dev, 417static int reg_w_var(struct gspca_dev *gspca_dev,
410 const __u8 *seq, 418 const __u8 *seq,
411 const __u8 *page3, unsigned int page3_len, 419 const __u8 *page3, unsigned int page3_len,
412 const __u8 *page4, unsigned int page4_len) 420 const __u8 *page4, unsigned int page4_len)
413{ 421{
414 int index, len; 422 int index, len;
423 int ret = 0;
415 424
416 for (;;) { 425 for (;;) {
417 index = *seq++; 426 index = *seq++;
418 len = *seq++; 427 len = *seq++;
419 switch (len) { 428 switch (len) {
420 case END_OF_SEQUENCE: 429 case END_OF_SEQUENCE:
421 return; 430 return ret;
422 case LOAD_PAGE4: 431 case LOAD_PAGE4:
423 reg_w_page(gspca_dev, page4, page4_len); 432 ret = reg_w_page(gspca_dev, page4, page4_len);
424 break; 433 break;
425 case LOAD_PAGE3: 434 case LOAD_PAGE3:
426 reg_w_page(gspca_dev, page3, page3_len); 435 ret = reg_w_page(gspca_dev, page3, page3_len);
427 break; 436 break;
428 default: 437 default:
429 if (len > USB_BUF_SZ) { 438 if (len > USB_BUF_SZ) {
430 PDEBUG(D_ERR|D_STREAM, 439 PDEBUG(D_ERR|D_STREAM,
431 "Incorrect variable sequence"); 440 "Incorrect variable sequence");
432 return; 441 return -EINVAL;
433 } 442 }
434 while (len > 0) { 443 while (len > 0) {
435 if (len < 8) { 444 if (len < 8) {
436 reg_w_buf(gspca_dev, index, seq, len); 445 ret = reg_w_buf(gspca_dev,
446 index, seq, len);
447 if (ret < 0)
448 return ret;
437 seq += len; 449 seq += len;
438 break; 450 break;
439 } 451 }
440 reg_w_buf(gspca_dev, index, seq, 8); 452 ret = reg_w_buf(gspca_dev, index, seq, 8);
441 seq += 8; 453 seq += 8;
442 index += 8; 454 index += 8;
443 len -= 8; 455 len -= 8;
444 } 456 }
445 } 457 }
458 if (ret < 0)
459 return ret;
446 } 460 }
447 /* not reached */ 461 /* not reached */
448} 462}
@@ -472,10 +486,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
472} 486}
473 487
474/* This function is used by pac7302 only */ 488/* This function is used by pac7302 only */
475static void setbrightcont(struct gspca_dev *gspca_dev) 489static int setbrightcont(struct gspca_dev *gspca_dev)
476{ 490{
477 struct sd *sd = (struct sd *) gspca_dev; 491 struct sd *sd = (struct sd *) gspca_dev;
478 int i, v; 492 int i, v;
493 int ret;
479 static const __u8 max[10] = 494 static const __u8 max[10] =
480 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, 495 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
481 0xd4, 0xec}; 496 0xd4, 0xec};
@@ -483,7 +498,7 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
483 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, 498 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
484 0x11, 0x0b}; 499 0x11, 0x0b};
485 500
486 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 501 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
487 for (i = 0; i < 10; i++) { 502 for (i = 0; i < 10; i++) {
488 v = max[i]; 503 v = max[i];
489 v += (sd->brightness - BRIGHTNESS_MAX) 504 v += (sd->brightness - BRIGHTNESS_MAX)
@@ -493,47 +508,62 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
493 v = 0; 508 v = 0;
494 else if (v > 0xff) 509 else if (v > 0xff)
495 v = 0xff; 510 v = 0xff;
496 reg_w(gspca_dev, 0xa2 + i, v); 511 if (0 <= ret)
512 ret = reg_w(gspca_dev, 0xa2 + i, v);
497 } 513 }
498 reg_w(gspca_dev, 0xdc, 0x01); 514 if (0 <= ret)
515 ret = reg_w(gspca_dev, 0xdc, 0x01);
516 return ret;
499} 517}
500 518
501/* This function is used by pac7302 only */ 519/* This function is used by pac7302 only */
502static void setcolors(struct gspca_dev *gspca_dev) 520static int setcolors(struct gspca_dev *gspca_dev)
503{ 521{
504 struct sd *sd = (struct sd *) gspca_dev; 522 struct sd *sd = (struct sd *) gspca_dev;
505 int i, v; 523 int i, v;
524 int ret;
506 static const int a[9] = 525 static const int a[9] =
507 {217, -212, 0, -101, 170, -67, -38, -315, 355}; 526 {217, -212, 0, -101, 170, -67, -38, -315, 355};
508 static const int b[9] = 527 static const int b[9] =
509 {19, 106, 0, 19, 106, 1, 19, 106, 1}; 528 {19, 106, 0, 19, 106, 1, 19, 106, 1};
510 529
511 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 530 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
512 reg_w(gspca_dev, 0x11, 0x01); 531 if (0 <= ret)
513 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 532 ret = reg_w(gspca_dev, 0x11, 0x01);
533 if (0 <= ret)
534 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
514 for (i = 0; i < 9; i++) { 535 for (i = 0; i < 9; i++) {
515 v = a[i] * sd->colors / COLOR_MAX + b[i]; 536 v = a[i] * sd->colors / COLOR_MAX + b[i];
516 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); 537 if (0 <= ret)
517 reg_w(gspca_dev, 0x0f + 2 * i + 1, v); 538 ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
539 if (0 <= ret)
540 ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
518 } 541 }
519 reg_w(gspca_dev, 0xdc, 0x01); 542 if (0 <= ret)
543 ret = reg_w(gspca_dev, 0xdc, 0x01);
520 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); 544 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
545 return ret;
521} 546}
522 547
523static void setgain(struct gspca_dev *gspca_dev) 548static int setgain(struct gspca_dev *gspca_dev)
524{ 549{
525 struct sd *sd = (struct sd *) gspca_dev; 550 struct sd *sd = (struct sd *) gspca_dev;
551 int ret;
526 552
527 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 553 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
528 reg_w(gspca_dev, 0x10, sd->gain >> 3); 554 if (0 <= ret)
555 ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
529 556
530 /* load registers to sensor (Bit 0, auto clear) */ 557 /* load registers to sensor (Bit 0, auto clear) */
531 reg_w(gspca_dev, 0x11, 0x01); 558 if (0 <= ret)
559 ret = reg_w(gspca_dev, 0x11, 0x01);
560 return ret;
532} 561}
533 562
534static void setexposure(struct gspca_dev *gspca_dev) 563static int setexposure(struct gspca_dev *gspca_dev)
535{ 564{
536 struct sd *sd = (struct sd *) gspca_dev; 565 struct sd *sd = (struct sd *) gspca_dev;
566 int ret;
537 __u8 reg; 567 __u8 reg;
538 568
539 /* register 2 of frame 3/4 contains the clock divider configuring the 569 /* register 2 of frame 3/4 contains the clock divider configuring the
@@ -549,47 +579,58 @@ static void setexposure(struct gspca_dev *gspca_dev)
549 the nearest multiple of 3, except when between 6 and 12? */ 579 the nearest multiple of 3, except when between 6 and 12? */
550 if (reg < 6 || reg > 12) 580 if (reg < 6 || reg > 12)
551 reg = ((reg + 1) / 3) * 3; 581 reg = ((reg + 1) / 3) * 3;
552 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 582 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
553 reg_w(gspca_dev, 0x02, reg); 583 if (0 <= ret)
584 ret = reg_w(gspca_dev, 0x02, reg);
554 585
555 /* load registers to sensor (Bit 0, auto clear) */ 586 /* load registers to sensor (Bit 0, auto clear) */
556 reg_w(gspca_dev, 0x11, 0x01); 587 if (0 <= ret)
588 ret = reg_w(gspca_dev, 0x11, 0x01);
589 return ret;
557} 590}
558 591
559static void sethvflip(struct gspca_dev *gspca_dev) 592static int sethvflip(struct gspca_dev *gspca_dev)
560{ 593{
561 struct sd *sd = (struct sd *) gspca_dev; 594 struct sd *sd = (struct sd *) gspca_dev;
595 int ret;
562 __u8 data; 596 __u8 data;
563 597
564 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 598 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
565 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); 599 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
566 reg_w(gspca_dev, 0x21, data); 600 if (0 <= ret)
601 ret = reg_w(gspca_dev, 0x21, data);
567 /* load registers to sensor (Bit 0, auto clear) */ 602 /* load registers to sensor (Bit 0, auto clear) */
568 reg_w(gspca_dev, 0x11, 0x01); 603 if (0 <= ret)
604 ret = reg_w(gspca_dev, 0x11, 0x01);
605 return ret;
569} 606}
570 607
571/* this function is called at probe and resume time for pac7302 */ 608/* this function is called at probe and resume time for pac7302 */
572static int sd_init(struct gspca_dev *gspca_dev) 609static int sd_init(struct gspca_dev *gspca_dev)
573{ 610{
574 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); 611 return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
575
576 return 0;
577} 612}
578 613
579static int sd_start(struct gspca_dev *gspca_dev) 614static int sd_start(struct gspca_dev *gspca_dev)
580{ 615{
581 struct sd *sd = (struct sd *) gspca_dev; 616 struct sd *sd = (struct sd *) gspca_dev;
617 int ret = 0;
582 618
583 sd->sof_read = 0; 619 sd->sof_read = 0;
584 620
585 reg_w_var(gspca_dev, start_7302, 621 ret = reg_w_var(gspca_dev, start_7302,
586 page3_7302, sizeof(page3_7302), 622 page3_7302, sizeof(page3_7302),
587 NULL, 0); 623 NULL, 0);
588 setbrightcont(gspca_dev); 624 if (0 <= ret)
589 setcolors(gspca_dev); 625 ret = setbrightcont(gspca_dev);
590 setgain(gspca_dev); 626 if (0 <= ret)
591 setexposure(gspca_dev); 627 ret = setcolors(gspca_dev);
592 sethvflip(gspca_dev); 628 if (0 <= ret)
629 setgain(gspca_dev);
630 if (0 <= ret)
631 setexposure(gspca_dev);
632 if (0 <= ret)
633 sethvflip(gspca_dev);
593 634
594 /* only resolution 640x480 is supported for pac7302 */ 635 /* only resolution 640x480 is supported for pac7302 */
595 636
@@ -598,26 +639,34 @@ static int sd_start(struct gspca_dev *gspca_dev)
598 atomic_set(&sd->avg_lum, -1); 639 atomic_set(&sd->avg_lum, -1);
599 640
600 /* start stream */ 641 /* start stream */
601 reg_w(gspca_dev, 0xff, 0x01); 642 if (0 <= ret)
602 reg_w(gspca_dev, 0x78, 0x01); 643 ret = reg_w(gspca_dev, 0xff, 0x01);
644 if (0 <= ret)
645 ret = reg_w(gspca_dev, 0x78, 0x01);
603 646
604 return 0; 647 return ret;
605} 648}
606 649
607static void sd_stopN(struct gspca_dev *gspca_dev) 650static void sd_stopN(struct gspca_dev *gspca_dev)
608{ 651{
652 int ret;
653
609 /* stop stream */ 654 /* stop stream */
610 reg_w(gspca_dev, 0xff, 0x01); 655 ret = reg_w(gspca_dev, 0xff, 0x01);
611 reg_w(gspca_dev, 0x78, 0x00); 656 if (0 <= ret)
657 ret = reg_w(gspca_dev, 0x78, 0x00);
612} 658}
613 659
614/* called on streamoff with alt 0 and on disconnect for pac7302 */ 660/* called on streamoff with alt 0 and on disconnect for pac7302 */
615static void sd_stop0(struct gspca_dev *gspca_dev) 661static void sd_stop0(struct gspca_dev *gspca_dev)
616{ 662{
663 int ret;
664
617 if (!gspca_dev->present) 665 if (!gspca_dev->present)
618 return; 666 return;
619 reg_w(gspca_dev, 0xff, 0x01); 667 ret = reg_w(gspca_dev, 0xff, 0x01);
620 reg_w(gspca_dev, 0x78, 0x40); 668 if (0 <= ret)
669 ret = reg_w(gspca_dev, 0x78, 0x40);
621} 670}
622 671
623/* Include pac common sof detection functions */ 672/* Include pac common sof detection functions */