extractedLnx/linux-2.6.38/drivers/staging/easycap/easycap_main.c_easycap_complete.c
void
easycap_complete(struct urb *purb)
{
struct easycap *peasycap;
struct data_buffer *pfield_buffer;
char errbuf[16];
int i, more, much, leap, rc, last;
int videofieldamount;
unsigned int override, bad;
int framestatus, framelength, frameactual, frameoffset;
__u8 *pu;
if (NULL == purb) {
SAY("ERROR: easycap_complete(): purb is NULL\n");
return;
}
peasycap = purb->context;
if (NULL == peasycap) {
SAY("ERROR: easycap_complete(): peasycap is NULL\n");
return;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
return;
}
if (peasycap->video_eof)
return;
for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
break;
JOM(16, "%2i=urb\n", i);
last = peasycap->video_isoc_sequence;
if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \
(0 != i)) || \
(((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \
((last + 1) != i))) {
JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
}
peasycap->video_isoc_sequence = i;
if (peasycap->video_idle) {
JOM(16, "%i=video_idle %i=video_isoc_streaming\n", \
peasycap->video_idle, peasycap->video_isoc_streaming);
if (peasycap->video_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
switch (rc) {
case -ENOMEM: {
SAM("ENOMEM\n");
break;
}
case -ENODEV: {
SAM("ENODEV\n");
break;
}
case -ENXIO: {
SAM("ENXIO\n");
break;
}
case -EINVAL: {
SAM("EINVAL\n");
break;
}
case -EAGAIN: {
SAM("EAGAIN\n");
break;
}
case -EFBIG: {
SAM("EFBIG\n");
break;
}
case -EPIPE: {
SAM("EPIPE\n");
break;
}
case -EMSGSIZE: {
SAM("EMSGSIZE\n");
break;
}
case -ENOSPC: {
SAM("ENOSPC\n");
break;
}
default: {
SAM("0x%08X\n", rc);
break;
}
}
if (-ENODEV != rc) \
SAM("ERROR: while %i=video_idle, " \
"usb_submit_urb() " \
"failed with rc:\n", \
peasycap->video_idle);
}
}
return;
}
override = 0;
/*---------------------------------------------------------------------------*/
if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
SAM("ERROR: bad peasycap->field_fill\n");
return;
}
if (purb->status) {
if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
return;
}
(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
SAM("ERROR: bad urb status:\n");
switch (purb->status) {
case -EINPROGRESS: {
SAM("-EINPROGRESS\n"); break;
}
case -ENOSR: {
SAM("-ENOSR\n"); break;
}
case -EPIPE: {
SAM("-EPIPE\n"); break;
}
case -EOVERFLOW: {
SAM("-EOVERFLOW\n"); break;
}
case -EPROTO: {
SAM("-EPROTO\n"); break;
}
case -EILSEQ: {
SAM("-EILSEQ\n"); break;
}
case -ETIMEDOUT: {
SAM("-ETIMEDOUT\n"); break;
}
case -EMSGSIZE: {
SAM("-EMSGSIZE\n"); break;
}
case -EOPNOTSUPP: {
SAM("-EOPNOTSUPP\n"); break;
}
case -EPFNOSUPPORT: {
SAM("-EPFNOSUPPORT\n"); break;
}
case -EAFNOSUPPORT: {
SAM("-EAFNOSUPPORT\n"); break;
}
case -EADDRINUSE: {
SAM("-EADDRINUSE\n"); break;
}
case -EADDRNOTAVAIL: {
SAM("-EADDRNOTAVAIL\n"); break;
}
case -ENOBUFS: {
SAM("-ENOBUFS\n"); break;
}
case -EISCONN: {
SAM("-EISCONN\n"); break;
}
case -ENOTCONN: {
SAM("-ENOTCONN\n"); break;
}
case -ESHUTDOWN: {
SAM("-ESHUTDOWN\n"); break;
}
case -ENOENT: {
SAM("-ENOENT\n"); break;
}
case -ECONNRESET: {
SAM("-ECONNRESET\n"); break;
}
case -ENOSPC: {
SAM("ENOSPC\n"); break;
}
default: {
SAM("unknown error code 0x%08X\n", purb->status); break;
}
}
/*---------------------------------------------------------------------------*/
} else {
for (i = 0; i < purb->number_of_packets; i++) {
if (0 != purb->iso_frame_desc[i].status) {
(peasycap->field_buffer\
[peasycap->field_fill][0].kount) |= 0x8000 ;
switch (purb->iso_frame_desc[i].status) {
case 0: {
strcpy(&errbuf[0], "OK"); break;
}
case -ENOENT: {
strcpy(&errbuf[0], "-ENOENT"); break;
}
case -EINPROGRESS: {
strcpy(&errbuf[0], "-EINPROGRESS"); break;
}
case -EPROTO: {
strcpy(&errbuf[0], "-EPROTO"); break;
}
case -EILSEQ: {
strcpy(&errbuf[0], "-EILSEQ"); break;
}
case -ETIME: {
strcpy(&errbuf[0], "-ETIME"); break;
}
case -ETIMEDOUT: {
strcpy(&errbuf[0], "-ETIMEDOUT"); break;
}
case -EPIPE: {
strcpy(&errbuf[0], "-EPIPE"); break;
}
case -ECOMM: {
strcpy(&errbuf[0], "-ECOMM"); break;
}
case -ENOSR: {
strcpy(&errbuf[0], "-ENOSR"); break;
}
case -EOVERFLOW: {
strcpy(&errbuf[0], "-EOVERFLOW"); break;
}
case -EREMOTEIO: {
strcpy(&errbuf[0], "-EREMOTEIO"); break;
}
case -ENODEV: {
strcpy(&errbuf[0], "-ENODEV"); break;
}
case -EXDEV: {
strcpy(&errbuf[0], "-EXDEV"); break;
}
case -EINVAL: {
strcpy(&errbuf[0], "-EINVAL"); break;
}
case -ECONNRESET: {
strcpy(&errbuf[0], "-ECONNRESET"); break;
}
case -ENOSPC: {
SAM("ENOSPC\n"); break;
}
case -ESHUTDOWN: {
strcpy(&errbuf[0], "-ESHUTDOWN"); break;
}
default: {
strcpy(&errbuf[0], "unknown error"); break;
}
}
}
framestatus = purb->iso_frame_desc[i].status;
framelength = purb->iso_frame_desc[i].length;
frameactual = purb->iso_frame_desc[i].actual_length;
frameoffset = purb->iso_frame_desc[i].offset;
JOM(16, "frame[%2i]:" \
"%4i=status " \
"%4i=actual " \
"%4i=length " \
"%5i=offset\n", \
i, framestatus, frameactual, framelength, frameoffset);
if (!purb->iso_frame_desc[i].status) {
more = purb->iso_frame_desc[i].actual_length;
pfield_buffer = &peasycap->field_buffer\
[peasycap->field_fill][peasycap->field_page];
videofieldamount = (peasycap->field_page * \
PAGE_SIZE) + \
(int)(pfield_buffer->pto - pfield_buffer->pgo);
if (4 == more)
peasycap->video_mt++;
if (4 < more) {
if (peasycap->video_mt) {
JOM(8, "%4i empty video urb frames\n", \
peasycap->video_mt);
peasycap->video_mt = 0;
}
if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
SAM("ERROR: bad peasycap->field_fill\n");
return;
}
if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
peasycap->field_page) {
SAM("ERROR: bad peasycap->field_page\n");
return;
}
pfield_buffer = &peasycap->field_buffer\
[peasycap->field_fill][peasycap->field_page];
pu = (__u8 *)(purb->transfer_buffer + \
purb->iso_frame_desc[i].offset);
if (0x80 & *pu)
leap = 8;
else
leap = 4;
/*--------------------------------------------------------------------------*/
/*
* EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
* NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
* CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
*
* PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
* BYTE OF
* peasycap->field_buffer[peasycap->field_fill][0].kount
* THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
* UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
* NOTHING IS OFFERED TO dqbuf().
*
* THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
* RESTS WITH dqbuf().
*/
/*---------------------------------------------------------------------------*/
if ((8 == more) || override) {
if (videofieldamount > \
peasycap->videofieldamount) {
if (2 == videofieldamount - \
peasycap->\
videofieldamount) {
(peasycap->field_buffer\
[peasycap->field_fill]\
[0].kount) |= 0x0100;
peasycap->video_junk += (1 + \
VIDEO_JUNK_TOLERATE);
} else
(peasycap->field_buffer\
[peasycap->field_fill]\
[0].kount) |= 0x4000;
} else if (videofieldamount < \
peasycap->\
videofieldamount) {
(peasycap->field_buffer\
[peasycap->field_fill]\
[0].kount) |= 0x2000;
}
bad = 0xFF00 & peasycap->field_buffer\
[peasycap->field_fill]\
[0].kount;
if (!bad) {
(peasycap->video_junk)--;
if (-VIDEO_JUNK_TOLERATE > \
peasycap->video_junk) \
peasycap->video_junk =\
-VIDEO_JUNK_TOLERATE;
peasycap->field_read = \
(peasycap->\
field_fill)++;
if (FIELD_BUFFER_MANY <= \
peasycap->\
field_fill)
peasycap->\
field_fill = 0;
peasycap->field_page = 0;
pfield_buffer = &peasycap->\
field_buffer\
[peasycap->\
field_fill]\
[peasycap->\
field_page];
pfield_buffer->pto = \
pfield_buffer->pgo;
JOM(8, "bumped to: %i="\
"peasycap->" \
"field_fill %i="\
"parity\n", \
peasycap->field_fill, \
0x00FF & \
pfield_buffer->kount);
JOM(8, "field buffer %i has "\
"%i bytes fit to be "\
"read\n", \
peasycap->field_read, \
videofieldamount);
JOM(8, "wakeup call to "\
"wq_video, " \
"%i=field_read "\
"%i=field_fill "\
"%i=parity\n", \
peasycap->field_read, \
peasycap->field_fill, \
0x00FF & peasycap->\
field_buffer\
[peasycap->\
field_read][0].kount);
wake_up_interruptible\
(&(peasycap->\
wq_video));
do_gettimeofday\
(&peasycap->timeval7);
} else {
peasycap->video_junk++;
if (bad & 0x0010) \
peasycap->video_junk += \
(1 + VIDEO_JUNK_TOLERATE/2);
JOM(8, "field buffer %i had %i " \
"bytes, now discarded: "\
"0x%04X\n", \
peasycap->field_fill, \
videofieldamount,\
(0xFF00 & \
peasycap->field_buffer\
[peasycap->field_fill][0].\
kount));
(peasycap->field_fill)++;
if (FIELD_BUFFER_MANY <= \
peasycap->field_fill)
peasycap->field_fill = 0;
peasycap->field_page = 0;
pfield_buffer = \
&peasycap->field_buffer\
[peasycap->field_fill]\
[peasycap->field_page];
pfield_buffer->pto = \
pfield_buffer->pgo;
JOM(8, "bumped to: %i=peasycap->" \
"field_fill %i=parity\n", \
peasycap->field_fill, \
0x00FF & pfield_buffer->kount);
}
if (8 == more) {
JOM(8, "end-of-field: received " \
"parity byte 0x%02X\n", \
(0xFF & *pu));
if (0x40 & *pu)
pfield_buffer->kount = 0x0000;
else
pfield_buffer->kount = 0x0001;
pfield_buffer->input = 0x08 | \
(0x07 & peasycap->input);
JOM(8, "end-of-field: 0x%02X=kount\n",\
0xFF & pfield_buffer->kount);
}
}
/*---------------------------------------------------------------------------*/
/*
* COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
*/
/*---------------------------------------------------------------------------*/
pu += leap;
more -= leap;
if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
SAM("ERROR: bad peasycap->field_fill\n");
return;
}
if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
peasycap->field_page) {
SAM("ERROR: bad peasycap->field_page\n");
return;
}
pfield_buffer = &peasycap->field_buffer\
[peasycap->field_fill][peasycap->field_page];
while (more) {
pfield_buffer = &peasycap->field_buffer\
[peasycap->field_fill]\
[peasycap->field_page];
if (PAGE_SIZE < (pfield_buffer->pto - \
pfield_buffer->pgo)) {
SAM("ERROR: bad pfield_buffer->pto\n");
return;
}
if (PAGE_SIZE == (pfield_buffer->pto - \
pfield_buffer->pgo)) {
(peasycap->field_page)++;
if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
peasycap->field_page) {
JOM(16, "wrapping peasycap->" \
"field_page\n");
peasycap->field_page = 0;
}
pfield_buffer = &peasycap->\
field_buffer\
[peasycap->field_fill]\
[peasycap->field_page];
pfield_buffer->pto = \
pfield_buffer->pgo;
pfield_buffer->input = 0x08 | \
(0x07 & peasycap->input);
if ((peasycap->field_buffer[peasycap->\
field_fill][0]).\
input != \
pfield_buffer->input)
(peasycap->field_buffer\
[peasycap->field_fill]\
[0]).kount |= 0x1000;
}
much = PAGE_SIZE - (int)(pfield_buffer->pto - \
pfield_buffer->pgo);
if (much > more)
much = more;
memcpy(pfield_buffer->pto, pu, much);
pu += much;
(pfield_buffer->pto) += much;
more -= much;
}
}
}
}
}
/*---------------------------------------------------------------------------*/
/*
* RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
*
* IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
* THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
*/
/*---------------------------------------------------------------------------*/
if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
SAM("easycap driver shutting down on condition green\n");
peasycap->status = 1;
peasycap->video_eof = 1;
peasycap->video_junk = 0;
wake_up_interruptible(&peasycap->wq_video);
#if !defined(PERSEVERE)
peasycap->audio_eof = 1;
wake_up_interruptible(&peasycap->wq_audio);
#endif /*PERSEVERE*/
return;
}
if (peasycap->video_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
switch (rc) {
case -ENOMEM: {
SAM("ENOMEM\n"); break;
}
case -ENODEV: {
SAM("ENODEV\n"); break;
}
case -ENXIO: {
SAM("ENXIO\n"); break;
}
case -EINVAL: {
SAM("EINVAL\n"); break;
}
case -EAGAIN: {
SAM("EAGAIN\n"); break;
}
case -EFBIG: {
SAM("EFBIG\n"); break;
}
case -EPIPE: {
SAM("EPIPE\n"); break;
}
case -EMSGSIZE: {
SAM("EMSGSIZE\n"); break;
}
case -ENOSPC: {
SAM("ENOSPC\n"); break;
}
default: {
SAM("0x%08X\n", rc); break;
}
}
if (-ENODEV != rc) \
SAM("ERROR: while %i=video_idle, " \
"usb_submit_urb() " \
"failed with rc:\n", \
peasycap->video_idle);
}
}
return;
}
Generated by GNU enscript 1.6.4.