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