diff -Nur --exclude='*.orig' linux-2.6.0-test1.org/drivers/media/video/bttv-cards.c linux-2.6.0-test1/drivers/media/video/bttv-cards.c --- linux-2.6.0-test1.org/drivers/media/video/bttv-cards.c Mon Jul 14 03:34:03 2003 +++ linux-2.6.0-test1/drivers/media/video/bttv-cards.c Tue Jul 22 09:01:24 2003 @@ -1630,12 +1630,8 @@ btv->type=card[btv->nr]; /* print which card config we are using */ - sprintf(btv->video_dev.name,"BT%d%s(%.23s)", - btv->id, - (btv->id==848 && btv->revision==0x12) ? "A" : "", - bttv_tvcards[btv->type].name); printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr, - btv->video_dev.name,btv->type, + bttv_tvcards[btv->type].name, btv->type, (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ? "insmod option" : "autodetected"); diff -Nur --exclude='*.orig' linux-2.6.0-test1.org/drivers/media/video/bttv-driver.c linux-2.6.0-test1/drivers/media/video/bttv-driver.c --- linux-2.6.0-test1.org/drivers/media/video/bttv-driver.c Mon Jul 14 03:36:43 2003 +++ linux-2.6.0-test1/drivers/media/video/bttv-driver.c Tue Jul 22 09:02:57 2003 @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -123,6 +124,17 @@ #endif /* ----------------------------------------------------------------------- */ +/* sysfs */ + +static ssize_t show_card(struct class_device *cd, char *buf) +{ + struct video_device *vfd = to_video_device(cd); + struct bttv *btv = dev_get_drvdata(vfd->dev); + return sprintf(buf, "%d\n", btv ? btv->type : UNSET); +} +static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); + +/* ----------------------------------------------------------------------- */ /* static data */ /* special timing tables from conexant... */ @@ -2007,7 +2019,7 @@ struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev.name); + strcpy(cap->name,btv->video_dev->name); if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { /* vbi */ cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; @@ -2309,7 +2321,7 @@ if (0 == v4l2) return -EINVAL; strcpy(cap->driver,"bttv"); - strlcpy(cap->card,btv->video_dev.name,sizeof(cap->card)); + strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",btv->dev->slot_name); cap->version = BTTV_VERSION_CODE; cap->capabilities = @@ -2683,12 +2695,12 @@ dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); for (i = 0; i < bttv_num; i++) { - if (bttvs[i].video_dev.minor == minor) { + if (bttvs[i].video_dev->minor == minor) { btv = &bttvs[i]; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; break; } - if (bttvs[i].vbi_dev.minor == minor) { + if (bttvs[i].vbi_dev->minor == minor) { btv = &bttvs[i]; type = V4L2_BUF_TYPE_VBI_CAPTURE; break; @@ -2786,8 +2798,8 @@ static struct video_device bttv_video_template = { .name = "UNSET", - type: VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, .minor = -1, @@ -2815,7 +2827,7 @@ dprintk("bttv: open minor=%d\n",minor); for (i = 0; i < bttv_num; i++) { - if (bttvs[i].radio_dev.minor == minor) { + if (bttvs[i].radio_dev->minor == minor) { btv = &bttvs[i]; break; } @@ -2860,7 +2872,7 @@ struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev.name); + strcpy(cap->name,btv->radio_dev->name); cap->type = VID_TYPE_TUNER; cap->channels = 1; cap->audios = 1; @@ -3239,30 +3251,83 @@ /* ----------------------------------------------------------------------- */ /* initialitation */ +static struct video_device *vdev_init(struct bttv *btv, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->release = video_device_release; + vfd->dev = &btv->dev->dev; + snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", + btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", + type, bttv_tvcards[btv->type].name); + return vfd; +} + /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { - if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) - return -1; + /* video */ + btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); + if (NULL == btv->video_dev) + goto err; + if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) + goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", - btv->nr,btv->video_dev.minor & 0x1f); + btv->nr,btv->video_dev->minor & 0x1f); + video_device_create_file(btv->video_dev, &class_device_attr_card); - if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) { - video_unregister_device(&btv->video_dev); - return -1; - } + /* vbi */ + btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); + if (NULL == btv->vbi_dev) + goto err; + if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", - btv->nr,btv->vbi_dev.minor & 0x1f); + btv->nr,btv->vbi_dev->minor & 0x1f); if (!btv->has_radio) return 0; - if (video_register_device(&btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) { - video_unregister_device(&btv->vbi_dev); - video_unregister_device(&btv->video_dev); - return -1; - } + /* radio */ + btv->radio_dev = vdev_init(btv, &radio_template, "radio"); + if (NULL == btv->radio_dev) + goto err; + if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) + goto err; printk(KERN_INFO "bttv%d: registered device radio%d\n", - btv->nr,btv->radio_dev.minor & 0x1f); + btv->nr,btv->radio_dev->minor & 0x1f); + + /* all done */ + return 0; + + err: + if (btv->video_dev) { + if (-1 != btv->video_dev->minor) + video_unregister_device(btv->video_dev); + else + video_device_release(btv->video_dev); + btv->video_dev = NULL; + } + if (btv->vbi_dev) { + if (-1 != btv->vbi_dev->minor) + video_unregister_device(btv->vbi_dev); + else + video_device_release(btv->vbi_dev); + btv->vbi_dev = NULL; + } + if (btv->radio_dev) { + if (-1 != btv->radio_dev->minor) + video_unregister_device(btv->radio_dev); + else + video_device_release(btv->radio_dev); + btv->radio_dev = NULL; + } return 0; } @@ -3310,15 +3375,6 @@ btv->i2c_rc = -1; btv->tuner_type = -1; - memcpy(&btv->video_dev, &bttv_video_template, sizeof(bttv_video_template)); - memcpy(&btv->radio_dev, &radio_template, sizeof(radio_template)); - memcpy(&btv->vbi_dev, &bttv_vbi_template, sizeof(bttv_vbi_template)); - btv->video_dev.minor = -1; - btv->video_dev.priv = btv; - btv->radio_dev.minor = -1; - btv->radio_dev.priv = btv; - btv->vbi_dev.minor = -1; - btv->vbi_dev.priv = btv; btv->has_radio=radio[btv->nr]; /* pci stuff (init, get irq/mmip, ... */ @@ -3477,12 +3533,18 @@ i2c_bit_del_bus(&btv->i2c_adap); /* unregister video4linux */ - if (btv->video_dev.minor!=-1) - video_unregister_device(&btv->video_dev); - if (btv->radio_dev.minor!=-1) - video_unregister_device(&btv->radio_dev); - if (btv->vbi_dev.minor!=-1) - video_unregister_device(&btv->vbi_dev); + if (btv->video_dev) { + video_unregister_device(btv->video_dev); + btv->video_dev = NULL; + } + if (btv->radio_dev) { + video_unregister_device(btv->radio_dev); + btv->radio_dev = NULL; + } + if (btv->vbi_dev) { + video_unregister_device(btv->vbi_dev); + btv->vbi_dev = NULL; + } /* free allocated memory */ bttv_riscmem_free(btv->dev,&btv->main); diff -Nur --exclude='*.orig' linux-2.6.0-test1.org/drivers/media/video/bttvp.h linux-2.6.0-test1/drivers/media/video/bttvp.h --- linux-2.6.0-test1.org/drivers/media/video/bttvp.h Mon Jul 14 03:32:44 2003 +++ linux-2.6.0-test1/drivers/media/video/bttvp.h Tue Jul 22 08:57:59 2003 @@ -280,9 +280,9 @@ int i2c_state, i2c_rc; /* video4linux (1) */ - struct video_device video_dev; - struct video_device radio_dev; - struct video_device vbi_dev; + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; /* locking */ spinlock_t s_lock; diff -Nur --exclude='*.orig' linux-2.6.0-test1.org/drivers/media/video/videodev.c linux-2.6.0-test1/drivers/media/video/videodev.c --- linux-2.6.0-test1.org/drivers/media/video/videodev.c Mon Jul 14 03:30:42 2003 +++ linux-2.6.0-test1/drivers/media/video/videodev.c Tue Jul 22 08:57:54 2003 @@ -15,7 +15,6 @@ * - Added procfs support */ -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -35,33 +35,67 @@ #include -#define VIDEO_NUM_DEVICES 256 +#define VIDEO_NUM_DEVICES 256 +#define VIDEO_NAME "video4linux" /* - * Active devices + * sysfs stuff */ - -static struct video_device *video_device[VIDEO_NUM_DEVICES]; -static DECLARE_MUTEX(videodev_lock); +static ssize_t show_name(struct class_device *cd, char *buf) +{ + struct video_device *vfd = to_video_device(cd); + return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); +} + +static ssize_t show_dev(struct class_device *cd, char *buf) +{ + struct video_device *vfd = to_video_device(cd); + dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor); + return sprintf(buf,"%04x\n",(int)dev); +} -#ifdef CONFIG_VIDEO_PROC_FS +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); -#include +struct video_device *video_device_alloc(void) +{ + struct video_device *vfd; -struct videodev_proc_data { - struct list_head proc_list; - char name[16]; - struct video_device *vdev; - struct proc_dir_entry *proc_entry; -}; + vfd = kmalloc(sizeof(*vfd),GFP_KERNEL); + if (NULL == vfd) + return NULL; + memset(vfd,0,sizeof(*vfd)); + return vfd; +} + +void video_device_release(struct video_device *vfd) +{ + kfree(vfd); +} + +static void video_release(struct class_device *cd) +{ + struct video_device *vfd = container_of(cd, struct video_device, class_dev); -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); +#if 1 /* needed until all drivers are fixed */ + if (!vfd->release) + return; +#endif + vfd->release(vfd); +} -#endif /* CONFIG_VIDEO_PROC_FS */ +static struct class video_class = { + .name = VIDEO_NAME, + .release = video_release, +}; + +/* + * Active devices + */ + +static struct video_device *video_device[VIDEO_NUM_DEVICES]; +static DECLARE_MUTEX(videodev_lock); struct video_device* video_devdata(struct file *file) { @@ -192,156 +226,6 @@ return 0; } -/* - * /proc support - */ - -#ifdef 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 __exit 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); - if (!p) { - kfree(d); - return; - } - 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; /** @@ -429,15 +313,23 @@ devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name); init_MUTEX(&vfd->lock); - -#ifdef CONFIG_VIDEO_PROC_FS -{ - char name[16]; - sprintf(name, "%s%d", name_base, i - base); - videodev_proc_create_dev(vfd, name); -} -#endif + /* sysfs class */ + memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); + if (vfd->dev) + vfd->class_dev.dev = vfd->dev; + vfd->class_dev.class = &video_class; + strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE); + class_device_register(&vfd->class_dev); + video_device_create_file(vfd, &class_device_attr_name); + video_device_create_file(vfd, &class_device_attr_dev); + +#if 1 /* needed until all drivers are fixed */ + if (!vfd->release) + printk(KERN_WARNING "videodev: \"%s\" has no release callback. " + "Please fix your driver for proper sysfs support, see " + "http://lwn.net/Articles/36850/\n", vfd->name); +#endif return 0; } @@ -455,10 +347,7 @@ if(video_device[vfd->minor]!=vfd) panic("videodev: bad unregister"); -#ifdef CONFIG_VIDEO_PROC_FS - videodev_proc_destroy_dev (vfd); -#endif - + class_device_unregister(&vfd->class_dev); devfs_remove(vfd->devfs_name); video_device[vfd->minor]=NULL; up(&videodev_lock); @@ -479,24 +368,18 @@ static int __init videodev_init(void) { printk(KERN_INFO "Linux video capture interface: v1.00\n"); - if (register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops)) { + if (register_chrdev(VIDEO_MAJOR,VIDEO_NAME, &video_fops)) { printk("video_dev: unable to get major %d\n", VIDEO_MAJOR); return -EIO; } - -#ifdef CONFIG_VIDEO_PROC_FS - videodev_proc_create (); -#endif - + class_register(&video_class); return 0; } static void __exit videodev_exit(void) { -#ifdef CONFIG_VIDEO_PROC_FS - videodev_proc_destroy (); -#endif - unregister_chrdev(VIDEO_MAJOR, "video_capture"); + class_unregister(&video_class); + unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); } module_init(videodev_init) @@ -508,6 +391,8 @@ EXPORT_SYMBOL(video_usercopy); EXPORT_SYMBOL(video_exclusive_open); EXPORT_SYMBOL(video_exclusive_release); +EXPORT_SYMBOL(video_device_alloc); +EXPORT_SYMBOL(video_device_release); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers"); diff -Nur --exclude='*.orig' linux-2.6.0-test1.org/include/linux/videodev.h linux-2.6.0-test1/include/linux/videodev.h --- linux-2.6.0-test1.org/include/linux/videodev.h Mon Jul 14 03:39:37 2003 +++ linux-2.6.0-test1/include/linux/videodev.h Tue Jul 22 08:57:54 2003 @@ -3,18 +3,10 @@ #include #include +#include -#if 1 -/* - * v4l2 is still work-in-progress, integration planed for 2.5.x - * documentation: http://bytesex.org/v4l/ - * patches available from: http://bytesex.org/patches/ - */ -# define HAVE_V4L2 1 -# include -#else -# undef HAVE_V4L2 -#endif +#define HAVE_V4L2 1 +#include #ifdef __KERNEL__ @@ -23,35 +15,70 @@ struct video_device { - struct module *owner; + /* device info */ + struct device *dev; char name[32]; int type; /* v4l1 */ int type2; /* v4l2 */ int hardware; int minor; - /* new interface -- we will use file_operations directly - * like soundcore does. */ + /* device ops + callbacks */ struct file_operations *fops; - void *priv; /* Used to be 'private' but that upsets C++ */ + void (*release)(struct video_device *vfd); - /* for videodev.c intenal usage -- don't touch */ - int users; - struct semaphore lock; - char devfs_name[64]; /* devfs */ +#if 1 /* to be removed in 2.7.x */ + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb|dev}_{get|set}_drvdata() directly. */ + void *priv; +#endif + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct semaphore lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ + struct class_device class_dev; /* sysfs */ }; #define VIDEO_MAJOR 81 -extern int video_register_device(struct video_device *, int type, int nr); #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 #define VFL_TYPE_VTX 3 +extern int video_register_device(struct video_device *, int type, int nr); extern void video_unregister_device(struct video_device *); extern struct video_device* video_devdata(struct file*); +#define to_video_device(cd) container_of(cd, struct video_device, class_dev) +static inline void +video_device_create_file(struct video_device *vfd, + struct class_device_attribute *attr) +{ + class_device_create_file(&vfd->class_dev, attr); +} + +/* helper functions to alloc / release struct video_device, the + later can be used for video_device->release() */ +struct video_device *video_device_alloc(void); +void video_device_release(struct video_device *vfd); + +/* helper functions to access driver private data. */ +static inline void *video_get_drvdata(struct video_device *dev) +{ + return dev->priv; +} + +static inline void video_set_drvdata(struct video_device *dev, void *data) +{ + dev->priv = data; +} + extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); extern int video_usercopy(struct inode *inode, struct file *file,