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