linux/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
<<
>>
Prefs
   1/*
   2 *
   3 *
   4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 *
  19 */
  20
  21#include <linux/string.h>
  22#include <linux/slab.h>
  23#include "pvrusb2-sysfs.h"
  24#include "pvrusb2-hdw.h"
  25#include "pvrusb2-debug.h"
  26#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
  27#include "pvrusb2-debugifc.h"
  28#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
  29
  30#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
  31
  32struct pvr2_sysfs {
  33        struct pvr2_channel channel;
  34        struct device *class_dev;
  35#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
  36        struct pvr2_sysfs_debugifc *debugifc;
  37#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
  38        struct pvr2_sysfs_ctl_item *item_first;
  39        struct pvr2_sysfs_ctl_item *item_last;
  40        struct device_attribute attr_v4l_minor_number;
  41        struct device_attribute attr_v4l_radio_minor_number;
  42        struct device_attribute attr_unit_number;
  43        struct device_attribute attr_bus_info;
  44        struct device_attribute attr_hdw_name;
  45        struct device_attribute attr_hdw_desc;
  46        int v4l_minor_number_created_ok;
  47        int v4l_radio_minor_number_created_ok;
  48        int unit_number_created_ok;
  49        int bus_info_created_ok;
  50        int hdw_name_created_ok;
  51        int hdw_desc_created_ok;
  52};
  53
  54#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
  55struct pvr2_sysfs_debugifc {
  56        struct device_attribute attr_debugcmd;
  57        struct device_attribute attr_debuginfo;
  58        int debugcmd_created_ok;
  59        int debuginfo_created_ok;
  60};
  61#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
  62
  63struct pvr2_sysfs_ctl_item {
  64        struct device_attribute attr_name;
  65        struct device_attribute attr_type;
  66        struct device_attribute attr_min;
  67        struct device_attribute attr_max;
  68        struct device_attribute attr_def;
  69        struct device_attribute attr_enum;
  70        struct device_attribute attr_bits;
  71        struct device_attribute attr_val;
  72        struct device_attribute attr_custom;
  73        struct pvr2_ctrl *cptr;
  74        int ctl_id;
  75        struct pvr2_sysfs *chptr;
  76        struct pvr2_sysfs_ctl_item *item_next;
  77        struct attribute *attr_gen[8];
  78        struct attribute_group grp;
  79        int created_ok;
  80        char name[80];
  81};
  82
  83struct pvr2_sysfs_class {
  84        struct class class;
  85};
  86
  87static ssize_t show_name(struct device *class_dev,
  88                         struct device_attribute *attr,
  89                         char *buf)
  90{
  91        struct pvr2_sysfs_ctl_item *cip;
  92        const char *name;
  93        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
  94        name = pvr2_ctrl_get_desc(cip->cptr);
  95        pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
  96                         cip->chptr, cip->ctl_id, name);
  97        if (!name) return -EINVAL;
  98        return scnprintf(buf, PAGE_SIZE, "%s\n", name);
  99}
 100
 101static ssize_t show_type(struct device *class_dev,
 102                         struct device_attribute *attr,
 103                         char *buf)
 104{
 105        struct pvr2_sysfs_ctl_item *cip;
 106        const char *name;
 107        enum pvr2_ctl_type tp;
 108        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
 109        tp = pvr2_ctrl_get_type(cip->cptr);
 110        switch (tp) {
 111        case pvr2_ctl_int: name = "integer"; break;
 112        case pvr2_ctl_enum: name = "enum"; break;
 113        case pvr2_ctl_bitmask: name = "bitmask"; break;
 114        case pvr2_ctl_bool: name = "boolean"; break;
 115        default: name = "?"; break;
 116        }
 117        pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
 118                         cip->chptr, cip->ctl_id, name);
 119        if (!name) return -EINVAL;
 120        return scnprintf(buf, PAGE_SIZE, "%s\n", name);
 121}
 122
 123static ssize_t show_min(struct device *class_dev,
 124                        struct device_attribute *attr,
 125                        char *buf)
 126{
 127        struct pvr2_sysfs_ctl_item *cip;
 128        long val;
 129        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
 130        val = pvr2_ctrl_get_min(cip->cptr);
 131        pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
 132                         cip->chptr, cip->ctl_id, val);
 133        return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
 134}
 135
 136static ssize_t show_max(struct device *class_dev,
 137                        struct device_attribute *attr,
 138                        char *buf)
 139{
 140        struct pvr2_sysfs_ctl_item *cip;
 141        long val;
 142        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
 143        val = pvr2_ctrl_get_max(cip->cptr);
 144        pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
 145                         cip->chptr, cip->ctl_id, val);
 146        return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
 147}
 148
 149static ssize_t show_def(struct device *class_dev,
 150                        struct device_attribute *attr,
 151                        char *buf)
 152{
 153        struct pvr2_sysfs_ctl_item *cip;
 154        int val;
 155        int ret;
 156        unsigned int cnt = 0;
 157        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
 158        ret = pvr2_ctrl_get_def(cip->cptr, &val);
 159        if (ret < 0) return ret;
 160        ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
 161                                     buf, PAGE_SIZE - 1, &cnt);
 162        pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
 163                         cip->chptr, cip->ctl_id, cnt, buf, val);
 164        buf[cnt] = '\n';
 165        return cnt + 1;
 166}
 167
 168static ssize_t show_val_norm(struct device *class_dev,
 169                             struct device_attribute *attr,
 170                             char *buf)
 171{
 172        struct pvr2_sysfs_ctl_item *cip;
 173        int val;
 174        int ret;
 175        unsigned int cnt = 0;
 176        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
 177        ret = pvr2_ctrl_get_value(cip->cptr, &val);
 178        if (ret < 0) return ret;
 179        ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
 180                                     buf, PAGE_SIZE - 1, &cnt);
 181        pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
 182                         cip->chptr, cip->ctl_id, cnt, buf, val);
 183        buf[cnt] = '\n';
 184        return cnt+1;
 185}
 186
 187static ssize_t show_val_custom(struct device *class_dev,
 188                               struct device_attribute *attr,
 189                               char *buf)
 190{
 191        struct pvr2_sysfs_ctl_item *cip;
 192        int val;
 193        int ret;
 194        unsigned int cnt = 0;
 195        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
 196        ret = pvr2_ctrl_get_value(cip->cptr, &val);
 197        if (ret < 0) return ret;
 198        ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
 199                                            buf, PAGE_SIZE - 1, &cnt);
 200        pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
 201                         cip->chptr, cip->ctl_id, cnt, buf, val);
 202        buf[cnt] = '\n';
 203        return cnt+1;
 204}
 205
 206static ssize_t show_enum(struct device *class_dev,
 207                         struct device_attribute *attr,
 208                         char *buf)
 209{
 210        struct pvr2_sysfs_ctl_item *cip;
 211        long val;
 212        unsigned int bcnt, ccnt, ecnt;
 213        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
 214        ecnt = pvr2_ctrl_get_cnt(cip->cptr);
 215        bcnt = 0;
 216        for (val = 0; val < ecnt; val++) {
 217                pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
 218                                      PAGE_SIZE - bcnt, &ccnt);
 219                if (!ccnt) continue;
 220                bcnt += ccnt;
 221                if (bcnt >= PAGE_SIZE) break;
 222                buf[bcnt] = '\n';
 223                bcnt++;
 224        }
 225        pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
 226                         cip->chptr, cip->ctl_id);
 227        return bcnt;
 228}
 229
 230static ssize_t show_bits(struct device *class_dev,
 231                         struct device_attribute *attr,
 232                         char *buf)
 233{
 234        struct pvr2_sysfs_ctl_item *cip;
 235        int valid_bits, msk;
 236        unsigned int bcnt, ccnt;
 237        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
 238        valid_bits = pvr2_ctrl_get_mask(cip->cptr);
 239        bcnt = 0;
 240        for (msk = 1; valid_bits; msk <<= 1) {
 241                if (!(msk & valid_bits)) continue;
 242                valid_bits &= ~msk;
 243                pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
 244                                      PAGE_SIZE - bcnt, &ccnt);
 245                bcnt += ccnt;
 246                if (bcnt >= PAGE_SIZE) break;
 247                buf[bcnt] = '\n';
 248                bcnt++;
 249        }
 250        pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
 251                         cip->chptr, cip->ctl_id);
 252        return bcnt;
 253}
 254
 255static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
 256                         const char *buf,unsigned int count)
 257{
 258        int ret;
 259        int mask,val;
 260        if (customfl) {
 261                ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
 262                                                    &mask, &val);
 263        } else {
 264                ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
 265                                             &mask, &val);
 266        }
 267        if (ret < 0) return ret;
 268        ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
 269        pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
 270        return ret;
 271}
 272
 273static ssize_t store_val_norm(struct device *class_dev,
 274                              struct device_attribute *attr,
 275                              const char *buf, size_t count)
 276{
 277        struct pvr2_sysfs_ctl_item *cip;
 278        int ret;
 279        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
 280        pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
 281                         cip->chptr, cip->ctl_id, (int)count, buf);
 282        ret = store_val_any(cip, 0, buf, count);
 283        if (!ret) ret = count;
 284        return ret;
 285}
 286
 287static ssize_t store_val_custom(struct device *class_dev,
 288                                struct device_attribute *attr,
 289                                const char *buf, size_t count)
 290{
 291        struct pvr2_sysfs_ctl_item *cip;
 292        int ret;
 293        cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
 294        pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
 295                         cip->chptr, cip->ctl_id, (int)count, buf);
 296        ret = store_val_any(cip, 1, buf, count);
 297        if (!ret) ret = count;
 298        return ret;
 299}
 300
 301static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
 302{
 303        struct pvr2_sysfs_ctl_item *cip;
 304        struct pvr2_ctrl *cptr;
 305        unsigned int cnt,acnt;
 306        int ret;
 307
 308        cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
 309        if (!cptr) return;
 310
 311        cip = kzalloc(sizeof(*cip),GFP_KERNEL);
 312        if (!cip) return;
 313        pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
 314
 315        cip->cptr = cptr;
 316        cip->ctl_id = ctl_id;
 317
 318        cip->chptr = sfp;
 319        cip->item_next = NULL;
 320        if (sfp->item_last) {
 321                sfp->item_last->item_next = cip;
 322        } else {
 323                sfp->item_first = cip;
 324        }
 325        sfp->item_last = cip;
 326
 327        sysfs_attr_init(&cip->attr_name.attr);
 328        cip->attr_name.attr.name = "name";
 329        cip->attr_name.attr.mode = S_IRUGO;
 330        cip->attr_name.show = show_name;
 331
 332        sysfs_attr_init(&cip->attr_type.attr);
 333        cip->attr_type.attr.name = "type";
 334        cip->attr_type.attr.mode = S_IRUGO;
 335        cip->attr_type.show = show_type;
 336
 337        sysfs_attr_init(&cip->attr_min.attr);
 338        cip->attr_min.attr.name = "min_val";
 339        cip->attr_min.attr.mode = S_IRUGO;
 340        cip->attr_min.show = show_min;
 341
 342        sysfs_attr_init(&cip->attr_max.attr);
 343        cip->attr_max.attr.name = "max_val";
 344        cip->attr_max.attr.mode = S_IRUGO;
 345        cip->attr_max.show = show_max;
 346
 347        sysfs_attr_init(&cip->attr_def.attr);
 348        cip->attr_def.attr.name = "def_val";
 349        cip->attr_def.attr.mode = S_IRUGO;
 350        cip->attr_def.show = show_def;
 351
 352        sysfs_attr_init(&cip->attr_val.attr);
 353        cip->attr_val.attr.name = "cur_val";
 354        cip->attr_val.attr.mode = S_IRUGO;
 355
 356        sysfs_attr_init(&cip->attr_custom.attr);
 357        cip->attr_custom.attr.name = "custom_val";
 358        cip->attr_custom.attr.mode = S_IRUGO;
 359
 360        sysfs_attr_init(&cip->attr_enum.attr);
 361        cip->attr_enum.attr.name = "enum_val";
 362        cip->attr_enum.attr.mode = S_IRUGO;
 363        cip->attr_enum.show = show_enum;
 364
 365        sysfs_attr_init(&cip->attr_bits.attr);
 366        cip->attr_bits.attr.name = "bit_val";
 367        cip->attr_bits.attr.mode = S_IRUGO;
 368        cip->attr_bits.show = show_bits;
 369
 370        if (pvr2_ctrl_is_writable(cptr)) {
 371                cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
 372                cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
 373        }
 374
 375        acnt = 0;
 376        cip->attr_gen[acnt++] = &cip->attr_name.attr;
 377        cip->attr_gen[acnt++] = &cip->attr_type.attr;
 378        cip->attr_gen[acnt++] = &cip->attr_val.attr;
 379        cip->attr_gen[acnt++] = &cip->attr_def.attr;
 380        cip->attr_val.show = show_val_norm;
 381        cip->attr_val.store = store_val_norm;
 382        if (pvr2_ctrl_has_custom_symbols(cptr)) {
 383                cip->attr_gen[acnt++] = &cip->attr_custom.attr;
 384                cip->attr_custom.show = show_val_custom;
 385                cip->attr_custom.store = store_val_custom;
 386        }
 387        switch (pvr2_ctrl_get_type(cptr)) {
 388        case pvr2_ctl_enum:
 389                // Control is an enumeration
 390                cip->attr_gen[acnt++] = &cip->attr_enum.attr;
 391                break;
 392        case pvr2_ctl_int:
 393                // Control is an integer
 394                cip->attr_gen[acnt++] = &cip->attr_min.attr;
 395                cip->attr_gen[acnt++] = &cip->attr_max.attr;
 396                break;
 397        case pvr2_ctl_bitmask:
 398                // Control is an bitmask
 399                cip->attr_gen[acnt++] = &cip->attr_bits.attr;
 400                break;
 401        default: break;
 402        }
 403
 404        cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
 405                        pvr2_ctrl_get_name(cptr));
 406        cip->name[cnt] = 0;
 407        cip->grp.name = cip->name;
 408        cip->grp.attrs = cip->attr_gen;
 409
 410        ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
 411        if (ret) {
 412                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 413                           "sysfs_create_group error: %d",
 414                           ret);
 415                return;
 416        }
 417        cip->created_ok = !0;
 418}
 419
 420#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 421static ssize_t debuginfo_show(struct device *, struct device_attribute *,
 422                              char *);
 423static ssize_t debugcmd_show(struct device *, struct device_attribute *,
 424                             char *);
 425static ssize_t debugcmd_store(struct device *, struct device_attribute *,
 426                              const char *, size_t count);
 427
 428static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
 429{
 430        struct pvr2_sysfs_debugifc *dip;
 431        int ret;
 432
 433        dip = kzalloc(sizeof(*dip),GFP_KERNEL);
 434        if (!dip) return;
 435        sysfs_attr_init(&dip->attr_debugcmd.attr);
 436        dip->attr_debugcmd.attr.name = "debugcmd";
 437        dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
 438        dip->attr_debugcmd.show = debugcmd_show;
 439        dip->attr_debugcmd.store = debugcmd_store;
 440        sysfs_attr_init(&dip->attr_debuginfo.attr);
 441        dip->attr_debuginfo.attr.name = "debuginfo";
 442        dip->attr_debuginfo.attr.mode = S_IRUGO;
 443        dip->attr_debuginfo.show = debuginfo_show;
 444        sfp->debugifc = dip;
 445        ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
 446        if (ret < 0) {
 447                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 448                           "device_create_file error: %d",
 449                           ret);
 450        } else {
 451                dip->debugcmd_created_ok = !0;
 452        }
 453        ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
 454        if (ret < 0) {
 455                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 456                           "device_create_file error: %d",
 457                           ret);
 458        } else {
 459                dip->debuginfo_created_ok = !0;
 460        }
 461}
 462
 463
 464static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
 465{
 466        if (!sfp->debugifc) return;
 467        if (sfp->debugifc->debuginfo_created_ok) {
 468                device_remove_file(sfp->class_dev,
 469                                         &sfp->debugifc->attr_debuginfo);
 470        }
 471        if (sfp->debugifc->debugcmd_created_ok) {
 472                device_remove_file(sfp->class_dev,
 473                                         &sfp->debugifc->attr_debugcmd);
 474        }
 475        kfree(sfp->debugifc);
 476        sfp->debugifc = NULL;
 477}
 478#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 479
 480
 481static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
 482{
 483        unsigned int idx,cnt;
 484        cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
 485        for (idx = 0; idx < cnt; idx++) {
 486                pvr2_sysfs_add_control(sfp,idx);
 487        }
 488}
 489
 490
 491static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
 492{
 493        struct pvr2_sysfs_ctl_item *cip1,*cip2;
 494        for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
 495                cip2 = cip1->item_next;
 496                if (cip1->created_ok) {
 497                        sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
 498                }
 499                pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
 500                kfree(cip1);
 501        }
 502}
 503
 504
 505static void pvr2_sysfs_class_release(struct class *class)
 506{
 507        struct pvr2_sysfs_class *clp;
 508        clp = container_of(class,struct pvr2_sysfs_class,class);
 509        pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
 510        kfree(clp);
 511}
 512
 513
 514static void pvr2_sysfs_release(struct device *class_dev)
 515{
 516        pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
 517        kfree(class_dev);
 518}
 519
 520
 521static void class_dev_destroy(struct pvr2_sysfs *sfp)
 522{
 523        struct device *dev;
 524        if (!sfp->class_dev) return;
 525#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 526        pvr2_sysfs_tear_down_debugifc(sfp);
 527#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 528        pvr2_sysfs_tear_down_controls(sfp);
 529        if (sfp->hdw_desc_created_ok) {
 530                device_remove_file(sfp->class_dev,
 531                                   &sfp->attr_hdw_desc);
 532        }
 533        if (sfp->hdw_name_created_ok) {
 534                device_remove_file(sfp->class_dev,
 535                                   &sfp->attr_hdw_name);
 536        }
 537        if (sfp->bus_info_created_ok) {
 538                device_remove_file(sfp->class_dev,
 539                                         &sfp->attr_bus_info);
 540        }
 541        if (sfp->v4l_minor_number_created_ok) {
 542                device_remove_file(sfp->class_dev,
 543                                         &sfp->attr_v4l_minor_number);
 544        }
 545        if (sfp->v4l_radio_minor_number_created_ok) {
 546                device_remove_file(sfp->class_dev,
 547                                         &sfp->attr_v4l_radio_minor_number);
 548        }
 549        if (sfp->unit_number_created_ok) {
 550                device_remove_file(sfp->class_dev,
 551                                         &sfp->attr_unit_number);
 552        }
 553        pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
 554        dev_set_drvdata(sfp->class_dev, NULL);
 555        dev = sfp->class_dev->parent;
 556        sfp->class_dev->parent = NULL;
 557        put_device(dev);
 558        device_unregister(sfp->class_dev);
 559        sfp->class_dev = NULL;
 560}
 561
 562
 563static ssize_t v4l_minor_number_show(struct device *class_dev,
 564                                     struct device_attribute *attr, char *buf)
 565{
 566        struct pvr2_sysfs *sfp;
 567        sfp = dev_get_drvdata(class_dev);
 568        if (!sfp) return -EINVAL;
 569        return scnprintf(buf,PAGE_SIZE,"%d\n",
 570                         pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
 571                                                       pvr2_v4l_type_video));
 572}
 573
 574
 575static ssize_t bus_info_show(struct device *class_dev,
 576                             struct device_attribute *attr, char *buf)
 577{
 578        struct pvr2_sysfs *sfp;
 579        sfp = dev_get_drvdata(class_dev);
 580        if (!sfp) return -EINVAL;
 581        return scnprintf(buf,PAGE_SIZE,"%s\n",
 582                         pvr2_hdw_get_bus_info(sfp->channel.hdw));
 583}
 584
 585
 586static ssize_t hdw_name_show(struct device *class_dev,
 587                             struct device_attribute *attr, char *buf)
 588{
 589        struct pvr2_sysfs *sfp;
 590        sfp = dev_get_drvdata(class_dev);
 591        if (!sfp) return -EINVAL;
 592        return scnprintf(buf,PAGE_SIZE,"%s\n",
 593                         pvr2_hdw_get_type(sfp->channel.hdw));
 594}
 595
 596
 597static ssize_t hdw_desc_show(struct device *class_dev,
 598                             struct device_attribute *attr, char *buf)
 599{
 600        struct pvr2_sysfs *sfp;
 601        sfp = dev_get_drvdata(class_dev);
 602        if (!sfp) return -EINVAL;
 603        return scnprintf(buf,PAGE_SIZE,"%s\n",
 604                         pvr2_hdw_get_desc(sfp->channel.hdw));
 605}
 606
 607
 608static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
 609                                           struct device_attribute *attr,
 610                                           char *buf)
 611{
 612        struct pvr2_sysfs *sfp;
 613        sfp = dev_get_drvdata(class_dev);
 614        if (!sfp) return -EINVAL;
 615        return scnprintf(buf,PAGE_SIZE,"%d\n",
 616                         pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
 617                                                       pvr2_v4l_type_radio));
 618}
 619
 620
 621static ssize_t unit_number_show(struct device *class_dev,
 622                                struct device_attribute *attr, char *buf)
 623{
 624        struct pvr2_sysfs *sfp;
 625        sfp = dev_get_drvdata(class_dev);
 626        if (!sfp) return -EINVAL;
 627        return scnprintf(buf,PAGE_SIZE,"%d\n",
 628                         pvr2_hdw_get_unit_number(sfp->channel.hdw));
 629}
 630
 631
 632static void class_dev_create(struct pvr2_sysfs *sfp,
 633                             struct pvr2_sysfs_class *class_ptr)
 634{
 635        struct usb_device *usb_dev;
 636        struct device *class_dev;
 637        int ret;
 638
 639        usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
 640        if (!usb_dev) return;
 641        class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
 642        if (!class_dev) return;
 643
 644        pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 645
 646        class_dev->class = &class_ptr->class;
 647
 648        dev_set_name(class_dev, "%s",
 649                     pvr2_hdw_get_device_identifier(sfp->channel.hdw));
 650
 651        class_dev->parent = get_device(&usb_dev->dev);
 652
 653        sfp->class_dev = class_dev;
 654        dev_set_drvdata(class_dev, sfp);
 655        ret = device_register(class_dev);
 656        if (ret) {
 657                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 658                           "device_register failed");
 659                put_device(class_dev);
 660                return;
 661        }
 662
 663        sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
 664        sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
 665        sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
 666        sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
 667        sfp->attr_v4l_minor_number.store = NULL;
 668        ret = device_create_file(sfp->class_dev,
 669                                       &sfp->attr_v4l_minor_number);
 670        if (ret < 0) {
 671                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 672                           "device_create_file error: %d",
 673                           ret);
 674        } else {
 675                sfp->v4l_minor_number_created_ok = !0;
 676        }
 677
 678        sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
 679        sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
 680        sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
 681        sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
 682        sfp->attr_v4l_radio_minor_number.store = NULL;
 683        ret = device_create_file(sfp->class_dev,
 684                                       &sfp->attr_v4l_radio_minor_number);
 685        if (ret < 0) {
 686                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 687                           "device_create_file error: %d",
 688                           ret);
 689        } else {
 690                sfp->v4l_radio_minor_number_created_ok = !0;
 691        }
 692
 693        sysfs_attr_init(&sfp->attr_unit_number.attr);
 694        sfp->attr_unit_number.attr.name = "unit_number";
 695        sfp->attr_unit_number.attr.mode = S_IRUGO;
 696        sfp->attr_unit_number.show = unit_number_show;
 697        sfp->attr_unit_number.store = NULL;
 698        ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
 699        if (ret < 0) {
 700                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 701                           "device_create_file error: %d",
 702                           ret);
 703        } else {
 704                sfp->unit_number_created_ok = !0;
 705        }
 706
 707        sysfs_attr_init(&sfp->attr_bus_info.attr);
 708        sfp->attr_bus_info.attr.name = "bus_info_str";
 709        sfp->attr_bus_info.attr.mode = S_IRUGO;
 710        sfp->attr_bus_info.show = bus_info_show;
 711        sfp->attr_bus_info.store = NULL;
 712        ret = device_create_file(sfp->class_dev,
 713                                       &sfp->attr_bus_info);
 714        if (ret < 0) {
 715                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 716                           "device_create_file error: %d",
 717                           ret);
 718        } else {
 719                sfp->bus_info_created_ok = !0;
 720        }
 721
 722        sysfs_attr_init(&sfp->attr_hdw_name.attr);
 723        sfp->attr_hdw_name.attr.name = "device_hardware_type";
 724        sfp->attr_hdw_name.attr.mode = S_IRUGO;
 725        sfp->attr_hdw_name.show = hdw_name_show;
 726        sfp->attr_hdw_name.store = NULL;
 727        ret = device_create_file(sfp->class_dev,
 728                                 &sfp->attr_hdw_name);
 729        if (ret < 0) {
 730                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 731                           "device_create_file error: %d",
 732                           ret);
 733        } else {
 734                sfp->hdw_name_created_ok = !0;
 735        }
 736
 737        sysfs_attr_init(&sfp->attr_hdw_desc.attr);
 738        sfp->attr_hdw_desc.attr.name = "device_hardware_description";
 739        sfp->attr_hdw_desc.attr.mode = S_IRUGO;
 740        sfp->attr_hdw_desc.show = hdw_desc_show;
 741        sfp->attr_hdw_desc.store = NULL;
 742        ret = device_create_file(sfp->class_dev,
 743                                 &sfp->attr_hdw_desc);
 744        if (ret < 0) {
 745                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 746                           "device_create_file error: %d",
 747                           ret);
 748        } else {
 749                sfp->hdw_desc_created_ok = !0;
 750        }
 751
 752        pvr2_sysfs_add_controls(sfp);
 753#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 754        pvr2_sysfs_add_debugifc(sfp);
 755#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 756}
 757
 758
 759static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
 760{
 761        struct pvr2_sysfs *sfp;
 762        sfp = container_of(chp,struct pvr2_sysfs,channel);
 763        if (!sfp->channel.mc_head->disconnect_flag) return;
 764        pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
 765        class_dev_destroy(sfp);
 766        pvr2_channel_done(&sfp->channel);
 767        kfree(sfp);
 768}
 769
 770
 771struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
 772                                     struct pvr2_sysfs_class *class_ptr)
 773{
 774        struct pvr2_sysfs *sfp;
 775        sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
 776        if (!sfp) return sfp;
 777        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
 778        pvr2_channel_init(&sfp->channel,mp);
 779        sfp->channel.check_func = pvr2_sysfs_internal_check;
 780
 781        class_dev_create(sfp,class_ptr);
 782        return sfp;
 783}
 784
 785
 786
 787struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 788{
 789        struct pvr2_sysfs_class *clp;
 790        clp = kzalloc(sizeof(*clp),GFP_KERNEL);
 791        if (!clp) return clp;
 792        pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
 793                         clp);
 794        clp->class.name = "pvrusb2";
 795        clp->class.class_release = pvr2_sysfs_class_release;
 796        clp->class.dev_release = pvr2_sysfs_release;
 797        if (class_register(&clp->class)) {
 798                pvr2_sysfs_trace(
 799                        "Registration failed for pvr2_sysfs_class id=%p",clp);
 800                kfree(clp);
 801                clp = NULL;
 802        }
 803        return clp;
 804}
 805
 806
 807void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
 808{
 809        pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
 810        class_unregister(&clp->class);
 811}
 812
 813
 814#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 815static ssize_t debuginfo_show(struct device *class_dev,
 816                              struct device_attribute *attr, char *buf)
 817{
 818        struct pvr2_sysfs *sfp;
 819        sfp = dev_get_drvdata(class_dev);
 820        if (!sfp) return -EINVAL;
 821        pvr2_hdw_trigger_module_log(sfp->channel.hdw);
 822        return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
 823}
 824
 825
 826static ssize_t debugcmd_show(struct device *class_dev,
 827                             struct device_attribute *attr, char *buf)
 828{
 829        struct pvr2_sysfs *sfp;
 830        sfp = dev_get_drvdata(class_dev);
 831        if (!sfp) return -EINVAL;
 832        return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
 833}
 834
 835
 836static ssize_t debugcmd_store(struct device *class_dev,
 837                              struct device_attribute *attr,
 838                              const char *buf, size_t count)
 839{
 840        struct pvr2_sysfs *sfp;
 841        int ret;
 842
 843        sfp = dev_get_drvdata(class_dev);
 844        if (!sfp) return -EINVAL;
 845
 846        ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
 847        if (ret < 0) return ret;
 848        return count;
 849}
 850#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 851