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