0001
0002
0003
0004
0005
0006
0007 #include <linux/string.h>
0008 #include <linux/slab.h>
0009 #include "pvrusb2-sysfs.h"
0010 #include "pvrusb2-hdw.h"
0011 #include "pvrusb2-debug.h"
0012 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0013 #include "pvrusb2-debugifc.h"
0014 #endif
0015
0016 #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
0017
0018 struct pvr2_sysfs {
0019 struct pvr2_channel channel;
0020 struct device *class_dev;
0021 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0022 struct pvr2_sysfs_debugifc *debugifc;
0023 #endif
0024 struct pvr2_sysfs_ctl_item *item_first;
0025 struct pvr2_sysfs_ctl_item *item_last;
0026 struct device_attribute attr_v4l_minor_number;
0027 struct device_attribute attr_v4l_radio_minor_number;
0028 struct device_attribute attr_unit_number;
0029 struct device_attribute attr_bus_info;
0030 struct device_attribute attr_hdw_name;
0031 struct device_attribute attr_hdw_desc;
0032 int v4l_minor_number_created_ok;
0033 int v4l_radio_minor_number_created_ok;
0034 int unit_number_created_ok;
0035 int bus_info_created_ok;
0036 int hdw_name_created_ok;
0037 int hdw_desc_created_ok;
0038 };
0039
0040 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0041 struct pvr2_sysfs_debugifc {
0042 struct device_attribute attr_debugcmd;
0043 struct device_attribute attr_debuginfo;
0044 int debugcmd_created_ok;
0045 int debuginfo_created_ok;
0046 };
0047 #endif
0048
0049 struct pvr2_sysfs_ctl_item {
0050 struct device_attribute attr_name;
0051 struct device_attribute attr_type;
0052 struct device_attribute attr_min;
0053 struct device_attribute attr_max;
0054 struct device_attribute attr_def;
0055 struct device_attribute attr_enum;
0056 struct device_attribute attr_bits;
0057 struct device_attribute attr_val;
0058 struct device_attribute attr_custom;
0059 struct pvr2_ctrl *cptr;
0060 int ctl_id;
0061 struct pvr2_sysfs *chptr;
0062 struct pvr2_sysfs_ctl_item *item_next;
0063 struct attribute *attr_gen[8];
0064 struct attribute_group grp;
0065 int created_ok;
0066 char name[80];
0067 };
0068
0069 struct pvr2_sysfs_class {
0070 struct class class;
0071 };
0072
0073 static ssize_t show_name(struct device *class_dev,
0074 struct device_attribute *attr,
0075 char *buf)
0076 {
0077 struct pvr2_sysfs_ctl_item *cip;
0078 const char *name;
0079 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
0080 name = pvr2_ctrl_get_desc(cip->cptr);
0081 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
0082 cip->chptr, cip->ctl_id, name);
0083 if (!name) return -EINVAL;
0084 return scnprintf(buf, PAGE_SIZE, "%s\n", name);
0085 }
0086
0087 static ssize_t show_type(struct device *class_dev,
0088 struct device_attribute *attr,
0089 char *buf)
0090 {
0091 struct pvr2_sysfs_ctl_item *cip;
0092 const char *name;
0093 enum pvr2_ctl_type tp;
0094 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
0095 tp = pvr2_ctrl_get_type(cip->cptr);
0096 switch (tp) {
0097 case pvr2_ctl_int: name = "integer"; break;
0098 case pvr2_ctl_enum: name = "enum"; break;
0099 case pvr2_ctl_bitmask: name = "bitmask"; break;
0100 case pvr2_ctl_bool: name = "boolean"; break;
0101 default: name = "?"; break;
0102 }
0103 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
0104 cip->chptr, cip->ctl_id, name);
0105 return scnprintf(buf, PAGE_SIZE, "%s\n", name);
0106 }
0107
0108 static ssize_t show_min(struct device *class_dev,
0109 struct device_attribute *attr,
0110 char *buf)
0111 {
0112 struct pvr2_sysfs_ctl_item *cip;
0113 long val;
0114 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
0115 val = pvr2_ctrl_get_min(cip->cptr);
0116 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
0117 cip->chptr, cip->ctl_id, val);
0118 return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
0119 }
0120
0121 static ssize_t show_max(struct device *class_dev,
0122 struct device_attribute *attr,
0123 char *buf)
0124 {
0125 struct pvr2_sysfs_ctl_item *cip;
0126 long val;
0127 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
0128 val = pvr2_ctrl_get_max(cip->cptr);
0129 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
0130 cip->chptr, cip->ctl_id, val);
0131 return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
0132 }
0133
0134 static ssize_t show_def(struct device *class_dev,
0135 struct device_attribute *attr,
0136 char *buf)
0137 {
0138 struct pvr2_sysfs_ctl_item *cip;
0139 int val;
0140 int ret;
0141 unsigned int cnt = 0;
0142 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
0143 ret = pvr2_ctrl_get_def(cip->cptr, &val);
0144 if (ret < 0) return ret;
0145 ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
0146 buf, PAGE_SIZE - 1, &cnt);
0147 pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
0148 cip->chptr, cip->ctl_id, cnt, buf, val);
0149 buf[cnt] = '\n';
0150 return cnt + 1;
0151 }
0152
0153 static ssize_t show_val_norm(struct device *class_dev,
0154 struct device_attribute *attr,
0155 char *buf)
0156 {
0157 struct pvr2_sysfs_ctl_item *cip;
0158 int val;
0159 int ret;
0160 unsigned int cnt = 0;
0161 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
0162 ret = pvr2_ctrl_get_value(cip->cptr, &val);
0163 if (ret < 0) return ret;
0164 ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
0165 buf, PAGE_SIZE - 1, &cnt);
0166 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
0167 cip->chptr, cip->ctl_id, cnt, buf, val);
0168 buf[cnt] = '\n';
0169 return cnt+1;
0170 }
0171
0172 static ssize_t show_val_custom(struct device *class_dev,
0173 struct device_attribute *attr,
0174 char *buf)
0175 {
0176 struct pvr2_sysfs_ctl_item *cip;
0177 int val;
0178 int ret;
0179 unsigned int cnt = 0;
0180 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
0181 ret = pvr2_ctrl_get_value(cip->cptr, &val);
0182 if (ret < 0) return ret;
0183 ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
0184 buf, PAGE_SIZE - 1, &cnt);
0185 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
0186 cip->chptr, cip->ctl_id, cnt, buf, val);
0187 buf[cnt] = '\n';
0188 return cnt+1;
0189 }
0190
0191 static ssize_t show_enum(struct device *class_dev,
0192 struct device_attribute *attr,
0193 char *buf)
0194 {
0195 struct pvr2_sysfs_ctl_item *cip;
0196 long val;
0197 unsigned int bcnt, ccnt, ecnt;
0198 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
0199 ecnt = pvr2_ctrl_get_cnt(cip->cptr);
0200 bcnt = 0;
0201 for (val = 0; val < ecnt; val++) {
0202 pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
0203 PAGE_SIZE - bcnt, &ccnt);
0204 if (!ccnt) continue;
0205 bcnt += ccnt;
0206 if (bcnt >= PAGE_SIZE) break;
0207 buf[bcnt] = '\n';
0208 bcnt++;
0209 }
0210 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
0211 cip->chptr, cip->ctl_id);
0212 return bcnt;
0213 }
0214
0215 static ssize_t show_bits(struct device *class_dev,
0216 struct device_attribute *attr,
0217 char *buf)
0218 {
0219 struct pvr2_sysfs_ctl_item *cip;
0220 int valid_bits, msk;
0221 unsigned int bcnt, ccnt;
0222 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
0223 valid_bits = pvr2_ctrl_get_mask(cip->cptr);
0224 bcnt = 0;
0225 for (msk = 1; valid_bits; msk <<= 1) {
0226 if (!(msk & valid_bits)) continue;
0227 valid_bits &= ~msk;
0228 pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
0229 PAGE_SIZE - bcnt, &ccnt);
0230 bcnt += ccnt;
0231 if (bcnt >= PAGE_SIZE) break;
0232 buf[bcnt] = '\n';
0233 bcnt++;
0234 }
0235 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
0236 cip->chptr, cip->ctl_id);
0237 return bcnt;
0238 }
0239
0240 static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
0241 const char *buf,unsigned int count)
0242 {
0243 int ret;
0244 int mask,val;
0245 if (customfl) {
0246 ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
0247 &mask, &val);
0248 } else {
0249 ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
0250 &mask, &val);
0251 }
0252 if (ret < 0) return ret;
0253 ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
0254 pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
0255 return ret;
0256 }
0257
0258 static ssize_t store_val_norm(struct device *class_dev,
0259 struct device_attribute *attr,
0260 const char *buf, size_t count)
0261 {
0262 struct pvr2_sysfs_ctl_item *cip;
0263 int ret;
0264 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
0265 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
0266 cip->chptr, cip->ctl_id, (int)count, buf);
0267 ret = store_val_any(cip, 0, buf, count);
0268 if (!ret) ret = count;
0269 return ret;
0270 }
0271
0272 static ssize_t store_val_custom(struct device *class_dev,
0273 struct device_attribute *attr,
0274 const char *buf, size_t count)
0275 {
0276 struct pvr2_sysfs_ctl_item *cip;
0277 int ret;
0278 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
0279 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
0280 cip->chptr, cip->ctl_id, (int)count, buf);
0281 ret = store_val_any(cip, 1, buf, count);
0282 if (!ret) ret = count;
0283 return ret;
0284 }
0285
0286 static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
0287 {
0288 struct pvr2_sysfs_ctl_item *cip;
0289 struct pvr2_ctrl *cptr;
0290 unsigned int cnt,acnt;
0291 int ret;
0292
0293 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
0294 if (!cptr) return;
0295
0296 cip = kzalloc(sizeof(*cip),GFP_KERNEL);
0297 if (!cip) return;
0298 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
0299
0300 cip->cptr = cptr;
0301 cip->ctl_id = ctl_id;
0302
0303 cip->chptr = sfp;
0304 cip->item_next = NULL;
0305 if (sfp->item_last) {
0306 sfp->item_last->item_next = cip;
0307 } else {
0308 sfp->item_first = cip;
0309 }
0310 sfp->item_last = cip;
0311
0312 sysfs_attr_init(&cip->attr_name.attr);
0313 cip->attr_name.attr.name = "name";
0314 cip->attr_name.attr.mode = S_IRUGO;
0315 cip->attr_name.show = show_name;
0316
0317 sysfs_attr_init(&cip->attr_type.attr);
0318 cip->attr_type.attr.name = "type";
0319 cip->attr_type.attr.mode = S_IRUGO;
0320 cip->attr_type.show = show_type;
0321
0322 sysfs_attr_init(&cip->attr_min.attr);
0323 cip->attr_min.attr.name = "min_val";
0324 cip->attr_min.attr.mode = S_IRUGO;
0325 cip->attr_min.show = show_min;
0326
0327 sysfs_attr_init(&cip->attr_max.attr);
0328 cip->attr_max.attr.name = "max_val";
0329 cip->attr_max.attr.mode = S_IRUGO;
0330 cip->attr_max.show = show_max;
0331
0332 sysfs_attr_init(&cip->attr_def.attr);
0333 cip->attr_def.attr.name = "def_val";
0334 cip->attr_def.attr.mode = S_IRUGO;
0335 cip->attr_def.show = show_def;
0336
0337 sysfs_attr_init(&cip->attr_val.attr);
0338 cip->attr_val.attr.name = "cur_val";
0339 cip->attr_val.attr.mode = S_IRUGO;
0340
0341 sysfs_attr_init(&cip->attr_custom.attr);
0342 cip->attr_custom.attr.name = "custom_val";
0343 cip->attr_custom.attr.mode = S_IRUGO;
0344
0345 sysfs_attr_init(&cip->attr_enum.attr);
0346 cip->attr_enum.attr.name = "enum_val";
0347 cip->attr_enum.attr.mode = S_IRUGO;
0348 cip->attr_enum.show = show_enum;
0349
0350 sysfs_attr_init(&cip->attr_bits.attr);
0351 cip->attr_bits.attr.name = "bit_val";
0352 cip->attr_bits.attr.mode = S_IRUGO;
0353 cip->attr_bits.show = show_bits;
0354
0355 if (pvr2_ctrl_is_writable(cptr)) {
0356 cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
0357 cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
0358 }
0359
0360 acnt = 0;
0361 cip->attr_gen[acnt++] = &cip->attr_name.attr;
0362 cip->attr_gen[acnt++] = &cip->attr_type.attr;
0363 cip->attr_gen[acnt++] = &cip->attr_val.attr;
0364 cip->attr_gen[acnt++] = &cip->attr_def.attr;
0365 cip->attr_val.show = show_val_norm;
0366 cip->attr_val.store = store_val_norm;
0367 if (pvr2_ctrl_has_custom_symbols(cptr)) {
0368 cip->attr_gen[acnt++] = &cip->attr_custom.attr;
0369 cip->attr_custom.show = show_val_custom;
0370 cip->attr_custom.store = store_val_custom;
0371 }
0372 switch (pvr2_ctrl_get_type(cptr)) {
0373 case pvr2_ctl_enum:
0374
0375 cip->attr_gen[acnt++] = &cip->attr_enum.attr;
0376 break;
0377 case pvr2_ctl_int:
0378
0379 cip->attr_gen[acnt++] = &cip->attr_min.attr;
0380 cip->attr_gen[acnt++] = &cip->attr_max.attr;
0381 break;
0382 case pvr2_ctl_bitmask:
0383
0384 cip->attr_gen[acnt++] = &cip->attr_bits.attr;
0385 break;
0386 default: break;
0387 }
0388
0389 cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
0390 pvr2_ctrl_get_name(cptr));
0391 cip->name[cnt] = 0;
0392 cip->grp.name = cip->name;
0393 cip->grp.attrs = cip->attr_gen;
0394
0395 ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
0396 if (ret) {
0397 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0398 "sysfs_create_group error: %d",
0399 ret);
0400 return;
0401 }
0402 cip->created_ok = !0;
0403 }
0404
0405 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0406 static ssize_t debuginfo_show(struct device *, struct device_attribute *,
0407 char *);
0408 static ssize_t debugcmd_show(struct device *, struct device_attribute *,
0409 char *);
0410 static ssize_t debugcmd_store(struct device *, struct device_attribute *,
0411 const char *, size_t count);
0412
0413 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
0414 {
0415 struct pvr2_sysfs_debugifc *dip;
0416 int ret;
0417
0418 dip = kzalloc(sizeof(*dip),GFP_KERNEL);
0419 if (!dip) return;
0420 sysfs_attr_init(&dip->attr_debugcmd.attr);
0421 dip->attr_debugcmd.attr.name = "debugcmd";
0422 dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
0423 dip->attr_debugcmd.show = debugcmd_show;
0424 dip->attr_debugcmd.store = debugcmd_store;
0425 sysfs_attr_init(&dip->attr_debuginfo.attr);
0426 dip->attr_debuginfo.attr.name = "debuginfo";
0427 dip->attr_debuginfo.attr.mode = S_IRUGO;
0428 dip->attr_debuginfo.show = debuginfo_show;
0429 sfp->debugifc = dip;
0430 ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
0431 if (ret < 0) {
0432 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0433 "device_create_file error: %d",
0434 ret);
0435 } else {
0436 dip->debugcmd_created_ok = !0;
0437 }
0438 ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
0439 if (ret < 0) {
0440 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0441 "device_create_file error: %d",
0442 ret);
0443 } else {
0444 dip->debuginfo_created_ok = !0;
0445 }
0446 }
0447
0448
0449 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
0450 {
0451 if (!sfp->debugifc) return;
0452 if (sfp->debugifc->debuginfo_created_ok) {
0453 device_remove_file(sfp->class_dev,
0454 &sfp->debugifc->attr_debuginfo);
0455 }
0456 if (sfp->debugifc->debugcmd_created_ok) {
0457 device_remove_file(sfp->class_dev,
0458 &sfp->debugifc->attr_debugcmd);
0459 }
0460 kfree(sfp->debugifc);
0461 sfp->debugifc = NULL;
0462 }
0463 #endif
0464
0465
0466 static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
0467 {
0468 unsigned int idx,cnt;
0469 cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
0470 for (idx = 0; idx < cnt; idx++) {
0471 pvr2_sysfs_add_control(sfp,idx);
0472 }
0473 }
0474
0475
0476 static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
0477 {
0478 struct pvr2_sysfs_ctl_item *cip1,*cip2;
0479 for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
0480 cip2 = cip1->item_next;
0481 if (cip1->created_ok) {
0482 sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
0483 }
0484 pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
0485 kfree(cip1);
0486 }
0487 }
0488
0489
0490 static void pvr2_sysfs_class_release(struct class *class)
0491 {
0492 struct pvr2_sysfs_class *clp;
0493 clp = container_of(class,struct pvr2_sysfs_class,class);
0494 pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
0495 kfree(clp);
0496 }
0497
0498
0499 static void pvr2_sysfs_release(struct device *class_dev)
0500 {
0501 pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
0502 kfree(class_dev);
0503 }
0504
0505
0506 static void class_dev_destroy(struct pvr2_sysfs *sfp)
0507 {
0508 struct device *dev;
0509 if (!sfp->class_dev) return;
0510 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0511 pvr2_sysfs_tear_down_debugifc(sfp);
0512 #endif
0513 pvr2_sysfs_tear_down_controls(sfp);
0514 if (sfp->hdw_desc_created_ok) {
0515 device_remove_file(sfp->class_dev,
0516 &sfp->attr_hdw_desc);
0517 }
0518 if (sfp->hdw_name_created_ok) {
0519 device_remove_file(sfp->class_dev,
0520 &sfp->attr_hdw_name);
0521 }
0522 if (sfp->bus_info_created_ok) {
0523 device_remove_file(sfp->class_dev,
0524 &sfp->attr_bus_info);
0525 }
0526 if (sfp->v4l_minor_number_created_ok) {
0527 device_remove_file(sfp->class_dev,
0528 &sfp->attr_v4l_minor_number);
0529 }
0530 if (sfp->v4l_radio_minor_number_created_ok) {
0531 device_remove_file(sfp->class_dev,
0532 &sfp->attr_v4l_radio_minor_number);
0533 }
0534 if (sfp->unit_number_created_ok) {
0535 device_remove_file(sfp->class_dev,
0536 &sfp->attr_unit_number);
0537 }
0538 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
0539 dev_set_drvdata(sfp->class_dev, NULL);
0540 dev = sfp->class_dev->parent;
0541 sfp->class_dev->parent = NULL;
0542 put_device(dev);
0543 device_unregister(sfp->class_dev);
0544 sfp->class_dev = NULL;
0545 }
0546
0547
0548 static ssize_t v4l_minor_number_show(struct device *class_dev,
0549 struct device_attribute *attr, char *buf)
0550 {
0551 struct pvr2_sysfs *sfp;
0552 sfp = dev_get_drvdata(class_dev);
0553 if (!sfp) return -EINVAL;
0554 return scnprintf(buf,PAGE_SIZE,"%d\n",
0555 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
0556 pvr2_v4l_type_video));
0557 }
0558
0559
0560 static ssize_t bus_info_show(struct device *class_dev,
0561 struct device_attribute *attr, char *buf)
0562 {
0563 struct pvr2_sysfs *sfp;
0564 sfp = dev_get_drvdata(class_dev);
0565 if (!sfp) return -EINVAL;
0566 return scnprintf(buf,PAGE_SIZE,"%s\n",
0567 pvr2_hdw_get_bus_info(sfp->channel.hdw));
0568 }
0569
0570
0571 static ssize_t hdw_name_show(struct device *class_dev,
0572 struct device_attribute *attr, char *buf)
0573 {
0574 struct pvr2_sysfs *sfp;
0575 sfp = dev_get_drvdata(class_dev);
0576 if (!sfp) return -EINVAL;
0577 return scnprintf(buf,PAGE_SIZE,"%s\n",
0578 pvr2_hdw_get_type(sfp->channel.hdw));
0579 }
0580
0581
0582 static ssize_t hdw_desc_show(struct device *class_dev,
0583 struct device_attribute *attr, char *buf)
0584 {
0585 struct pvr2_sysfs *sfp;
0586 sfp = dev_get_drvdata(class_dev);
0587 if (!sfp) return -EINVAL;
0588 return scnprintf(buf,PAGE_SIZE,"%s\n",
0589 pvr2_hdw_get_desc(sfp->channel.hdw));
0590 }
0591
0592
0593 static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
0594 struct device_attribute *attr,
0595 char *buf)
0596 {
0597 struct pvr2_sysfs *sfp;
0598 sfp = dev_get_drvdata(class_dev);
0599 if (!sfp) return -EINVAL;
0600 return scnprintf(buf,PAGE_SIZE,"%d\n",
0601 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
0602 pvr2_v4l_type_radio));
0603 }
0604
0605
0606 static ssize_t unit_number_show(struct device *class_dev,
0607 struct device_attribute *attr, char *buf)
0608 {
0609 struct pvr2_sysfs *sfp;
0610 sfp = dev_get_drvdata(class_dev);
0611 if (!sfp) return -EINVAL;
0612 return scnprintf(buf,PAGE_SIZE,"%d\n",
0613 pvr2_hdw_get_unit_number(sfp->channel.hdw));
0614 }
0615
0616
0617 static void class_dev_create(struct pvr2_sysfs *sfp,
0618 struct pvr2_sysfs_class *class_ptr)
0619 {
0620 struct usb_device *usb_dev;
0621 struct device *class_dev;
0622 int ret;
0623
0624 usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
0625 if (!usb_dev) return;
0626 class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
0627 if (!class_dev) return;
0628
0629 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
0630
0631 class_dev->class = &class_ptr->class;
0632
0633 dev_set_name(class_dev, "%s",
0634 pvr2_hdw_get_device_identifier(sfp->channel.hdw));
0635
0636 class_dev->parent = get_device(&usb_dev->dev);
0637
0638 sfp->class_dev = class_dev;
0639 dev_set_drvdata(class_dev, sfp);
0640 ret = device_register(class_dev);
0641 if (ret) {
0642 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0643 "device_register failed");
0644 put_device(class_dev);
0645 return;
0646 }
0647
0648 sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
0649 sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
0650 sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
0651 sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
0652 sfp->attr_v4l_minor_number.store = NULL;
0653 ret = device_create_file(sfp->class_dev,
0654 &sfp->attr_v4l_minor_number);
0655 if (ret < 0) {
0656 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0657 "device_create_file error: %d",
0658 ret);
0659 } else {
0660 sfp->v4l_minor_number_created_ok = !0;
0661 }
0662
0663 sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
0664 sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
0665 sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
0666 sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
0667 sfp->attr_v4l_radio_minor_number.store = NULL;
0668 ret = device_create_file(sfp->class_dev,
0669 &sfp->attr_v4l_radio_minor_number);
0670 if (ret < 0) {
0671 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0672 "device_create_file error: %d",
0673 ret);
0674 } else {
0675 sfp->v4l_radio_minor_number_created_ok = !0;
0676 }
0677
0678 sysfs_attr_init(&sfp->attr_unit_number.attr);
0679 sfp->attr_unit_number.attr.name = "unit_number";
0680 sfp->attr_unit_number.attr.mode = S_IRUGO;
0681 sfp->attr_unit_number.show = unit_number_show;
0682 sfp->attr_unit_number.store = NULL;
0683 ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
0684 if (ret < 0) {
0685 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0686 "device_create_file error: %d",
0687 ret);
0688 } else {
0689 sfp->unit_number_created_ok = !0;
0690 }
0691
0692 sysfs_attr_init(&sfp->attr_bus_info.attr);
0693 sfp->attr_bus_info.attr.name = "bus_info_str";
0694 sfp->attr_bus_info.attr.mode = S_IRUGO;
0695 sfp->attr_bus_info.show = bus_info_show;
0696 sfp->attr_bus_info.store = NULL;
0697 ret = device_create_file(sfp->class_dev,
0698 &sfp->attr_bus_info);
0699 if (ret < 0) {
0700 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0701 "device_create_file error: %d",
0702 ret);
0703 } else {
0704 sfp->bus_info_created_ok = !0;
0705 }
0706
0707 sysfs_attr_init(&sfp->attr_hdw_name.attr);
0708 sfp->attr_hdw_name.attr.name = "device_hardware_type";
0709 sfp->attr_hdw_name.attr.mode = S_IRUGO;
0710 sfp->attr_hdw_name.show = hdw_name_show;
0711 sfp->attr_hdw_name.store = NULL;
0712 ret = device_create_file(sfp->class_dev,
0713 &sfp->attr_hdw_name);
0714 if (ret < 0) {
0715 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0716 "device_create_file error: %d",
0717 ret);
0718 } else {
0719 sfp->hdw_name_created_ok = !0;
0720 }
0721
0722 sysfs_attr_init(&sfp->attr_hdw_desc.attr);
0723 sfp->attr_hdw_desc.attr.name = "device_hardware_description";
0724 sfp->attr_hdw_desc.attr.mode = S_IRUGO;
0725 sfp->attr_hdw_desc.show = hdw_desc_show;
0726 sfp->attr_hdw_desc.store = NULL;
0727 ret = device_create_file(sfp->class_dev,
0728 &sfp->attr_hdw_desc);
0729 if (ret < 0) {
0730 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0731 "device_create_file error: %d",
0732 ret);
0733 } else {
0734 sfp->hdw_desc_created_ok = !0;
0735 }
0736
0737 pvr2_sysfs_add_controls(sfp);
0738 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0739 pvr2_sysfs_add_debugifc(sfp);
0740 #endif
0741 }
0742
0743
0744 static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
0745 {
0746 struct pvr2_sysfs *sfp;
0747 sfp = container_of(chp,struct pvr2_sysfs,channel);
0748 if (!sfp->channel.mc_head->disconnect_flag) return;
0749 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
0750 class_dev_destroy(sfp);
0751 pvr2_channel_done(&sfp->channel);
0752 kfree(sfp);
0753 }
0754
0755
0756 struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
0757 struct pvr2_sysfs_class *class_ptr)
0758 {
0759 struct pvr2_sysfs *sfp;
0760 sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
0761 if (!sfp) return sfp;
0762 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
0763 pvr2_channel_init(&sfp->channel,mp);
0764 sfp->channel.check_func = pvr2_sysfs_internal_check;
0765
0766 class_dev_create(sfp,class_ptr);
0767 return sfp;
0768 }
0769
0770
0771
0772 struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
0773 {
0774 struct pvr2_sysfs_class *clp;
0775 clp = kzalloc(sizeof(*clp),GFP_KERNEL);
0776 if (!clp) return clp;
0777 pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
0778 clp);
0779 clp->class.name = "pvrusb2";
0780 clp->class.class_release = pvr2_sysfs_class_release;
0781 clp->class.dev_release = pvr2_sysfs_release;
0782 if (class_register(&clp->class)) {
0783 pvr2_sysfs_trace(
0784 "Registration failed for pvr2_sysfs_class id=%p",clp);
0785 kfree(clp);
0786 clp = NULL;
0787 }
0788 return clp;
0789 }
0790
0791
0792 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
0793 {
0794 pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
0795 if (clp)
0796 class_unregister(&clp->class);
0797 }
0798
0799
0800 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
0801 static ssize_t debuginfo_show(struct device *class_dev,
0802 struct device_attribute *attr, char *buf)
0803 {
0804 struct pvr2_sysfs *sfp;
0805 sfp = dev_get_drvdata(class_dev);
0806 if (!sfp) return -EINVAL;
0807 pvr2_hdw_trigger_module_log(sfp->channel.hdw);
0808 return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
0809 }
0810
0811
0812 static ssize_t debugcmd_show(struct device *class_dev,
0813 struct device_attribute *attr, char *buf)
0814 {
0815 struct pvr2_sysfs *sfp;
0816 sfp = dev_get_drvdata(class_dev);
0817 if (!sfp) return -EINVAL;
0818 return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
0819 }
0820
0821
0822 static ssize_t debugcmd_store(struct device *class_dev,
0823 struct device_attribute *attr,
0824 const char *buf, size_t count)
0825 {
0826 struct pvr2_sysfs *sfp;
0827 int ret;
0828
0829 sfp = dev_get_drvdata(class_dev);
0830 if (!sfp) return -EINVAL;
0831
0832 ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
0833 if (ret < 0) return ret;
0834 return count;
0835 }
0836 #endif