Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (9087): gspca: Image transfer by bulk uses altsetting 0 with any buffer size.

- gspca_dev field 'bulk_size' added.
- when only one altsetting usable, do image transfer by bulk.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Jean-Francois Moine and committed by
Mauro Carvalho Chehab
95d9142c 6b060ffe

+28 -16
+27 -15
drivers/media/video/gspca/gspca.c
··· 461 461 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); 462 462 ep = NULL; 463 463 i = gspca_dev->alt; /* previous alt setting */ 464 + 465 + /* try isoc */ 464 466 while (--i > 0) { /* alt 0 is unusable */ 465 467 ep = alt_xfer(&intf->altsetting[i], 466 468 gspca_dev->cam.epaddr, 467 - gspca_dev->bulk 468 - ? USB_ENDPOINT_XFER_BULK 469 - : USB_ENDPOINT_XFER_ISOC); 469 + USB_ENDPOINT_XFER_ISOC); 470 470 if (ep) 471 471 break; 472 472 } 473 + 474 + /* if no isoc, try bulk */ 473 475 if (ep == NULL) { 474 - err("no transfer endpoint found"); 475 - return NULL; 476 + ep = alt_xfer(&intf->altsetting[0], 477 + gspca_dev->cam.epaddr, 478 + USB_ENDPOINT_XFER_BULK); 479 + if (ep == NULL) { 480 + err("no transfer endpoint found"); 481 + return NULL; 482 + } 476 483 } 477 484 PDEBUG(D_STREAM, "use alt %d ep 0x%02x", 478 485 i, ep->desc.bEndpointAddress); 479 - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); 480 - if (ret < 0) { 481 - err("set interface err %d", ret); 482 - return NULL; 486 + if (i > 0) { 487 + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); 488 + if (ret < 0) { 489 + err("set interface err %d", ret); 490 + return NULL; 491 + } 483 492 } 484 493 gspca_dev->alt = i; /* memorize the current alt setting */ 485 494 return ep; ··· 506 497 /* calculate the packet size and the number of packets */ 507 498 psize = le16_to_cpu(ep->desc.wMaxPacketSize); 508 499 509 - /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ 510 - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); 511 - if (!gspca_dev->bulk) { 500 + if (gspca_dev->alt != 0) { /* isoc */ 501 + 502 + /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ 503 + psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); 512 504 npkt = ISO_MAX_SIZE / psize; 513 505 if (npkt > ISO_MAX_PKT) 514 506 npkt = ISO_MAX_PKT; ··· 518 508 "isoc %d pkts size %d = bsize:%d", 519 509 npkt, psize, bsize); 520 510 nurbs = DEF_NURBS; 521 - } else { 511 + } else { /* bulk */ 522 512 npkt = 0; 523 - bsize = psize; 513 + bsize = gspca_dev->cam. bulk_size; 514 + if (bsize == 0) 515 + bsize = psize; 524 516 PDEBUG(D_STREAM, "bulk bsize:%d", bsize); 525 517 nurbs = 1; 526 518 } ··· 607 595 atomic_set(&gspca_dev->nevent, 0); 608 596 609 597 /* bulk transfers are started by the subdriver */ 610 - if (gspca_dev->bulk) 598 + if (gspca_dev->alt == 0) 611 599 break; 612 600 613 601 /* submit the URBs */
+1 -1
drivers/media/video/gspca/gspca.h
··· 56 56 57 57 /* device information - set at probe time */ 58 58 struct cam { 59 + int bulk_size; /* buffer size when image transfer by bulk */ 59 60 struct v4l2_pix_format *cam_mode; /* size nmodes */ 60 61 char nmodes; 61 62 __u8 epaddr; ··· 145 144 146 145 __u8 iface; /* USB interface number */ 147 146 __u8 alt; /* USB alternate setting */ 148 - __u8 bulk; /* image transfer by isoc (0) or bulk (1) */ 149 147 __u8 curr_mode; /* current camera mode */ 150 148 __u32 pixfmt; /* current mode parameters */ 151 149 __u16 width;