1/* 2 * 3 * $Id: pvrusb2-sysfs.c,v 1.1.1.1 2007/08/03 18:52:41 Exp $ 4 * 5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22#include <linux/string.h> 23#include <linux/slab.h> 24#include <asm/semaphore.h> 25#include "pvrusb2-sysfs.h" 26#include "pvrusb2-hdw.h" 27#include "pvrusb2-debug.h" 28#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 29#include "pvrusb2-debugifc.h" 30#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 31 32#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) 33 34struct pvr2_sysfs { 35 struct pvr2_channel channel; 36 struct class_device *class_dev; 37#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 38 struct pvr2_sysfs_debugifc *debugifc; 39#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 40 struct pvr2_sysfs_ctl_item *item_first; 41 struct pvr2_sysfs_ctl_item *item_last; 42 struct class_device_attribute attr_v4l_minor_number; 43 struct class_device_attribute attr_v4l_radio_minor_number; 44 struct class_device_attribute attr_unit_number; 45 struct class_device_attribute attr_bus_info; 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}; 51 52#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 53struct pvr2_sysfs_debugifc { 54 struct class_device_attribute attr_debugcmd; 55 struct class_device_attribute attr_debuginfo; 56 int debugcmd_created_ok; 57 int debuginfo_created_ok; 58}; 59#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 60 61struct pvr2_sysfs_ctl_item { 62 struct class_device_attribute attr_name; 63 struct class_device_attribute attr_type; 64 struct class_device_attribute attr_min; 65 struct class_device_attribute attr_max; 66 struct class_device_attribute attr_enum; 67 struct class_device_attribute attr_bits; 68 struct class_device_attribute attr_val; 69 struct class_device_attribute attr_custom; 70 struct pvr2_ctrl *cptr; 71 struct pvr2_sysfs *chptr; 72 struct pvr2_sysfs_ctl_item *item_next; 73 struct attribute *attr_gen[7]; 74 struct attribute_group grp; 75 int created_ok; 76 char name[80]; 77}; 78 79struct pvr2_sysfs_class { 80 struct class class; 81}; 82 83static ssize_t show_name(int id,struct class_device *class_dev,char *buf) 84{ 85 struct pvr2_ctrl *cptr; 86 struct pvr2_sysfs *sfp; 87 const char *name; 88 89 sfp = (struct pvr2_sysfs *)class_dev->class_data; 90 if (!sfp) return -EINVAL; 91 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 92 if (!cptr) return -EINVAL; 93 94 name = pvr2_ctrl_get_desc(cptr); 95 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name); 96 97 if (!name) return -EINVAL; 98 99 return scnprintf(buf,PAGE_SIZE,"%s\n",name); 100} 101 102static ssize_t show_type(int id,struct class_device *class_dev,char *buf) 103{ 104 struct pvr2_ctrl *cptr; 105 struct pvr2_sysfs *sfp; 106 const char *name; 107 enum pvr2_ctl_type tp; 108 109 sfp = (struct pvr2_sysfs *)class_dev->class_data; 110 if (!sfp) return -EINVAL; 111 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 112 if (!cptr) return -EINVAL; 113 114 tp = pvr2_ctrl_get_type(cptr); 115 switch (tp) { 116 case pvr2_ctl_int: name = "integer"; break; 117 case pvr2_ctl_enum: name = "enum"; break; 118 case pvr2_ctl_bitmask: name = "bitmask"; break; 119 case pvr2_ctl_bool: name = "boolean"; break; 120 default: name = "?"; break; 121 } 122 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name); 123 124 if (!name) return -EINVAL; 125 126 return scnprintf(buf,PAGE_SIZE,"%s\n",name); 127} 128 129static ssize_t show_min(int id,struct class_device *class_dev,char *buf) 130{ 131 struct pvr2_ctrl *cptr; 132 struct pvr2_sysfs *sfp; 133 long val; 134 135 sfp = (struct pvr2_sysfs *)class_dev->class_data; 136 if (!sfp) return -EINVAL; 137 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 138 if (!cptr) return -EINVAL; 139 val = pvr2_ctrl_get_min(cptr); 140 141 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val); 142 143 return scnprintf(buf,PAGE_SIZE,"%ld\n",val); 144} 145 146static ssize_t show_max(int id,struct class_device *class_dev,char *buf) 147{ 148 struct pvr2_ctrl *cptr; 149 struct pvr2_sysfs *sfp; 150 long val; 151 152 sfp = (struct pvr2_sysfs *)class_dev->class_data; 153 if (!sfp) return -EINVAL; 154 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 155 if (!cptr) return -EINVAL; 156 val = pvr2_ctrl_get_max(cptr); 157 158 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val); 159 160 return scnprintf(buf,PAGE_SIZE,"%ld\n",val); 161} 162 163static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf) 164{ 165 struct pvr2_ctrl *cptr; 166 struct pvr2_sysfs *sfp; 167 int val,ret; 168 unsigned int cnt = 0; 169 170 sfp = (struct pvr2_sysfs *)class_dev->class_data; 171 if (!sfp) return -EINVAL; 172 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 173 if (!cptr) return -EINVAL; 174 175 ret = pvr2_ctrl_get_value(cptr,&val); 176 if (ret < 0) return ret; 177 178 ret = pvr2_ctrl_value_to_sym(cptr,~0,val, 179 buf,PAGE_SIZE-1,&cnt); 180 181 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", 182 sfp,id,cnt,buf,val); 183 buf[cnt] = '\n'; 184 return cnt+1; 185} 186 187static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf) 188{ 189 struct pvr2_ctrl *cptr; 190 struct pvr2_sysfs *sfp; 191 int val,ret; 192 unsigned int cnt = 0; 193 194 sfp = (struct pvr2_sysfs *)class_dev->class_data; 195 if (!sfp) return -EINVAL; 196 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 197 if (!cptr) return -EINVAL; 198 199 ret = pvr2_ctrl_get_value(cptr,&val); 200 if (ret < 0) return ret; 201 202 ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val, 203 buf,PAGE_SIZE-1,&cnt); 204 205 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", 206 sfp,id,cnt,buf,val); 207 buf[cnt] = '\n'; 208 return cnt+1; 209} 210 211static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) 212{ 213 struct pvr2_ctrl *cptr; 214 struct pvr2_sysfs *sfp; 215 long val; 216 unsigned int bcnt,ccnt,ecnt; 217 218 sfp = (struct pvr2_sysfs *)class_dev->class_data; 219 if (!sfp) return -EINVAL; 220 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 221 if (!cptr) return -EINVAL; 222 ecnt = pvr2_ctrl_get_cnt(cptr); 223 bcnt = 0; 224 for (val = 0; val < ecnt; val++) { 225 pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); 226 if (!ccnt) continue; 227 bcnt += ccnt; 228 if (bcnt >= PAGE_SIZE) break; 229 buf[bcnt] = '\n'; 230 bcnt++; 231 } 232 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id); 233 return bcnt; 234} 235 236static ssize_t show_bits(int id,struct class_device *class_dev,char *buf) 237{ 238 struct pvr2_ctrl *cptr; 239 struct pvr2_sysfs *sfp; 240 int valid_bits,msk; 241 unsigned int bcnt,ccnt; 242 243 sfp = (struct pvr2_sysfs *)class_dev->class_data; 244 if (!sfp) return -EINVAL; 245 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 246 if (!cptr) return -EINVAL; 247 valid_bits = pvr2_ctrl_get_mask(cptr); 248 bcnt = 0; 249 for (msk = 1; valid_bits; msk <<= 1) { 250 if (!(msk & valid_bits)) continue; 251 valid_bits &= ~msk; 252 pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); 253 bcnt += ccnt; 254 if (bcnt >= PAGE_SIZE) break; 255 buf[bcnt] = '\n'; 256 bcnt++; 257 } 258 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id); 259 return bcnt; 260} 261 262static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp, 263 const char *buf,unsigned int count) 264{ 265 struct pvr2_ctrl *cptr; 266 int ret; 267 int mask,val; 268 269 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 270 if (customfl) { 271 ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val); 272 } else { 273 ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val); 274 } 275 if (ret < 0) return ret; 276 ret = pvr2_ctrl_set_mask_value(cptr,mask,val); 277 pvr2_hdw_commit_ctl(sfp->channel.hdw); 278 return ret; 279} 280 281static ssize_t store_val_norm(int id,struct class_device *class_dev, 282 const char *buf,size_t count) 283{ 284 struct pvr2_sysfs *sfp; 285 int ret; 286 sfp = (struct pvr2_sysfs *)class_dev->class_data; 287 ret = store_val_any(id,0,sfp,buf,count); 288 if (!ret) ret = count; 289 return ret; 290} 291 292static ssize_t store_val_custom(int id,struct class_device *class_dev, 293 const char *buf,size_t count) 294{ 295 struct pvr2_sysfs *sfp; 296 int ret; 297 sfp = (struct pvr2_sysfs *)class_dev->class_data; 298 ret = store_val_any(id,1,sfp,buf,count); 299 if (!ret) ret = count; 300 return ret; 301} 302 303 304#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \ 305static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \ 306{ return sf_name(ctl_id,class_dev,buf); } 307 308#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \ 309static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \ 310{ return sf_name(ctl_id,class_dev,buf,count); } 311 312#define CREATE_BATCH(ctl_id) \ 313CREATE_SHOW_INSTANCE(show_name,ctl_id) \ 314CREATE_SHOW_INSTANCE(show_type,ctl_id) \ 315CREATE_SHOW_INSTANCE(show_min,ctl_id) \ 316CREATE_SHOW_INSTANCE(show_max,ctl_id) \ 317CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \ 318CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \ 319CREATE_SHOW_INSTANCE(show_enum,ctl_id) \ 320CREATE_SHOW_INSTANCE(show_bits,ctl_id) \ 321CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \ 322CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \ 323 324CREATE_BATCH(0) 325CREATE_BATCH(1) 326CREATE_BATCH(2) 327CREATE_BATCH(3) 328CREATE_BATCH(4) 329CREATE_BATCH(5) 330CREATE_BATCH(6) 331CREATE_BATCH(7) 332CREATE_BATCH(8) 333CREATE_BATCH(9) 334CREATE_BATCH(10) 335CREATE_BATCH(11) 336CREATE_BATCH(12) 337CREATE_BATCH(13) 338CREATE_BATCH(14) 339CREATE_BATCH(15) 340CREATE_BATCH(16) 341CREATE_BATCH(17) 342CREATE_BATCH(18) 343CREATE_BATCH(19) 344CREATE_BATCH(20) 345CREATE_BATCH(21) 346CREATE_BATCH(22) 347CREATE_BATCH(23) 348CREATE_BATCH(24) 349CREATE_BATCH(25) 350CREATE_BATCH(26) 351CREATE_BATCH(27) 352CREATE_BATCH(28) 353CREATE_BATCH(29) 354CREATE_BATCH(30) 355CREATE_BATCH(31) 356CREATE_BATCH(32) 357CREATE_BATCH(33) 358CREATE_BATCH(34) 359CREATE_BATCH(35) 360CREATE_BATCH(36) 361CREATE_BATCH(37) 362CREATE_BATCH(38) 363CREATE_BATCH(39) 364CREATE_BATCH(40) 365CREATE_BATCH(41) 366CREATE_BATCH(42) 367CREATE_BATCH(43) 368CREATE_BATCH(44) 369CREATE_BATCH(45) 370CREATE_BATCH(46) 371CREATE_BATCH(47) 372CREATE_BATCH(48) 373CREATE_BATCH(49) 374CREATE_BATCH(50) 375CREATE_BATCH(51) 376CREATE_BATCH(52) 377CREATE_BATCH(53) 378CREATE_BATCH(54) 379CREATE_BATCH(55) 380CREATE_BATCH(56) 381CREATE_BATCH(57) 382CREATE_BATCH(58) 383CREATE_BATCH(59) 384 385struct pvr2_sysfs_func_set { 386 ssize_t (*show_name)(struct class_device *,char *); 387 ssize_t (*show_type)(struct class_device *,char *); 388 ssize_t (*show_min)(struct class_device *,char *); 389 ssize_t (*show_max)(struct class_device *,char *); 390 ssize_t (*show_enum)(struct class_device *,char *); 391 ssize_t (*show_bits)(struct class_device *,char *); 392 ssize_t (*show_val_norm)(struct class_device *,char *); 393 ssize_t (*store_val_norm)(struct class_device *, 394 const char *,size_t); 395 ssize_t (*show_val_custom)(struct class_device *,char *); 396 ssize_t (*store_val_custom)(struct class_device *, 397 const char *,size_t); 398}; 399 400#define INIT_BATCH(ctl_id) \ 401[ctl_id] = { \ 402 .show_name = show_name_##ctl_id, \ 403 .show_type = show_type_##ctl_id, \ 404 .show_min = show_min_##ctl_id, \ 405 .show_max = show_max_##ctl_id, \ 406 .show_enum = show_enum_##ctl_id, \ 407 .show_bits = show_bits_##ctl_id, \ 408 .show_val_norm = show_val_norm_##ctl_id, \ 409 .store_val_norm = store_val_norm_##ctl_id, \ 410 .show_val_custom = show_val_custom_##ctl_id, \ 411 .store_val_custom = store_val_custom_##ctl_id, \ 412} \ 413 414static struct pvr2_sysfs_func_set funcs[] = { 415 INIT_BATCH(0), 416 INIT_BATCH(1), 417 INIT_BATCH(2), 418 INIT_BATCH(3), 419 INIT_BATCH(4), 420 INIT_BATCH(5), 421 INIT_BATCH(6), 422 INIT_BATCH(7), 423 INIT_BATCH(8), 424 INIT_BATCH(9), 425 INIT_BATCH(10), 426 INIT_BATCH(11), 427 INIT_BATCH(12), 428 INIT_BATCH(13), 429 INIT_BATCH(14), 430 INIT_BATCH(15), 431 INIT_BATCH(16), 432 INIT_BATCH(17), 433 INIT_BATCH(18), 434 INIT_BATCH(19), 435 INIT_BATCH(20), 436 INIT_BATCH(21), 437 INIT_BATCH(22), 438 INIT_BATCH(23), 439 INIT_BATCH(24), 440 INIT_BATCH(25), 441 INIT_BATCH(26), 442 INIT_BATCH(27), 443 INIT_BATCH(28), 444 INIT_BATCH(29), 445 INIT_BATCH(30), 446 INIT_BATCH(31), 447 INIT_BATCH(32), 448 INIT_BATCH(33), 449 INIT_BATCH(34), 450 INIT_BATCH(35), 451 INIT_BATCH(36), 452 INIT_BATCH(37), 453 INIT_BATCH(38), 454 INIT_BATCH(39), 455 INIT_BATCH(40), 456 INIT_BATCH(41), 457 INIT_BATCH(42), 458 INIT_BATCH(43), 459 INIT_BATCH(44), 460 INIT_BATCH(45), 461 INIT_BATCH(46), 462 INIT_BATCH(47), 463 INIT_BATCH(48), 464 INIT_BATCH(49), 465 INIT_BATCH(50), 466 INIT_BATCH(51), 467 INIT_BATCH(52), 468 INIT_BATCH(53), 469 INIT_BATCH(54), 470 INIT_BATCH(55), 471 INIT_BATCH(56), 472 INIT_BATCH(57), 473 INIT_BATCH(58), 474 INIT_BATCH(59), 475}; 476 477 478static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) 479{ 480 struct pvr2_sysfs_ctl_item *cip; 481 struct pvr2_sysfs_func_set *fp; 482 struct pvr2_ctrl *cptr; 483 unsigned int cnt,acnt; 484 int ret; 485 486 if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) { 487 return; 488 } 489 490 fp = funcs + ctl_id; 491 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); 492 if (!cptr) return; 493 494 cip = kzalloc(sizeof(*cip),GFP_KERNEL); 495 if (!cip) return; 496 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); 497 498 cip->cptr = cptr; 499 500 cip->chptr = sfp; 501 cip->item_next = NULL; 502 if (sfp->item_last) { 503 sfp->item_last->item_next = cip; 504 } else { 505 sfp->item_first = cip; 506 } 507 sfp->item_last = cip; 508 509 cip->attr_name.attr.name = "name"; 510 cip->attr_name.attr.mode = S_IRUGO; 511 cip->attr_name.show = fp->show_name; 512 513 cip->attr_type.attr.name = "type"; 514 cip->attr_type.attr.mode = S_IRUGO; 515 cip->attr_type.show = fp->show_type; 516 517 cip->attr_min.attr.name = "min_val"; 518 cip->attr_min.attr.mode = S_IRUGO; 519 cip->attr_min.show = fp->show_min; 520 521 cip->attr_max.attr.name = "max_val"; 522 cip->attr_max.attr.mode = S_IRUGO; 523 cip->attr_max.show = fp->show_max; 524 525 cip->attr_val.attr.name = "cur_val"; 526 cip->attr_val.attr.mode = S_IRUGO; 527 528 cip->attr_custom.attr.name = "custom_val"; 529 cip->attr_custom.attr.mode = S_IRUGO; 530 531 cip->attr_enum.attr.name = "enum_val"; 532 cip->attr_enum.attr.mode = S_IRUGO; 533 cip->attr_enum.show = fp->show_enum; 534 535 cip->attr_bits.attr.name = "bit_val"; 536 cip->attr_bits.attr.mode = S_IRUGO; 537 cip->attr_bits.show = fp->show_bits; 538 539 if (pvr2_ctrl_is_writable(cptr)) { 540 cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; 541 cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP; 542 } 543 544 acnt = 0; 545 cip->attr_gen[acnt++] = &cip->attr_name.attr; 546 cip->attr_gen[acnt++] = &cip->attr_type.attr; 547 cip->attr_gen[acnt++] = &cip->attr_val.attr; 548 cip->attr_val.show = fp->show_val_norm; 549 cip->attr_val.store = fp->store_val_norm; 550 if (pvr2_ctrl_has_custom_symbols(cptr)) { 551 cip->attr_gen[acnt++] = &cip->attr_custom.attr; 552 cip->attr_custom.show = fp->show_val_custom; 553 cip->attr_custom.store = fp->store_val_custom; 554 } 555 switch (pvr2_ctrl_get_type(cptr)) { 556 case pvr2_ctl_enum: 557 // Control is an enumeration 558 cip->attr_gen[acnt++] = &cip->attr_enum.attr; 559 break; 560 case pvr2_ctl_int: 561 // Control is an integer 562 cip->attr_gen[acnt++] = &cip->attr_min.attr; 563 cip->attr_gen[acnt++] = &cip->attr_max.attr; 564 break; 565 case pvr2_ctl_bitmask: 566 // Control is an bitmask 567 cip->attr_gen[acnt++] = &cip->attr_bits.attr; 568 break; 569 default: break; 570 } 571 572 cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", 573 pvr2_ctrl_get_name(cptr)); 574 cip->name[cnt] = 0; 575 cip->grp.name = cip->name; 576 cip->grp.attrs = cip->attr_gen; 577 578 ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); 579 if (ret) { 580 printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", 581 __FUNCTION__, ret); 582 return; 583 } 584 cip->created_ok = !0; 585} 586 587#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 588static ssize_t debuginfo_show(struct class_device *,char *); 589static ssize_t debugcmd_show(struct class_device *,char *); 590static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); 591 592static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) 593{ 594 struct pvr2_sysfs_debugifc *dip; 595 int ret; 596 597 dip = kzalloc(sizeof(*dip),GFP_KERNEL); 598 if (!dip) return; 599 dip->attr_debugcmd.attr.name = "debugcmd"; 600 dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; 601 dip->attr_debugcmd.show = debugcmd_show; 602 dip->attr_debugcmd.store = debugcmd_store; 603 dip->attr_debuginfo.attr.name = "debuginfo"; 604 dip->attr_debuginfo.attr.mode = S_IRUGO; 605 dip->attr_debuginfo.show = debuginfo_show; 606 sfp->debugifc = dip; 607 ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); 608 if (ret < 0) { 609 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 610 __FUNCTION__, ret); 611 } else { 612 dip->debugcmd_created_ok = !0; 613 } 614 ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); 615 if (ret < 0) { 616 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 617 __FUNCTION__, ret); 618 } else { 619 dip->debuginfo_created_ok = !0; 620 } 621} 622 623 624static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) 625{ 626 if (!sfp->debugifc) return; 627 if (sfp->debugifc->debuginfo_created_ok) { 628 class_device_remove_file(sfp->class_dev, 629 &sfp->debugifc->attr_debuginfo); 630 } 631 if (sfp->debugifc->debugcmd_created_ok) { 632 class_device_remove_file(sfp->class_dev, 633 &sfp->debugifc->attr_debugcmd); 634 } 635 kfree(sfp->debugifc); 636 sfp->debugifc = NULL; 637} 638#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 639 640 641static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp) 642{ 643 unsigned int idx,cnt; 644 cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw); 645 for (idx = 0; idx < cnt; idx++) { 646 pvr2_sysfs_add_control(sfp,idx); 647 } 648} 649 650 651static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) 652{ 653 struct pvr2_sysfs_ctl_item *cip1,*cip2; 654 for (cip1 = sfp->item_first; cip1; cip1 = cip2) { 655 cip2 = cip1->item_next; 656 if (cip1->created_ok) { 657 sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); 658 } 659 pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); 660 kfree(cip1); 661 } 662} 663 664 665static void pvr2_sysfs_class_release(struct class *class) 666{ 667 struct pvr2_sysfs_class *clp; 668 clp = container_of(class,struct pvr2_sysfs_class,class); 669 pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp); 670 kfree(clp); 671} 672 673 674static void pvr2_sysfs_release(struct class_device *class_dev) 675{ 676 pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); 677 kfree(class_dev); 678} 679 680 681static void class_dev_destroy(struct pvr2_sysfs *sfp) 682{ 683 if (!sfp->class_dev) return; 684#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 685 pvr2_sysfs_tear_down_debugifc(sfp); 686#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 687 pvr2_sysfs_tear_down_controls(sfp); 688 if (sfp->bus_info_created_ok) { 689 class_device_remove_file(sfp->class_dev, 690 &sfp->attr_bus_info); 691 } 692 if (sfp->v4l_minor_number_created_ok) { 693 class_device_remove_file(sfp->class_dev, 694 &sfp->attr_v4l_minor_number); 695 } 696 if (sfp->v4l_radio_minor_number_created_ok) { 697 class_device_remove_file(sfp->class_dev, 698 &sfp->attr_v4l_radio_minor_number); 699 } 700 if (sfp->unit_number_created_ok) { 701 class_device_remove_file(sfp->class_dev, 702 &sfp->attr_unit_number); 703 } 704 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); 705 sfp->class_dev->class_data = NULL; 706 class_device_unregister(sfp->class_dev); 707 sfp->class_dev = NULL; 708} 709 710 711static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) 712{ 713 struct pvr2_sysfs *sfp; 714 sfp = (struct pvr2_sysfs *)class_dev->class_data; 715 if (!sfp) return -EINVAL; 716 return scnprintf(buf,PAGE_SIZE,"%d\n", 717 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, 718 pvr2_v4l_type_video)); 719} 720 721 722static ssize_t bus_info_show(struct class_device *class_dev,char *buf) 723{ 724 struct pvr2_sysfs *sfp; 725 sfp = (struct pvr2_sysfs *)class_dev->class_data; 726 if (!sfp) return -EINVAL; 727 return scnprintf(buf,PAGE_SIZE,"%s\n", 728 pvr2_hdw_get_bus_info(sfp->channel.hdw)); 729} 730 731 732static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev, 733 char *buf) 734{ 735 struct pvr2_sysfs *sfp; 736 sfp = (struct pvr2_sysfs *)class_dev->class_data; 737 if (!sfp) return -EINVAL; 738 return scnprintf(buf,PAGE_SIZE,"%d\n", 739 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, 740 pvr2_v4l_type_radio)); 741} 742 743 744static ssize_t unit_number_show(struct class_device *class_dev,char *buf) 745{ 746 struct pvr2_sysfs *sfp; 747 sfp = (struct pvr2_sysfs *)class_dev->class_data; 748 if (!sfp) return -EINVAL; 749 return scnprintf(buf,PAGE_SIZE,"%d\n", 750 pvr2_hdw_get_unit_number(sfp->channel.hdw)); 751} 752 753 754static void class_dev_create(struct pvr2_sysfs *sfp, 755 struct pvr2_sysfs_class *class_ptr) 756{ 757 struct usb_device *usb_dev; 758 struct class_device *class_dev; 759 int ret; 760 761 usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); 762 if (!usb_dev) return; 763 class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL); 764 if (!class_dev) return; 765 766 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); 767 768 class_dev->class = &class_ptr->class; 769 if (pvr2_hdw_get_sn(sfp->channel.hdw)) { 770 snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu", 771 pvr2_hdw_get_sn(sfp->channel.hdw)); 772 } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { 773 snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c", 774 pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); 775 } else { 776 kfree(class_dev); 777 return; 778 } 779 780 class_dev->dev = &usb_dev->dev; 781 782 sfp->class_dev = class_dev; 783 class_dev->class_data = sfp; 784 ret = class_device_register(class_dev); 785 if (ret) { 786 printk(KERN_ERR "%s: class_device_register failed\n", 787 __FUNCTION__); 788 kfree(class_dev); 789 return; 790 } 791 792 sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; 793 sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; 794 sfp->attr_v4l_minor_number.show = v4l_minor_number_show; 795 sfp->attr_v4l_minor_number.store = NULL; 796 ret = class_device_create_file(sfp->class_dev, 797 &sfp->attr_v4l_minor_number); 798 if (ret < 0) { 799 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 800 __FUNCTION__, ret); 801 } else { 802 sfp->v4l_minor_number_created_ok = !0; 803 } 804 805 sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; 806 sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; 807 sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; 808 sfp->attr_v4l_radio_minor_number.store = NULL; 809 ret = class_device_create_file(sfp->class_dev, 810 &sfp->attr_v4l_radio_minor_number); 811 if (ret < 0) { 812 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 813 __FUNCTION__, ret); 814 } else { 815 sfp->v4l_radio_minor_number_created_ok = !0; 816 } 817 818 sfp->attr_unit_number.attr.name = "unit_number"; 819 sfp->attr_unit_number.attr.mode = S_IRUGO; 820 sfp->attr_unit_number.show = unit_number_show; 821 sfp->attr_unit_number.store = NULL; 822 ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); 823 if (ret < 0) { 824 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 825 __FUNCTION__, ret); 826 } else { 827 sfp->unit_number_created_ok = !0; 828 } 829 830 sfp->attr_bus_info.attr.name = "bus_info_str"; 831 sfp->attr_bus_info.attr.mode = S_IRUGO; 832 sfp->attr_bus_info.show = bus_info_show; 833 sfp->attr_bus_info.store = NULL; 834 ret = class_device_create_file(sfp->class_dev, 835 &sfp->attr_bus_info); 836 if (ret < 0) { 837 printk(KERN_WARNING "%s: class_device_create_file error: %d\n", 838 __FUNCTION__, ret); 839 } else { 840 sfp->bus_info_created_ok = !0; 841 } 842 843 pvr2_sysfs_add_controls(sfp); 844#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 845 pvr2_sysfs_add_debugifc(sfp); 846#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 847} 848 849 850static void pvr2_sysfs_internal_check(struct pvr2_channel *chp) 851{ 852 struct pvr2_sysfs *sfp; 853 sfp = container_of(chp,struct pvr2_sysfs,channel); 854 if (!sfp->channel.mc_head->disconnect_flag) return; 855 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp); 856 class_dev_destroy(sfp); 857 pvr2_channel_done(&sfp->channel); 858 kfree(sfp); 859} 860 861 862struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, 863 struct pvr2_sysfs_class *class_ptr) 864{ 865 struct pvr2_sysfs *sfp; 866 sfp = kzalloc(sizeof(*sfp),GFP_KERNEL); 867 if (!sfp) return sfp; 868 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); 869 pvr2_channel_init(&sfp->channel,mp); 870 sfp->channel.check_func = pvr2_sysfs_internal_check; 871 872 class_dev_create(sfp,class_ptr); 873 return sfp; 874} 875 876 877static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp, 878 int numenvp,char *buf,int size) 879{ 880 /* Even though we don't do anything here, we still need this function 881 because sysfs will still try to call it. */ 882 return 0; 883} 884 885struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) 886{ 887 struct pvr2_sysfs_class *clp; 888 clp = kzalloc(sizeof(*clp),GFP_KERNEL); 889 if (!clp) return clp; 890 pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); 891 clp->class.name = "pvrusb2"; 892 clp->class.class_release = pvr2_sysfs_class_release; 893 clp->class.release = pvr2_sysfs_release; 894 clp->class.uevent = pvr2_sysfs_hotplug; 895 if (class_register(&clp->class)) { 896 pvr2_sysfs_trace( 897 "Registration failed for pvr2_sysfs_class id=%p",clp); 898 kfree(clp); 899 clp = NULL; 900 } 901 return clp; 902} 903 904 905void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) 906{ 907 class_unregister(&clp->class); 908} 909 910 911#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 912static ssize_t debuginfo_show(struct class_device *class_dev,char *buf) 913{ 914 struct pvr2_sysfs *sfp; 915 sfp = (struct pvr2_sysfs *)class_dev->class_data; 916 if (!sfp) return -EINVAL; 917 pvr2_hdw_trigger_module_log(sfp->channel.hdw); 918 return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); 919} 920 921 922static ssize_t debugcmd_show(struct class_device *class_dev,char *buf) 923{ 924 struct pvr2_sysfs *sfp; 925 sfp = (struct pvr2_sysfs *)class_dev->class_data; 926 if (!sfp) return -EINVAL; 927 return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); 928} 929 930 931static ssize_t debugcmd_store(struct class_device *class_dev, 932 const char *buf,size_t count) 933{ 934 struct pvr2_sysfs *sfp; 935 int ret; 936 937 sfp = (struct pvr2_sysfs *)class_dev->class_data; 938 if (!sfp) return -EINVAL; 939 940 ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); 941 if (ret < 0) return ret; 942 return count; 943} 944#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 945 946 947/* 948 Stuff for Emacs to see, in order to encourage consistent editing style: 949 *** Local Variables: *** 950 *** mode: c *** 951 *** fill-column: 75 *** 952 *** tab-width: 8 *** 953 *** c-basic-offset: 8 *** 954 *** End: *** 955 */ 956