pvrusb2-sysfs.c (23349B)
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 */