Forgot to attach the patch; sorry about that. Here it is... Mark McClelland wrote: > > This is against 2.3.99-pre9-2 + my 1.14 patch. > > SUMMARY: > o 384x288 and 448x336 modes > o better /proc/video support > > CHANGES: > - changed to use /proc/video entry created by videodev.c > - 384x288 and 448x336 modes added > - ov511_move_data() rewritten > - Added debug messages for IOCTLs > - Miscellaneous changes in ov511_ioctl() > - Documentation/Configure.help: CONFIG_VIDEO_PROC_FS help added > - CREDITS: updated > - drivers/char/Config.in: CONFIG_VIDEO_PROC_FS option added > - drivers/char/videodev.c: procfs support added > - Documentation/ov511.txt: updated -- Mark McClelland [EMAIL PROTECTED]
diff -Naur linux-2.3.99-pre9-2-orig/CREDITS linux/CREDITS --- linux-2.3.99-pre9-2-orig/CREDITS Sat May 20 11:58:30 2000 +++ linux/CREDITS Sat May 20 11:02:25 2000 @@ -1617,7 +1617,7 @@ E: [EMAIL PROTECTED] E: [EMAIL PROTECTED] W: http://helllabs.org/~claudio -D: OV511 driver hacks +D: V4L, OV511 driver hacks S: Conectiva S.A. S: R. Tocantins 89 S: 80050-430 Curitiba PR diff -Naur linux-2.3.99-pre9-2-orig/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.3.99-pre9-2-orig/Documentation/Configure.help Thu May 18 09:03:03 2000 +++ linux/Documentation/Configure.help Sat May 20 11:02:26 2000 @@ -14832,6 +14832,14 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Video For Linux /proc file system information +CONFIG_VIDEO_PROC_FS + If you say Y here, you are able to access video device information + in /proc/video. + + To use this option, you have to check, that the "/proc file system + support" (CONFIG_PROC_FS) is enabled too. + AIMSlab RadioTrack (aka RadioReveal) support CONFIG_RADIO_RTRACK Choose Y here if you have one of these FM radio cards, and then fill diff -Naur linux-2.3.99-pre9-2-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- linux-2.3.99-pre9-2-orig/Documentation/usb/ov511.txt Sat May 20 11:58:30 2000 +++ linux/Documentation/usb/ov511.txt Sat May 20 11:48:04 2000 @@ -6,8 +6,8 @@ Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o 352x288 mode - o force_rgb parameter for apps that expect RGB instead of BGR + o 384x288 and 448x336 modes + o better /proc/video support INTRODUCTION: @@ -179,7 +179,7 @@ your colors look VERY wrong, you may want to change this. WORKING FEATURES: - o Color streaming/capture at 640x480, 352x288, and 320x240 + o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240 o YUV420 color o Monochrome o Setting/getting of saturation, contrast and brightness (no hue yet; only diff -Naur linux-2.3.99-pre9-2-orig/drivers/char/Config.in linux/drivers/char/Config.in --- linux-2.3.99-pre9-2-orig/drivers/char/Config.in Wed May 10 16:56:41 2000 +++ linux/drivers/char/Config.in Sat May 20 11:02:26 2000 @@ -153,6 +153,7 @@ tristate 'Video For Linux' CONFIG_VIDEO_DEV if [ "$CONFIG_VIDEO_DEV" != "n" ]; then + bool ' V4L information in proc filesystem' CONFIG_VIDEO_PROC_FS Y dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT $CONFIG_I2C comment 'Radio Adapters' dep_tristate ' ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV diff -Naur linux-2.3.99-pre9-2-orig/drivers/char/videodev.c linux/drivers/char/videodev.c --- linux-2.3.99-pre9-2-orig/drivers/char/videodev.c Thu Apr 13 07:54:32 2000 +++ linux/drivers/char/videodev.c Sat May 20 11:02:26 2000 @@ -11,7 +11,8 @@ * * Author: Alan Cox, <[EMAIL PROTECTED]> * - * Fixes: + * Fixes: 20000516 Claudio Matsuoka <[EMAIL PROTECTED]> + * - Added procfs support */ #include <linux/config.h> @@ -40,6 +41,27 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + +#include <linux/proc_fs.h> + +struct videodev_proc_data { + struct list_head proc_list; + char name[16]; + struct video_device *vdev; + struct proc_dir_entry *proc_entry; + struct video_capability vcap; +}; + +static struct proc_dir_entry *video_dev_proc_entry = NULL; +struct proc_dir_entry *video_proc_entry = NULL; +EXPORT_SYMBOL(video_proc_entry); +LIST_HEAD(videodev_proc_list); + +#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ + + #ifdef CONFIG_VIDEO_BT848 extern int init_bttv_cards(struct video_init *); extern int i2c_tuner_init(struct video_init *); @@ -217,6 +239,152 @@ return -EINVAL; } +/* + * /proc support + */ + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + +/* Hmm... i'd like to see video_capability information here, but + * how can I access it (without changing the other drivers? -claudio + */ +static int videodev_proc_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *out = page; + struct video_device *vfd = data; + struct videodev_proc_data *d; + struct list_head *tmp; + int len; + char c = ' '; + + list_for_each (tmp, &videodev_proc_list) { + d = list_entry(tmp, struct videodev_proc_data, proc_list); + if (vfd == d->vdev) + break; + } + + /* Sanity check */ + if (tmp == &videodev_proc_list) + goto skip; + +#define PRINT_VID_TYPE(x) do { if (vfd->type & x) \ + out += sprintf (out, "%c%s", c, #x); c='|';} while (0) + + out += sprintf (out, "name : %s\n", vfd->name); + out += sprintf (out, "type :"); + PRINT_VID_TYPE(VID_TYPE_CAPTURE); + PRINT_VID_TYPE(VID_TYPE_TUNER); + PRINT_VID_TYPE(VID_TYPE_TELETEXT); + PRINT_VID_TYPE(VID_TYPE_OVERLAY); + PRINT_VID_TYPE(VID_TYPE_CHROMAKEY); + PRINT_VID_TYPE(VID_TYPE_CLIPPING); + PRINT_VID_TYPE(VID_TYPE_FRAMERAM); + PRINT_VID_TYPE(VID_TYPE_SCALES); + PRINT_VID_TYPE(VID_TYPE_MONOCHROME); + PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE); + PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER); + PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER); + PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER); + PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER); + out += sprintf (out, "\n"); + out += sprintf (out, "hardware : 0x%x\n", vfd->hardware); +#if 0 + out += sprintf (out, "channels : %d\n", d->vcap.channels); + out += sprintf (out, "audios : %d\n", d->vcap.audios); + out += sprintf (out, "maxwidth : %d\n", d->vcap.maxwidth); + out += sprintf (out, "maxheight : %d\n", d->vcap.maxheight); + out += sprintf (out, "minwidth : %d\n", d->vcap.minwidth); + out += sprintf (out, "minheight : %d\n", d->vcap.minheight); +#endif + +skip: + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) + return 0; + } else + len = count; + + *start = page + off; + + return len; +} + +static void videodev_proc_create(void) +{ + video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root); + + if (video_proc_entry == NULL) { + printk("video_dev: unable to initialise /proc/video\n"); + return; + } + + video_proc_entry->owner = THIS_MODULE; + video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry); + + if (video_dev_proc_entry == NULL) { + printk("video_dev: unable to initialise /proc/video/dev\n"); + return; + } + + video_dev_proc_entry->owner = THIS_MODULE; +} + +static void videodev_proc_destroy(void) +{ + if (video_dev_proc_entry != NULL) + remove_proc_entry("dev", video_proc_entry); + + if (video_proc_entry != NULL) + remove_proc_entry("video", &proc_root); +} + +static void videodev_proc_create_dev (struct video_device *vfd, char *name) +{ + struct videodev_proc_data *d; + struct proc_dir_entry *p; + + if (video_dev_proc_entry == NULL) + return; + + d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL); + if (!d) + return; + + p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry); + p->data = vfd; + p->read_proc = videodev_proc_read; + + d->proc_entry = p; + d->vdev = vfd; + strcpy (d->name, name); + + /* How can I get capability information ? */ + + list_add (&d->proc_list, &videodev_proc_list); +} + +static void videodev_proc_destroy_dev (struct video_device *vfd) +{ + struct list_head *tmp; + struct videodev_proc_data *d; + + list_for_each (tmp, &videodev_proc_list) { + d = list_entry(tmp, struct videodev_proc_data, proc_list); + if (vfd == d->vdev) { + remove_proc_entry(d->name, video_dev_proc_entry); + list_del (&d->proc_list); + kfree (d); + break; + } + } +} + +#endif /* CONFIG_VIDEO_PROC_FS */ + extern struct file_operations video_fops; /** @@ -308,6 +476,13 @@ VIDEO_MAJOR, vfd->minor, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, &video_fops, NULL); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + sprintf (name, "%s%d", name_base, i - base); + videodev_proc_create_dev (vfd, name); +#endif + + return 0; } } @@ -326,6 +501,11 @@ { if(video_device[vfd->minor]!=vfd) panic("vfd: bad unregister"); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_destroy_dev (vfd); +#endif + devfs_unregister (vfd->devfs_handle); video_device[vfd->minor]=NULL; MOD_DEC_USE_COUNT; @@ -363,6 +543,10 @@ * Init kernel installed video drivers */ +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_create (); +#endif + while(vfli->init!=NULL) { vfli->init(vfli); @@ -379,6 +563,10 @@ void cleanup_module(void) { +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_destroy (); +#endif + devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture"); } diff -Naur linux-2.3.99-pre9-2-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- linux-2.3.99-pre9-2-orig/drivers/usb/ov511.c Sat May 20 11:58:30 2000 +++ linux/drivers/usb/ov511.c Sat May 20 11:47:38 2000 @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.14"; +static const char version[] = "1.15"; #define __NO_VERSION__ @@ -263,9 +263,10 @@ * Based on the CPiA driver version 0.7.4 -claudio **********************************************************************/ -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + static struct proc_dir_entry *ov511_proc_entry = NULL; -static struct proc_dir_entry *video_proc_entry = NULL; +extern struct proc_dir_entry *video_proc_entry; #define YES_NO(x) ((x) ? "yes" : "no") @@ -343,6 +344,7 @@ len = count; *start = page + off; + return len; } @@ -357,12 +359,11 @@ char name[7]; struct proc_dir_entry *ent; - PDEBUG (4, "creating /proc/video/ov511/videoX entry"); if (!ov511_proc_entry || !ov511) return; sprintf(name, "video%d", ov511->vdev.minor); - PDEBUG (4, "creating %s", name); + PDEBUG (4, "creating /proc/video/ov511/%s", name); ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry); @@ -372,7 +373,6 @@ ent->data = ov511; ent->read_proc = ov511_read_proc; ent->write_proc = ov511_write_proc; - ent->size = 3626; /* FIXME */ ov511->proc_entry = ent; } @@ -391,22 +391,13 @@ static void proc_ov511_create(void) { - struct proc_dir_entry *p = NULL; - /* No current standard here. Alan prefers /proc/video/ as it keeps * /proc "less cluttered than /proc/randomcardifoundintheshed/" * -claudio */ - PDEBUG (3, "creating /proc/video"); - video_proc_entry = proc_mkdir("video", p); - if (!video_proc_entry) { - if (!p) { - err("Unable to initialise /proc/video\n"); - return; - } else { /* FIXME - this doesn't work */ - PDEBUG (3, "/proc/video already exists"); - video_proc_entry = p; - } + if (video_proc_entry == NULL) { + err("Unable to initialise /proc/video/ov511"); + return; } ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry); @@ -414,16 +405,19 @@ if (ov511_proc_entry) ov511_proc_entry->owner = THIS_MODULE; else - err("Unable to initialise /proc/video/ov511\n"); + err("Unable to initialise /proc/ov511"); } static void proc_ov511_destroy(void) { PDEBUG (3, "removing /proc/video/ov511"); + + if (ov511_proc_entry == NULL) + return; + remove_proc_entry("ov511", video_proc_entry); - remove_proc_entry("video", NULL); } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ /********************************************************************** @@ -852,7 +846,7 @@ return 0; } -/* FIXME: add 176x144, 160x140 */ +/* FIXME: add 400x300, 176x144, 160x140 */ static struct mode_list mlist[] = { { 640, 480, VIDEO_PALETTE_GREY, 0x4f, 0x3d, 0x00, 0x00, 0x4f, 0x3d, 0x00, 0x00, 0x04, 0x03, 0x24, 0x04, 0x9e }, @@ -866,6 +860,14 @@ 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, { 352, 288, VIDEO_PALETTE_RGB24,0x2b, 0x25, 0x00, 0x00, 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 384, 288, VIDEO_PALETTE_GREY, 0x2f, 0x25, 0x00, 0x00, + 0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 384, 288, VIDEO_PALETTE_RGB24,0x2f, 0x25, 0x00, 0x00, + 0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 448, 336, VIDEO_PALETTE_GREY, 0x37, 0x29, 0x00, 0x00, + 0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 448, 336, VIDEO_PALETTE_RGB24,0x37, 0x29, 0x00, 0x00, + 0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, { 0, 0 } }; @@ -1302,158 +1304,190 @@ int i, totlen = 0; int aPackNum[10]; struct ov511_frame *frame; + unsigned char *pData; + int iPix; - PDEBUG(4, "ov511_move_data"); + PDEBUG (4, "Moving %d packets", urb->number_of_packets); for (i = 0; i < urb->number_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; + urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].status = 0; + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1; - if (!n || ov511->curframe == -1) continue; + if (!n || ov511->curframe == -1) + continue; if (st) PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st); frame = &ov511->frame[ov511->curframe]; - /* Can we find a frame end */ + /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th + * byte non-zero. The EOF packet has image width/height in the + * 10th and 11th packets. The 9th bit is given as follows: + * + * bit 7: EOF + * 6: compression enabled + * 5: 422/420/400 modes + * 4: 422/420/400 modes + * 3: 1 + * 2: snapshot bottom on + * 1: snapshot frame + * 0: even/odd field + */ + + /* Check for SOF/EOF packet */ if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | - cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 && - (cdata[8] & 8) && (cdata[8] & 0x80)) { + cdata[4] | cdata[5] | cdata[6] | cdata[7]) || + (~cdata[8] & 0x08)) + goto check_middle; + + /* Frame end */ + if (cdata[8] & 0x80) { +#if 0 + struct timeval *ts; + + ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE); + do_gettimeofday (ts); +#endif + + PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d", + ov511->curframe, (int)(cdata[ov511->packet_size - 1]), + (int)(cdata[9]), (int)(cdata[10])); - struct timeval *ts; - ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE); - do_gettimeofday(ts); - - PDEBUG(4, "Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d", - ov511->curframe, (int)(cdata[ov511->packet_size - 1]), - (int)(cdata[9]), (int)(cdata[10])); + if (frame->scanstate == STATE_LINES) { + int iFrameNext; - if (frame->scanstate == STATE_LINES) { - int iFrameNext; if (fix_rgb_offset) fixFrameRGBoffset(frame); frame->grabstate = FRAME_DONE; - if (waitqueue_active(&frame->wq)) { - frame->grabstate = FRAME_DONE; - wake_up_interruptible(&frame->wq); + + if (waitqueue_active(&frame->wq)) { + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); } - /* If next frame is ready or grabbing, point to it */ + + /* If next frame is ready or grabbing, + * point to it */ iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES; - if (ov511->frame[iFrameNext].grabstate== FRAME_READY || - ov511->frame[iFrameNext].grabstate== FRAME_GRABBING) { - ov511->curframe = iFrameNext; - ov511->frame[iFrameNext].scanstate = STATE_SCANNING; + if (ov511->frame[iFrameNext].grabstate == FRAME_READY + || ov511->frame[iFrameNext].grabstate == +FRAME_GRABBING) { + ov511->curframe = iFrameNext; + ov511->frame[iFrameNext].scanstate = +STATE_SCANNING; } else { + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "Frame done! +congratulations"); + } else { + PDEBUG(4, "Frame not ready? state = +%d", + +ov511->frame[iFrameNext].grabstate); + } - PDEBUG(4, "Frame not ready? state = %d", - ov511->frame[iFrameNext].grabstate); - - ov511->curframe = -1; + ov511->curframe = -1; } - } - } - - /* Can we find a frame start */ - else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | - cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 && - (cdata[8] & 8)) { - - PDEBUG(4, "ov511: Found Frame Start!, framenum = %d", - ov511->curframe); + } + /* Image corruption caused by misplaced frame->segment = 0 + * fixed by [EMAIL PROTECTED] + */ + } else { + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov511->curframe); /* Check to see if it's a snapshot frame */ /* FIXME?? Should the snapshot reset go here? Performance? */ if (cdata[8] & 0x02) { frame->snapshot = 1; - PDEBUG(3, "ov511_move_data: snapshot detected"); + PDEBUG(3, "snapshot detected"); } frame->scanstate = STATE_LINES; frame->segment = 0; } +check_middle: /* Are we in a frame? */ - if (frame->scanstate == STATE_LINES) { - unsigned char * pData; - int iPix; - - /* Deal with leftover from last segment, if any */ - if (frame->segment) { - pData = ov511->scratch; - iPix = - ov511->scratchlen; - memmove(pData + ov511->scratchlen, cdata, - iPix+frame->segsize); - } else { - pData = &cdata[iPix = 9]; - } + if (frame->scanstate != STATE_LINES) + continue; - /* Parse the segments */ - while(iPix <= (ov511->packet_size - 1) - frame->segsize && - frame->segment < frame->width * frame->height / 256) { - int iSegY; - int iSegUV; - int iY, jY, iUV, jUV; - int iOutY, iOutUV; - unsigned char * pOut; - - iSegY = iSegUV = frame->segment; - pOut = frame->data; - - frame->segment++; - iPix += frame->segsize; - - if (frame->sub_flag) { - int iSeg1; - iSeg1 = iSegY / (ov511->subw / 32); - iSeg1 *= frame->width / 32; - iSegY = iSeg1 + (iSegY % (ov511->subw / 32)); - if (iSegY >= frame->width * ov511->subh / 256) - break; - - iSeg1 = iSegUV / (ov511->subw / 16); - iSeg1 *= frame->width / 16; - iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16)); - - pOut += (ov511->subx + - ov511->suby * frame->width) * frame->depth; - } - - iY = iSegY / (frame->width / WDIV); - jY = iSegY - iY * (frame->width / WDIV); - iOutY = (iY*HDIV*frame->width + jY*WDIV) * frame->depth; - iUV = iSegUV / (frame->width / WDIV * 2); - jUV = iSegUV - iUV * (frame->width / WDIV * 2); - iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * frame->depth; - - if (frame->format == VIDEO_PALETTE_GREY) { - ov511_parse_data_grey(pData, pOut, iOutY, frame->width); - } else if (frame->format == VIDEO_PALETTE_RGB24) { - ov511_parse_data_rgb24(pData, pOut, iOutY, iOutUV, iY & 1, - frame->width); - } - pData = &cdata[iPix]; - } + /* Deal with leftover from last segment, if any */ + if (frame->segment) { + pData = ov511->scratch; + iPix = -ov511->scratchlen; + memmove(pData + ov511->scratchlen, cdata, + iPix+frame->segsize); + } else { + pData = &cdata[iPix = 9]; + } + + /* Parse the segments */ + while (iPix <= (ov511->packet_size - 1) - frame->segsize && + frame->segment < frame->width * frame->height / 256) { + int iSegY, iSegUV; + int iY, jY, iUV, jUV; + int iOutY, iOutUV; + unsigned char *pOut; + + iSegY = iSegUV = frame->segment; + pOut = frame->data; + frame->segment++; + iPix += frame->segsize; + + /* Handle subwindow */ + if (frame->sub_flag) { + int iSeg1; + + iSeg1 = iSegY / (ov511->subw / 32); + iSeg1 *= frame->width / 32; + iSegY = iSeg1 + (iSegY % (ov511->subw / 32)); + if (iSegY >= frame->width * ov511->subh / 256) + break; + + iSeg1 = iSegUV / (ov511->subw / 16); + iSeg1 *= frame->width / 16; + iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16)); - /* Save extra data for next time */ - if (frame->segment < frame->width * frame->height / 256) { - ov511->scratchlen = (ov511->packet_size - 1) - iPix; - if (ov511->scratchlen < frame->segsize) { - memmove(ov511->scratch, pData, ov511->scratchlen); - } else { - ov511->scratchlen = 0; - } + pOut += (ov511->subx + ov511->suby * frame->width) * + (frame->depth >> 3); } + + /* + * iY counts segment lines + * jY counts segment columns + * iOutY is the offset (in bytes) of the segment upper left +corner + */ + iY = iSegY / (frame->width / WDIV); + jY = iSegY - iY * (frame->width / WDIV); + iOutY = (iY*HDIV*frame->width + jY*WDIV) * (frame->depth >> 3); + iUV = iSegUV / (frame->width / WDIV * 2); + jUV = iSegUV - iUV * (frame->width / WDIV * 2); + iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * +(frame->depth >> 3); + + if (frame->format == VIDEO_PALETTE_GREY) + ov511_parse_data_grey (pData, pOut, iOutY, +frame->width); + else if (frame->format == VIDEO_PALETTE_RGB24) + ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV, + iY & 1, frame->width); + + pData = &cdata[iPix]; + } + + /* Save extra data for next time */ + if (frame->segment < frame->width * frame->height / 256) { + ov511->scratchlen = (ov511->packet_size - 1) - iPix; + if (ov511->scratchlen < frame->segsize) + memmove(ov511->scratch, pData, + ov511->scratchlen); + else + ov511->scratchlen = 0; } } - - PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d\n", + PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d", aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4], aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]); @@ -1472,8 +1506,6 @@ if (!ov511->streaming) { PDEBUG(2, "hmmm... not streaming, but got interrupt"); return; - } else { - PDEBUG(5, "streaming. got interrupt"); } sbuf = &ov511->sbuf[ov511->cursbuf]; @@ -1723,7 +1755,7 @@ static int ov511_init_done(struct video_device *dev) { -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) create_proc_ov511_cam((struct usb_ov511 *)dev); #endif @@ -1749,6 +1781,8 @@ { struct video_capability b; + PDEBUG (4, "VIDIOCGCAP"); + strcpy(b.name, "OV511 USB Camera"); b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; b.channels = 1; @@ -1798,6 +1832,8 @@ { struct video_picture p; + PDEBUG (4, "VIDIOCGPICT"); + if (ov7610_get_picture(ov511, &p)) return -EIO; @@ -1809,18 +1845,33 @@ case VIDIOCSPICT: { struct video_picture p; + int i; + + PDEBUG (4, "VIDIOCSPICT"); if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; - + if (ov7610_set_picture(ov511, &p)) return -EIO; + /* FIXME: check validity */ + + PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette); + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].depth = p.depth; + ov511->frame[i].format = p.palette; + ov511->frame[i].segsize = GET_SEGSIZE(p.palette); + } + return 0; } case VIDIOCGCAPTURE: { int vf; + + PDEBUG (4, "VIDIOCGCAPTURE"); + if (copy_from_user(&vf, arg, sizeof(vf))) return -EFAULT; ov511->sub_flag = vf; @@ -1836,16 +1887,25 @@ return -EINVAL; if (vc.decimation) return -EINVAL; +#if 0 vc.x /= 4; vc.x *= 4; vc.y /= 2; vc.y *= 2; vc.width /= 32; vc.width *= 32; - if (vc.width == 0) vc.width = 32; +#else + vc.x &= ~3L; + vc.y &= ~1L; + vc.y &= ~31L; +#endif + if (vc.width == 0) + vc.width = 32; + vc.height /= 16; vc.height *= 16; - if (vc.height == 0) vc.height = 16; + if (vc.height == 0) + vc.height = 16; ov511->subx = vc.x; ov511->suby = vc.y; @@ -1857,9 +1917,15 @@ case VIDIOCSWIN: { struct video_window vw; + int i, result; if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; + + PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d", + vw.width, vw.height); + +#if 0 if (vw.flags) return -EINVAL; if (vw.clipcount) @@ -1868,8 +1934,22 @@ return -EINVAL; if (vw.width != DEFAULT_WIDTH) return -EINVAL; +#endif - ov511->compress = 0; + /* If we're collecting previous frame wait + before changing modes */ + interruptible_sleep_on(&ov511->wq); + if (signal_pending(current)) return -EINTR; + + result = ov511_mode_init_regs(ov511, vw.width, vw.height, + ov511->frame[0].format, ov511->sub_flag); + if (result < 0) + return result; + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].width = vw.width; + ov511->frame[i].height = vw.height; + } return 0; } @@ -1877,13 +1957,15 @@ { struct video_window vw; - vw.x = 0; + vw.x = 0; /* FIXME */ vw.y = 0; - vw.width = DEFAULT_WIDTH; - vw.height = DEFAULT_HEIGHT; + vw.width = ov511->frame[0].width; + vw.height = ov511->frame[0].height; vw.chromakey = 0; vw.flags = 30; + PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height); + if (copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; @@ -1935,19 +2017,16 @@ before changing modes */ interruptible_sleep_on(&ov511->wq); if (signal_pending(current)) return -EINTR; - ov511_mode_init_regs(ov511, - vm.width, vm.height, - vm.format, ov511->sub_flag); + ov511_mode_init_regs(ov511, vm.width, vm.height, + vm.format, ov511->sub_flag); } ov511->frame[vm.frame].width = vm.width; ov511->frame[vm.frame].height = vm.height; ov511->frame[vm.frame].format = vm.format; ov511->frame[vm.frame].sub_flag = ov511->sub_flag; - ov511->frame[vm.frame].segsize = - vm.format == VIDEO_PALETTE_RGB24 ? 384 : 256; - ov511->frame[vm.frame].depth = - vm.format == VIDEO_PALETTE_RGB24 ? 3 : 1; + ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format); + ov511->frame[vm.frame].depth = GET_DEPTH(vm.format); /* Mark it as ready */ ov511->frame[vm.frame].grabstate = FRAME_READY; @@ -1965,11 +2044,11 @@ ov511->frame[frame].grabstate); switch (ov511->frame[frame].grabstate) { - case FRAME_UNUSED: - return -EINVAL; - case FRAME_READY: - case FRAME_GRABBING: - case FRAME_ERROR: + case FRAME_UNUSED: + return -EINVAL; + case FRAME_READY: + case FRAME_GRABBING: + case FRAME_ERROR: redo: if (!ov511->dev) return -EIO; @@ -1989,23 +2068,21 @@ if ((ret = ov511_new_frame(ov511, frame)) < 0) return ret; goto redo; - } - case FRAME_DONE: - ov511->frame[frame].grabstate = FRAME_UNUSED; - break; - } - - ov511->frame[frame].grabstate = FRAME_UNUSED; - - /* Reset the hardware snapshot button */ - /* FIXME - Is this the best place for this? */ - if ((ov511->snap_enabled) && - (ov511->frame[frame].snapshot)) { - ov511->frame[frame].snapshot = 0; - ov511_reg_write(ov511->dev, 0x52, 0x01); - ov511_reg_write(ov511->dev, 0x52, 0x03); - ov511_reg_write(ov511->dev, 0x52, 0x01); - } + } + case FRAME_DONE: + ov511->frame[frame].grabstate = FRAME_UNUSED; + + /* Reset the hardware snapshot button */ + /* FIXME - Is this the best place for this? */ + if ((ov511->snap_enabled) && + (ov511->frame[frame].snapshot)) { + ov511->frame[frame].snapshot = 0; + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, +0x01); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, +0x03); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, +0x01); + } + break; + } /* end switch */ return 0; } @@ -2038,7 +2115,7 @@ return -EINVAL; default: return -ENOIOCTLCMD; - } /* End switch(cmd) */ + } /* end switch */ return 0; } @@ -2610,7 +2687,7 @@ ov511->sbuf[0].urb = NULL; } -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_ov511_cam(ov511); #endif @@ -2637,8 +2714,7 @@ static int __init usb_ov511_init(void) { -#ifdef CONFIG_PROC_FS - PDEBUG(3, "creating /proc/ov511"); +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_create(); #endif @@ -2655,7 +2731,7 @@ usb_deregister(&ov511_driver); info("ov511 driver deregistered"); -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_destroy(); #endif }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
