Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f53b0b0 authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab
Browse files

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: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 1852e75a
Loading
Loading
Loading
Loading
+37 −18
Original line number Diff line number Diff line
@@ -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. */
		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;
	for (;;) {
		PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
	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);
		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) {
			if (ret < 0)
				break;
		}
		if (ret >= 0)
			break;
		PDEBUG(D_ERR|D_STREAM,
					"usb_submit_urb [%d] err %d", n, ret);
			"usb_submit_urb alt %d err %d", gspca_dev->alt, ret);
		gspca_dev->streaming = 0;
		destroy_urbs(gspca_dev);
				if (ret == -ENOSPC) {
					msleep(20);	/* wait for kill
							 * complete */
					break;	/* try the previous alt */
				}
		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;
			}
		}
		if (ret >= 0)
			break;
	}
out:
	mutex_unlock(&gspca_dev->usb_lock);
+4 −1
Original line number Diff line number Diff line
@@ -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,