mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-15 15:15:47 +00:00
V4L/DVB (12229): gspca - main: Change the ISOC initialization mechanism.
- call a new subdriver function 'isoc_init' before chosing the first alternate setting. - call a new subdriver function 'isoc_nego' when submitting the URBs failed. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
1852e75a55
commit
1f53b0b010
2 changed files with 41 additions and 19 deletions
|
@ -512,7 +512,10 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
|||
if (!gspca_dev->cam.bulk) { /* isoc */
|
||||
|
||||
/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
|
||||
psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
|
||||
if (gspca_dev->pkt_size == 0)
|
||||
psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
|
||||
else
|
||||
psize = gspca_dev->pkt_size;
|
||||
npkt = gspca_dev->cam.npkt;
|
||||
if (npkt == 0)
|
||||
npkt = 32; /* default value */
|
||||
|
@ -597,13 +600,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
|||
/* set the higher alternate setting and
|
||||
* loop until urb submit succeeds */
|
||||
gspca_dev->alt = gspca_dev->nbalt;
|
||||
if (gspca_dev->sd_desc->isoc_init) {
|
||||
ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
ep = get_ep(gspca_dev);
|
||||
if (ep == NULL) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
for (;;) {
|
||||
PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
|
||||
ep = get_ep(gspca_dev);
|
||||
if (ep == NULL) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ret = create_urbs(gspca_dev, ep);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -628,21 +636,32 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
|||
/* submit the URBs */
|
||||
for (n = 0; n < gspca_dev->nurbs; n++) {
|
||||
ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR|D_STREAM,
|
||||
"usb_submit_urb [%d] err %d", n, ret);
|
||||
gspca_dev->streaming = 0;
|
||||
destroy_urbs(gspca_dev);
|
||||
if (ret == -ENOSPC) {
|
||||
msleep(20); /* wait for kill
|
||||
* complete */
|
||||
break; /* try the previous alt */
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
break;
|
||||
PDEBUG(D_ERR|D_STREAM,
|
||||
"usb_submit_urb alt %d err %d", gspca_dev->alt, ret);
|
||||
gspca_dev->streaming = 0;
|
||||
destroy_urbs(gspca_dev);
|
||||
if (ret != -ENOSPC)
|
||||
goto out;
|
||||
|
||||
/* the bandwidth is not wide enough
|
||||
* negociate or try a lower alternate setting */
|
||||
msleep(20); /* wait for kill complete */
|
||||
if (gspca_dev->sd_desc->isoc_nego) {
|
||||
ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} else {
|
||||
ep = get_ep(gspca_dev);
|
||||
if (ep == NULL) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&gspca_dev->usb_lock);
|
||||
|
|
|
@ -98,9 +98,11 @@ struct sd_desc {
|
|||
/* mandatory operations */
|
||||
cam_cf_op config; /* called on probe */
|
||||
cam_op init; /* called on probe and resume */
|
||||
cam_op start; /* called on stream on */
|
||||
cam_op start; /* called on stream on after URBs creation */
|
||||
cam_pkt_op pkt_scan;
|
||||
/* optional operations */
|
||||
cam_op isoc_init; /* called on stream on before getting the EP */
|
||||
cam_op isoc_nego; /* called when URB submit failed with NOSPC */
|
||||
cam_v_op stopN; /* called on stream off - main alt */
|
||||
cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
|
||||
cam_v_op dq_callback; /* called when a frame has been dequeued */
|
||||
|
@ -178,6 +180,7 @@ struct gspca_dev {
|
|||
__u8 iface; /* USB interface number */
|
||||
__u8 alt; /* USB alternate setting */
|
||||
__u8 nbalt; /* number of USB alternate settings */
|
||||
u16 pkt_size; /* ISOC packet size */
|
||||
};
|
||||
|
||||
int gspca_dev_probe(struct usb_interface *intf,
|
||||
|
|
Loading…
Reference in a new issue