patch-2.3.15 linux/drivers/usb/cpia.c
Next file: linux/drivers/usb/cpia.h
Previous file: linux/drivers/usb/audio.c
Back to the patch index
Back to the overall index
- Lines: 240
- Date:
Wed Aug 25 15:03:54 1999
- Orig file:
v2.3.14/linux/drivers/usb/cpia.c
- Orig date:
Fri Jul 30 12:31:45 1999
diff -u --recursive --new-file v2.3.14/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
@@ -1,11 +1,12 @@
/*
* USB CPiA Video Camera driver
*
- * Supports CPiA based Video Camera's. Many manufacturers use this chipset.
+ * Supports CPiA based Video Cameras. Many manufacturers use this chipset.
* There's a good chance, if you have a USB video camera, it's a CPiA based
- * one
+ * one.
*
* (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
*/
#include <linux/kernel.h>
@@ -453,6 +454,31 @@
cpia->scratchlen = l;
}
+/*
+ * For the moment there is no actual data compression (making blocks
+ * of data contiguous). This just checks the "frames" array for errors.
+ */
+static int cpia_compress_isochronous(struct usb_isoc_desc *isodesc)
+{
+ char *data = isodesc->data;
+ int i, totlen = 0;
+
+ for (i = 0; i < isodesc->frame_count; i++) {
+ int n = isodesc->frames [i].frame_length;
+ int st = isodesc->frames [i].frame_status;
+
+#ifdef CPIA_DEBUG
+ /* Debugging */
+ if (st)
+ printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n",
+ i, n, st);
+#endif
+
+ }
+
+ return totlen;
+}
+
static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id)
{
struct usb_cpia *cpia = dev_id;
@@ -489,10 +515,10 @@
sbuf = &cpia->sbuf[cpia->receivesbuf];
- usb_unschedule_isochronous(dev, sbuf->isodesc);
+ usb_kill_isoc(sbuf->isodesc);
/* Do something to it now */
- sbuf->len = usb_compress_isochronous(dev, sbuf->isodesc);
+ sbuf->len = cpia_compress_isochronous(sbuf->isodesc);
#ifdef CPIA_DEBUG
if (sbuf->len)
@@ -511,7 +537,12 @@
}
/* Reschedule this block of Isochronous desc */
+ /*
+ usb_run_isoc(sbuf->isodesc, NULL);
+ */
+/*
usb_schedule_isochronous(dev, sbuf->isodesc, cpia->sbuf[(cpia->receivesbuf + 2) % 3].isodesc);
+*/
/* Move to the next one */
cpia->receivesbuf = (cpia->receivesbuf + 1) % 3;
@@ -522,6 +553,8 @@
int cpia_init_isoc(struct usb_cpia *cpia)
{
struct usb_device *dev = cpia->dev;
+ struct usb_isoc_desc *id;
+ int fx, err;
cpia->receivesbuf = 0;
@@ -529,21 +562,66 @@
cpia->curline = 0;
cpia->state = STATE_SCANNING;
- /* Allocate all of the memory necessary */
+ /* ALT_ISOC is only doing double-buffering, not triple. */
+ err = usb_init_isoc (dev, usb_rcvisocpipe (dev, 1), FRAMES_PER_DESC, cpia,
+ &cpia->sbuf[0].isodesc);
+ if (err)
+ printk ("cpia_init_isoc: usb_init_isoc() ret. %d\n", err);
+ err = usb_init_isoc (dev, usb_rcvisocpipe (dev, 1), FRAMES_PER_DESC, cpia,
+ &cpia->sbuf[1].isodesc);
+ if (err)
+ printk ("cpia_init_isoc: usb_init_isoc() ret. %d\n", err);
+
+ if (!cpia->sbuf[0].isodesc || !cpia->sbuf[1].isodesc) {
+ if (cpia->sbuf[0].isodesc)
+ usb_free_isoc (cpia->sbuf[0].isodesc);
+ if (cpia->sbuf[1].isodesc)
+ usb_free_isoc (cpia->sbuf[1].isodesc);
+ return -ENOMEM;
+ }
+#if 0
cpia->sbuf[0].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[0].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
cpia->sbuf[1].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
cpia->sbuf[2].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
+#endif
#ifdef CPIA_DEBUG
printk("isodesc[0] @ %p\n", cpia->sbuf[0].isodesc);
printk("isodesc[1] @ %p\n", cpia->sbuf[1].isodesc);
+#if 0
printk("isodesc[2] @ %p\n", cpia->sbuf[2].isodesc);
#endif
+#endif
+
+ /* Set the Isoc. desc. parameters. */
+ /* First for desc. [0] */
+ id = cpia->sbuf [0].isodesc;
+ id->start_type = START_ASAP;
+ id->callback_frames = 1; /* on every frame */
+ id->callback_fn = cpia_isoc_irq;
+ id->data = cpia->sbuf [0].data;
+ id->buf_size = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
+ for (fx = 0; fx < FRAMES_PER_DESC; fx++)
+ id->frames [fx].frame_length = FRAME_SIZE_PER_DESC;
+
+ /* and the desc. [1] */
+ id = cpia->sbuf [1].isodesc;
+ id->start_type = 0; /* will follow the first desc. */
+ id->callback_frames = 1; /* on every frame */
+ id->callback_fn = cpia_isoc_irq;
+ id->data = cpia->sbuf [1].data;
+ id->buf_size = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
+ for (fx = 0; fx < FRAMES_PER_DESC; fx++)
+ id->frames [fx].frame_length = FRAME_SIZE_PER_DESC;
+
+ usb_run_isoc (cpia->sbuf [0].isodesc, NULL);
+ usb_run_isoc (cpia->sbuf [1].isodesc, cpia->sbuf [0].isodesc);
- /* Schedule the queues */
+#if 0
usb_schedule_isochronous(dev, cpia->sbuf[0].isodesc, NULL);
usb_schedule_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc);
usb_schedule_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc);
+#endif
#ifdef CPIA_DEBUG
printk("done scheduling\n");
@@ -582,19 +660,28 @@
}
/* Unschedule all of the iso td's */
+ usb_kill_isoc (cpia->sbuf[1].isodesc);
+ usb_kill_isoc (cpia->sbuf[0].isodesc);
+#if 0
usb_unschedule_isochronous(dev, cpia->sbuf[2].isodesc);
usb_unschedule_isochronous(dev, cpia->sbuf[1].isodesc);
usb_unschedule_isochronous(dev, cpia->sbuf[0].isodesc);
+#endif
/* Delete them all */
+ usb_free_isoc (cpia->sbuf[1].isodesc);
+ usb_free_isoc (cpia->sbuf[0].isodesc);
+#if 0
usb_delete_isochronous(dev, cpia->sbuf[2].isodesc);
usb_delete_isochronous(dev, cpia->sbuf[1].isodesc);
usb_delete_isochronous(dev, cpia->sbuf[0].isodesc);
+#endif
}
/* Video 4 Linux API */
static int cpia_open(struct video_device *dev, int flags)
{
+ int err = -ENOMEM;
struct usb_cpia *cpia = (struct usb_cpia *)dev;
#ifdef CPIA_DEBUG
@@ -615,6 +702,15 @@
printk("frame [1] @ %p\n", cpia->frame[1].data);
#endif
+ cpia->sbuf[0].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+ if (!cpia->sbuf[0].data)
+ goto open_err_on0;
+
+ cpia->sbuf[1].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+ if (!cpia->sbuf[1].data)
+ goto open_err_on1;
+
+#if 0
cpia->sbuf[0].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
if (!cpia->sbuf[0].data)
goto open_err_on0;
@@ -626,19 +722,24 @@
cpia->sbuf[2].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
if (!cpia->sbuf[2].data)
goto open_err_on2;
+#endif
#ifdef CPIA_DEBUG
printk("sbuf[0] @ %p\n", cpia->sbuf[0].data);
printk("sbuf[1] @ %p\n", cpia->sbuf[1].data);
+#if 0
printk("sbuf[2] @ %p\n", cpia->sbuf[2].data);
#endif
+#endif
cpia->curframe = -1;
cpia->receivesbuf = 0;
usb_cpia_initstreamcap(cpia->dev, 0, 60);
- cpia_init_isoc(cpia);
+ err = cpia_init_isoc(cpia);
+ if (err)
+ goto open_err_on2;
return 0;
@@ -649,7 +750,7 @@
open_err_on0:
rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE);
open_err_ret:
- return -ENOMEM;
+ return err;
}
static void cpia_close(struct video_device *dev)
@@ -1083,7 +1184,7 @@
if (dev->descriptor.bNumConfigurations != 1)
return -1;
- interface = &dev->config[0].altsetting[0].interface[0];
+ interface = &dev->config[0].interface[0].altsetting[0];
/* Is it a CPiA? */
if (dev->descriptor.idVendor != 0x0553)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)