📄 spca_core.c
字号:
} if (waitqueue_active (&taskletframe->wq)) wake_up_interruptible (&taskletframe->wq);}/* ******************************************************************* spca50x_move_data* Function serves for moving data from USB transfer buffers* to internal driver frame buffers.******************************************************************* */static intspca50x_move_data (struct usb_spca50x *spca50x, struct urb *urb){ unsigned char *cdata; //Pointer to buffer where we do store next packet unsigned char *pData; //Pointer to buffer where we do store next packet int i; struct spca50x_frame *frame; //Pointer to frame data int iPix; //Offset of pixel data in the ISO packet int totlen = 0; int tv8532 = 0; for (i = 0; i < urb->number_of_packets; i++) { int datalength = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; int sequenceNumber; int sof; /* PDEBUG(5,"Packet data [%d,%d,%d]", datalength, st, urb->iso_frame_desc[i].offset); */ urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].status = 0; cdata = ((unsigned char *) urb->transfer_buffer) + urb->iso_frame_desc[i].offset; /* Check for zero length block or no selected frame buffer */ if (!datalength || spca50x->curframe == -1) { tv8532 = 0; continue; } PDEBUG (5, "Packet data [%d,%d,%d] Status: %d", datalength, st, urb->iso_frame_desc[i].offset, st); if (st) PDEBUG (2, "data error: [%d] len=%d, status=%d", i, datalength, st); frame = &spca50x->frame[spca50x->curframe]; totlen = frame->totlength; /* read the sequence number */ if (spca50x->bridge == BRIDGE_ZC3XX || spca50x->bridge == BRIDGE_SN9CXXX ) { if (frame->last_packet == -1) { /*initialize a new frame */ sequenceNumber = 0; } else { sequenceNumber = frame->last_packet; } } else { sequenceNumber = cdata[SPCA50X_OFFSET_SEQUENCE]; PDEBUG (4, "Packet start %x %x %x %x %x", cdata[0], cdata[1], cdata[2], cdata[3], cdata[4]); } /* check frame start */ switch (spca50x->bridge) { case BRIDGE_SN9CXXX: iPix = 0; sof = datalength - 64; if (sof < 0) sequenceNumber++; else if(cdata[sof] == 0xff && cdata[sof +1] == 0xd9){ sequenceNumber = 0; //start of frame // copy the end of data frame memcpy (frame->highwater, cdata, sof+2); frame->highwater += (sof+2); totlen += (sof+2);#if 0 spin_lock(&spca50x->v4l_lock); spca50x->avg_lum = (cdata[sof+24] + cdata[sof+26]) >> 1 ; spin_unlock(&spca50x->v4l_lock); PDEBUG (5,"mean luma %d",spca50x->avg_lum );#endif PDEBUG (5, "Sonix header packet found datalength %d totlength %d!!", datalength, totlen); PDEBUG(5,"%03d %03d %03d %03d %03d %03d %03d %03d",cdata[sof+24], cdata[sof+25], cdata[sof+26] , cdata[sof+27], cdata[sof+28], cdata[sof+29], cdata[sof+30], cdata[sof+31]); // setting to skip the rest of the packet spca50x->header_len = datalength; } else sequenceNumber++; break; case BRIDGE_ZC3XX: { iPix = 0; if (cdata[0] == 0xFF && cdata[1] == 0xD8) { sequenceNumber = 0; spca50x->header_len = 2; //18 remove 0xff 0xd8; PDEBUG (5, "Zc301 header packet found datalength %d totlength %d!!", datalength, totlen); } else { sequenceNumber++; } } break; case BRIDGE_SPCA533: { iPix = 1; if (sequenceNumber == SPCA50X_SEQUENCE_DROP) { if (cdata[1] == 0x01) { sequenceNumber = 0; } else { /* drop packet */ PDEBUG (5, "Dropped packet (expected seq 0x%02x)", frame->last_packet + 1); continue; } } else { sequenceNumber++; } } break; case BRIDGE_SPCA536: { iPix = 2; if (sequenceNumber == SPCA50X_SEQUENCE_DROP) { sequenceNumber = 0; } else { sequenceNumber++; } } break; case BRIDGE_SPCA504: case BRIDGE_SPCA504B: case BRIDGE_SPCA504C: { iPix = 1; switch (sequenceNumber) { case 0xfe: sequenceNumber = 0; break; case SPCA50X_SEQUENCE_DROP: /* drop packet */ PDEBUG (5, "Dropped packet (expected seq 0x%02x)", frame->last_packet + 1); continue; default: sequenceNumber++; break; } } break; default: { iPix = 1; /* check if this is a drop packet */ if (sequenceNumber == SPCA50X_SEQUENCE_DROP) { PDEBUG (3, "Dropped packet (expected seq 0x%02x)", frame->last_packet + 1); continue; } } break; } PDEBUG (3, "spca50x: Packet seqnum = 0x%02x. curframe=%2d", sequenceNumber, spca50x->curframe); pData = cdata; /* Can we find a frame start */ if (sequenceNumber == 0) { totlen = 0; iPix = spca50x->header_len; PDEBUG (3, "spca50x: Found Frame Start!, framenum = %d", spca50x->curframe); // Start of frame is implicit end of previous frame // Check for a previous frame and finish it off if one exists if (frame->scanstate == STATE_LINES){ if (frame->format != VIDEO_PALETTE_RAW_JPEG) { /* Decode the frame */ tasklet_init (&spca50x->spca5xx_tasklet, outpict_do_tasklet, (unsigned long) frame); tasklet_schedule (&spca50x->spca5xx_tasklet); } else { /* RAW DATA stream */ frame->grabstate = FRAME_DONE; if (waitqueue_active (&frame->wq)) wake_up_interruptible (&frame->wq); } // If someone decided to wait for ANY frame - wake him up if (waitqueue_active (&spca50x->wq)) wake_up_interruptible (&spca50x->wq); frame = spca50x_next_frame (spca50x, cdata); } else frame->scanstate = STATE_LINES; } /* Are we in a frame? */ if (frame == NULL || frame->scanstate != STATE_LINES) continue; if (sequenceNumber != frame->last_packet + 1 && frame->last_packet != -1) { /* Note, may get one of these for the first packet after opening */ PDEBUG (2, "Out of order packet, last = %d, this = %d", frame->last_packet, sequenceNumber); } frame->last_packet = sequenceNumber; /* This is the real conversion of the raw camera data to BGR for V4L */ datalength -= iPix; // correct length for packet header pData = cdata + iPix; // Skip packet header (1 or 10 bytes) // Consume data PDEBUG (5, "Processing packet seq %d,length %d,totlength %d", frame->last_packet, datalength, frame->totlength); /* this copy consume input data from the isoc stream */ if ((datalength > 0) && (datalength <= 0x3ff)){ memcpy (frame->highwater, pData, datalength); frame->highwater += datalength; totlen += datalength; } frame->totlength = totlen;#ifdef SPCA50X_ENABLE_EXP_BRIGHTNESS /* autoadjust is set to 1 to so now autobrightness will be calculated frome this frame. autoadjust will be set to 0 when autobrightness has been corrected if needed. */ autoadjust = 1;#endif /* SPCA50X_ENABLE_EXP_BRIGHTNESS */ } return totlen;}/**************************************************************************** * * Buffer management * ***************************************************************************/static intspca50x_alloc (struct usb_spca50x *spca50x){ int i; PDEBUG (4, "entered"); down (&spca50x->buf_lock); spca50x->tmpBuffer = rvmalloc (MAX_FRAME_SIZE); if (spca50x->buf_state == BUF_ALLOCATED) goto out; spca50x->fbuf = rvmalloc (SPCA50X_NUMFRAMES * MAX_DATA_SIZE); if (!spca50x->fbuf) goto error; for (i = 0; i < SPCA50X_NUMFRAMES; i++) { spca50x->frame[i].tmpbuffer = spca50x->tmpBuffer; spca50x->frame[i].decoder = &spca50x->maindecode; //connect each frame to the main data decoding spca50x->frame[i].grabstate = FRAME_UNUSED; spca50x->frame[i].scanstate = STATE_SCANNING; spca50x->frame[i].data = spca50x->fbuf + i * MAX_DATA_SIZE; spca50x->frame[i].highwater = spca50x->frame[i].data; PDEBUG (4, "frame[%d] @ %p", i, spca50x->frame[i].data); } for (i = 0; i < SPCA50X_NUMSBUF; i++) { spca50x->sbuf[i].data = kmalloc (FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); if (!spca50x->sbuf[i].data) goto error; PDEBUG (4, "sbuf[%d] @ %p", i, spca50x->sbuf[i].data); } spca50x->buf_state = BUF_ALLOCATED;out: up (&spca50x->buf_lock); PDEBUG (4, "leaving"); return 0;error: /* FIXME: IMHO, it's better to move error deallocation code here. */ for (i = 0; i < SPCA50X_NUMSBUF; i++) { if (spca50x->sbuf[i].data) { kfree (spca50x->sbuf[i].data); spca50x->sbuf[i].data = NULL; } } if (spca50x->fbuf) { rvfree (spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE); spca50x->fbuf = NULL; } if (spca50x->tmpBuffer) { rvfree (spca50x->tmpBuffer, MAX_FRAME_SIZE); spca50x->tmpBuffer = NULL; } spca50x->buf_state = BUF_NOT_ALLOCATED; up (&spca50x->buf_lock); PDEBUG (1, "errored"); return -ENOMEM;}static voidspca5xx_dealloc (struct usb_spca50x *spca50x ){ int i; PDEBUG (2, "entered dealloc"); down (&spca50x->buf_lock); if (spca50x->fbuf) { rvfree (spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE); spca50x->fbuf = NULL; for (i = 0; i < SPCA50X_NUMFRAMES; i++) spca50x->frame[i].data = NULL; } if (spca50x->tmpBuffer) { rvfree (spca50x->tmpBuffer, MAX_FRAME_SIZE); spca50x->tmpBuffer = NULL; } for (i = 0; i < SPCA50X_NUMSBUF; i++) { if (spca50x->sbuf[i].data) { kfree (spca50x->sbuf[i].data); spca50x->sbuf[i].data = NULL; } } PDEBUG (2, "buffer memory deallocated"); spca50x->buf_state = BUF_NOT_ALLOCATED; up (&spca50x->buf_lock); PDEBUG (2, "leaving dealloc");}/** * Reset the camera and send the correct initialization sequence for the * currently selected source */static intspca50x_init_source (struct usb_spca50x *spca50x){ int err_code; switch (spca50x->bridge) { case BRIDGE_SN9CXXX: err_code = sn9cxxx_init (spca50x); PDEBUG (2, "Initializing Sonix finished %d",err_code); if (err_code < 0) return err_code; break; case BRIDGE_ZC3XX: err_code = zc3xx_init (spca50x); break; case BRIDGE_SPCA504: case BRIDGE_SPCA504C: case BRIDGE_SPCA536: case BRIDGE_SPCA533: case BRIDGE_SPCA504B: { PDEBUG (2, "Opening SPCA5xx FW2"); sp5xxfw2_init (spca50x); break; } default: { err ("Unimplemented bridge type"); return -EINVAL; } } spca50x->norme = 0; spca50x->channel = 0; err_code =spca5xx_setMode(spca50x,spca50x->width,spca50x->height,VIDEO_PALETTE_JPEG); PDEBUG(2,"set Mode return %d ", err_code); if (err_code < 0) return -EINVAL; return 0;}/**************************************************************************** * * V4L API * ***************************************************************************/static inline void spca5xx_setFrameDecoder(struct usb_spca50x *spca50x){ int i; /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used * (using read() instead). */ for (i = 0; i < SPCA50X_NUMFRAMES; i++) { spca50x->frame[i].width = spca50x->width; spca50x->frame[i].height = spca50x->height; spca50x->frame[i].cameratype = spca50x->cameratype; spca50x->frame[i].scanlength = 0; spca50x->frame[i].depth = 8; spca50x->frame[i].format = VIDEO_PALETTE_JPEG; }}static inline void spca5xx_initDecoder(struct usb_spca50x *spca50x){ if (spca50x->cameratype == JPEG) init_jpeg_decoder (spca50x,2); if (spca50x->cameratype == JPGH || spca50x->cameratype == JPGC || spca50x->cameratype == JPGS) init_jpeg_decoder (spca50x,1); if (spca50x->cameratype == JPGM) init_jpeg_decoder (spca50x,0);}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)static intspca5xx_open (struct inode *inode, struct file *file){ struct video_device *vdev = video_devdata (file);#elsestatic intspca5xx_open(struct video_device *vdev, int flags){#endif struct usb_spca50x *spca50x = video_get_drvdata (vdev); int err; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT;#endif PDEBUG (2, "opening"); down (&spca50x->lock); /* sanity check disconnect, in use, no memory available */ err = -ENODEV;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -