]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/pvrusb2/pvrusb2-sysfs.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
[linux-2.6-omap-h63xx.git] / drivers / media / video / pvrusb2 / pvrusb2-sysfs.c
index c6e6523d74b43dd3df9ecc5ab50405198b9c43f9..91396fd573e4a2c2a04f2b518d8a2811a8c60248 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <asm/semaphore.h>
@@ -40,16 +39,20 @@ struct pvr2_sysfs {
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
        struct pvr2_sysfs_ctl_item *item_first;
        struct pvr2_sysfs_ctl_item *item_last;
-       struct sysfs_ops kops;
-       struct kobj_type ktype;
        struct class_device_attribute attr_v4l_minor_number;
+       struct class_device_attribute attr_v4l_radio_minor_number;
        struct class_device_attribute attr_unit_number;
+       int v4l_minor_number_created_ok;
+       int v4l_radio_minor_number_created_ok;
+       int unit_number_created_ok;
 };
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 struct pvr2_sysfs_debugifc {
        struct class_device_attribute attr_debugcmd;
        struct class_device_attribute attr_debuginfo;
+       int debugcmd_created_ok;
+       int debuginfo_created_ok;
 };
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 
@@ -67,6 +70,7 @@ struct pvr2_sysfs_ctl_item {
        struct pvr2_sysfs_ctl_item *item_next;
        struct attribute *attr_gen[7];
        struct attribute_group grp;
+       int created_ok;
        char name[80];
 };
 
@@ -487,8 +491,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        struct pvr2_sysfs_func_set *fp;
        struct pvr2_ctrl *cptr;
        unsigned int cnt,acnt;
+       int ret;
 
-       if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
+       if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
                return;
        }
 
@@ -496,15 +501,14 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
        if (!cptr) return;
 
-       cip = kmalloc(sizeof(*cip),GFP_KERNEL);
+       cip = kzalloc(sizeof(*cip),GFP_KERNEL);
        if (!cip) return;
-       memset(cip,0,sizeof(*cip));
        pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
 
        cip->cptr = cptr;
 
        cip->chptr = sfp;
-       cip->item_next = 0;
+       cip->item_next = NULL;
        if (sfp->item_last) {
                sfp->item_last->item_next = cip;
        } else {
@@ -589,7 +593,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cip->grp.name = cip->name;
        cip->grp.attrs = cip->attr_gen;
 
-       sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       if (ret) {
+               printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+                      __FUNCTION__, ret);
+               return;
+       }
+       cip->created_ok = !0;
 }
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -600,9 +610,10 @@ static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
 {
        struct pvr2_sysfs_debugifc *dip;
-       dip = kmalloc(sizeof(*dip),GFP_KERNEL);
+       int ret;
+
+       dip = kzalloc(sizeof(*dip),GFP_KERNEL);
        if (!dip) return;
-       memset(dip,0,sizeof(*dip));
        dip->attr_debugcmd.attr.owner = THIS_MODULE;
        dip->attr_debugcmd.attr.name = "debugcmd";
        dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
@@ -613,19 +624,36 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
        dip->attr_debuginfo.attr.mode = S_IRUGO;
        dip->attr_debuginfo.show = debuginfo_show;
        sfp->debugifc = dip;
-       class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
-       class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+       ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               dip->debugcmd_created_ok = !0;
+       }
+       ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               dip->debuginfo_created_ok = !0;
+       }
 }
 
 
 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
 {
        if (!sfp->debugifc) return;
-       class_device_remove_file(sfp->class_dev,
-                                &sfp->debugifc->attr_debuginfo);
-       class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+       if (sfp->debugifc->debuginfo_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debuginfo);
+       }
+       if (sfp->debugifc->debugcmd_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debugcmd);
+       }
        kfree(sfp->debugifc);
-       sfp->debugifc = 0;
+       sfp->debugifc = NULL;
 }
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 
@@ -645,7 +673,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
        struct pvr2_sysfs_ctl_item *cip1,*cip2;
        for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
                cip2 = cip1->item_next;
-               sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               if (cip1->created_ok) {
+                       sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               }
                pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
                kfree(cip1);
        }
@@ -675,12 +705,22 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
        pvr2_sysfs_tear_down_debugifc(sfp);
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
        pvr2_sysfs_tear_down_controls(sfp);
-       class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
-       class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+       if (sfp->v4l_minor_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_minor_number);
+       }
+       if (sfp->v4l_radio_minor_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_radio_minor_number);
+       }
+       if (sfp->unit_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_unit_number);
+       }
        pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
-       sfp->class_dev->class_data = 0;
+       sfp->class_dev->class_data = NULL;
        class_device_unregister(sfp->class_dev);
-       sfp->class_dev = 0;
+       sfp->class_dev = NULL;
 }
 
 
@@ -690,7 +730,20 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
        sfp = (struct pvr2_sysfs *)class_dev->class_data;
        if (!sfp) return -EINVAL;
        return scnprintf(buf,PAGE_SIZE,"%d\n",
-                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw));
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_video));
+}
+
+
+static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev,
+                                          char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_radio));
 }
 
 
@@ -709,11 +762,12 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 {
        struct usb_device *usb_dev;
        struct class_device *class_dev;
+       int ret;
+
        usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
        if (!usb_dev) return;
-       class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
+       class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
        if (!class_dev) return;
-       memset(class_dev,0,sizeof(*class_dev));
 
        pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 
@@ -733,20 +787,54 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 
        sfp->class_dev = class_dev;
        class_dev->class_data = sfp;
-       class_device_register(class_dev);
+       ret = class_device_register(class_dev);
+       if (ret) {
+               printk(KERN_ERR "%s: class_device_register failed\n",
+                      __FUNCTION__);
+               kfree(class_dev);
+               return;
+       }
 
        sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
        sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
        sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
        sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
-       sfp->attr_v4l_minor_number.store = 0;
-       class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+       sfp->attr_v4l_minor_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_minor_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->v4l_minor_number_created_ok = !0;
+       }
+
+       sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE;
+       sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
+       sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
+       sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
+       sfp->attr_v4l_radio_minor_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_radio_minor_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->v4l_radio_minor_number_created_ok = !0;
+       }
+
        sfp->attr_unit_number.attr.owner = THIS_MODULE;
        sfp->attr_unit_number.attr.name = "unit_number";
        sfp->attr_unit_number.attr.mode = S_IRUGO;
        sfp->attr_unit_number.show = unit_number_show;
-       sfp->attr_unit_number.store = 0;
-       class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+       sfp->attr_unit_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->unit_number_created_ok = !0;
+       }
 
        pvr2_sysfs_add_controls(sfp);
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -771,9 +859,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
                                     struct pvr2_sysfs_class *class_ptr)
 {
        struct pvr2_sysfs *sfp;
-       sfp = kmalloc(sizeof(*sfp),GFP_KERNEL);
+       sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
        if (!sfp) return sfp;
-       memset(sfp,0,sizeof(*sfp));
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
        pvr2_channel_init(&sfp->channel,mp);
        sfp->channel.check_func = pvr2_sysfs_internal_check;
@@ -794,9 +881,8 @@ static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp,
 struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 {
        struct pvr2_sysfs_class *clp;
-       clp = kmalloc(sizeof(*clp),GFP_KERNEL);
+       clp = kzalloc(sizeof(*clp),GFP_KERNEL);
        if (!clp) return clp;
-       memset(clp,0,sizeof(*clp));
        pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
        clp->class.name = "pvrusb2";
        clp->class.class_release = pvr2_sysfs_class_release;
@@ -806,7 +892,7 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
                pvr2_sysfs_trace(
                        "Registration failed for pvr2_sysfs_class id=%p",clp);
                kfree(clp);
-               clp = 0;
+               clp = NULL;
        }
        return clp;
 }