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