@@ -525,6 +525,9 @@
/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+ /* Variable packet size overriding alt setting ? */
+ if (gspca_dev->isoc_pkt_sz)
+ psize = gspca_dev->isoc_pkt_sz;
npkt = gspca_dev->cam.npkt;
if (npkt == 0)
npkt = 32; /* default value */
@@ -595,6 +598,7 @@
*/
static int gspca_init_transfer(struct gspca_dev *gspca_dev)
{
+ struct cam *cam = &gspca_dev->cam;
struct usb_host_endpoint *ep;
int n, ret;
@@ -609,9 +613,9 @@
/* set the higher alternate setting and
* loop until urb submit succeeds */
gspca_dev->alt = gspca_dev->nbalt;
+ gspca_dev->isoc_pkt_sz = cam->max_isoc_pkt_sz;
+ ep = get_ep(gspca_dev);
for (;;) {
- PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
- ep = get_ep(gspca_dev);
if (ep == NULL) {
ret = -EIO;
goto out;
@@ -648,7 +652,17 @@
if (ret == -ENOSPC) {
msleep(20); /* wait for kill
* complete */
- break; /* try the previous alt */
+ if (gspca_dev->isoc_pkt_sz) {
+ /* Try smaller packet size */
+ gspca_dev->isoc_pkt_sz -= 100;
+ if (gspca_dev->isoc_pkt_sz <
+ cam->min_isoc_pkt_sz)
+ goto out;
+ } else {
+ /* try the previous alt */
+ ep = get_ep(gspca_dev);
+ }
+ break;
}
goto out;
}
@@ -57,6 +57,12 @@
u8 bulk; /* image transfer by 0:isoc / 1:bulk */
u8 npkt; /* number of packets in an ISOC message
* 0 is the default value: 32 packets */
+ /* min / max isoc packet size for camera's which have a variable
+ packet size, when this is the case BOTH must be set to a non zero
+ value, the wMaxPacketSize of the alsetting will be ignored and the
+ highest alt setting will be used */
+ int min_isoc_pkt_sz;
+ int max_isoc_pkt_sz;
u32 input_flags; /* value for ENUM_INPUT status flags */
};
@@ -135,6 +141,7 @@
#define USB_BUF_SZ 64
__u8 *usb_buf; /* buffer for USB exchanges */
struct urb *urb[MAX_NURBS];
+ int isoc_pkt_sz; /* variable isoc packet size */
__u8 *frbuf; /* buffer for nframes */
struct gspca_frame frame[GSPCA_MAX_FRAMES];
@@ -133,6 +133,9 @@
sd->gspca_dev.cam.cam_mode = st6422_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+ sd->gspca_dev.cam.min_isoc_pkt_sz = 460;
+ sd->gspca_dev.cam.max_isoc_pkt_sz = 960;
+ sd->gspca_dev.cam.npkt = 10;
sd->desc.ctrls = st6422_ctrl;
sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
sd->sensor_priv = sensor_settings;
@@ -238,21 +241,11 @@
static int st6422_start(struct sd *sd)
{
- int err, packet_size;
+ int err;
struct cam *cam = &sd->gspca_dev.cam;
s32 *sensor_settings = sd->sensor_priv;
- struct usb_host_interface *alt;
- struct usb_interface *intf;
- intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
- alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
- if (!alt) {
- PDEBUG(D_ERR, "Couldn't get altsetting");
- return -EIO;
- }
-
- packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
- err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
+ err = stv06xx_write_bridge(sd, 0x15c1, sd->gspca_dev.isoc_pkt_sz);
if (err < 0)
return err;