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