5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
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
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.
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
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 */
32 #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
35 struct pvr2_channel channel
;
36 struct 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 device_attribute attr_v4l_minor_number
;
43 struct device_attribute attr_v4l_radio_minor_number
;
44 struct device_attribute attr_unit_number
;
45 struct 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
;
52 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
53 struct pvr2_sysfs_debugifc
{
54 struct device_attribute attr_debugcmd
;
55 struct device_attribute attr_debuginfo
;
56 int debugcmd_created_ok
;
57 int debuginfo_created_ok
;
59 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
61 struct pvr2_sysfs_ctl_item
{
62 struct device_attribute attr_name
;
63 struct device_attribute attr_type
;
64 struct device_attribute attr_min
;
65 struct device_attribute attr_max
;
66 struct device_attribute attr_enum
;
67 struct device_attribute attr_bits
;
68 struct device_attribute attr_val
;
69 struct 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
;
79 struct pvr2_sysfs_class
{
83 static ssize_t
show_name(int id
,struct device
*class_dev
,char *buf
)
85 struct pvr2_ctrl
*cptr
;
86 struct pvr2_sysfs
*sfp
;
89 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
90 if (!sfp
) return -EINVAL
;
91 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
92 if (!cptr
) return -EINVAL
;
94 name
= pvr2_ctrl_get_desc(cptr
);
95 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp
,id
,name
);
97 if (!name
) return -EINVAL
;
99 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
102 static ssize_t
show_type(int id
,struct device
*class_dev
,char *buf
)
104 struct pvr2_ctrl
*cptr
;
105 struct pvr2_sysfs
*sfp
;
107 enum pvr2_ctl_type tp
;
109 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
110 if (!sfp
) return -EINVAL
;
111 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
112 if (!cptr
) return -EINVAL
;
114 tp
= pvr2_ctrl_get_type(cptr
);
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;
122 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp
,id
,name
);
124 if (!name
) return -EINVAL
;
126 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
129 static ssize_t
show_min(int id
,struct device
*class_dev
,char *buf
)
131 struct pvr2_ctrl
*cptr
;
132 struct pvr2_sysfs
*sfp
;
135 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_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
);
141 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp
,id
,val
);
143 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
146 static ssize_t
show_max(int id
,struct device
*class_dev
,char *buf
)
148 struct pvr2_ctrl
*cptr
;
149 struct pvr2_sysfs
*sfp
;
152 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_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
);
158 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp
,id
,val
);
160 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
163 static ssize_t
show_val_norm(int id
,struct device
*class_dev
,char *buf
)
165 struct pvr2_ctrl
*cptr
;
166 struct pvr2_sysfs
*sfp
;
168 unsigned int cnt
= 0;
170 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
171 if (!sfp
) return -EINVAL
;
172 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
173 if (!cptr
) return -EINVAL
;
175 ret
= pvr2_ctrl_get_value(cptr
,&val
);
176 if (ret
< 0) return ret
;
178 ret
= pvr2_ctrl_value_to_sym(cptr
,~0,val
,
179 buf
,PAGE_SIZE
-1,&cnt
);
181 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
187 static ssize_t
show_val_custom(int id
,struct device
*class_dev
,char *buf
)
189 struct pvr2_ctrl
*cptr
;
190 struct pvr2_sysfs
*sfp
;
192 unsigned int cnt
= 0;
194 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
195 if (!sfp
) return -EINVAL
;
196 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
197 if (!cptr
) return -EINVAL
;
199 ret
= pvr2_ctrl_get_value(cptr
,&val
);
200 if (ret
< 0) return ret
;
202 ret
= pvr2_ctrl_custom_value_to_sym(cptr
,~0,val
,
203 buf
,PAGE_SIZE
-1,&cnt
);
205 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
211 static ssize_t
show_enum(int id
,struct device
*class_dev
,char *buf
)
213 struct pvr2_ctrl
*cptr
;
214 struct pvr2_sysfs
*sfp
;
216 unsigned int bcnt
,ccnt
,ecnt
;
218 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_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
);
224 for (val
= 0; val
< ecnt
; val
++) {
225 pvr2_ctrl_get_valname(cptr
,val
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
228 if (bcnt
>= PAGE_SIZE
) break;
232 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp
,id
);
236 static ssize_t
show_bits(int id
,struct device
*class_dev
,char *buf
)
238 struct pvr2_ctrl
*cptr
;
239 struct pvr2_sysfs
*sfp
;
241 unsigned int bcnt
,ccnt
;
243 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_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
);
249 for (msk
= 1; valid_bits
; msk
<<= 1) {
250 if (!(msk
& valid_bits
)) continue;
252 pvr2_ctrl_get_valname(cptr
,msk
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
254 if (bcnt
>= PAGE_SIZE
) break;
258 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp
,id
);
262 static int store_val_any(int id
,int customfl
,struct pvr2_sysfs
*sfp
,
263 const char *buf
,unsigned int count
)
265 struct pvr2_ctrl
*cptr
;
269 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
271 ret
= pvr2_ctrl_custom_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
273 ret
= pvr2_ctrl_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
275 if (ret
< 0) return ret
;
276 ret
= pvr2_ctrl_set_mask_value(cptr
,mask
,val
);
277 pvr2_hdw_commit_ctl(sfp
->channel
.hdw
);
281 static ssize_t
store_val_norm(int id
,struct device
*class_dev
,
282 const char *buf
,size_t count
)
284 struct pvr2_sysfs
*sfp
;
286 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
287 ret
= store_val_any(id
,0,sfp
,buf
,count
);
288 if (!ret
) ret
= count
;
292 static ssize_t
store_val_custom(int id
,struct device
*class_dev
,
293 const char *buf
,size_t count
)
295 struct pvr2_sysfs
*sfp
;
297 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
298 ret
= store_val_any(id
,1,sfp
,buf
,count
);
299 if (!ret
) ret
= count
;
304 Mike Isely <isely@pobox.com> 30-April-2005
306 This next batch of horrible preprocessor hackery is needed because the
307 kernel's device_attribute mechanism fails to pass the actual
308 attribute through to the show / store functions, which means we have no
309 way to package up any attribute-specific parameters, like for example the
310 control id. So we work around this brain-damage by encoding the control
311 id into the show / store functions themselves and pick the function based
312 on the control id we're setting up. These macros try to ease the pain.
316 #define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
317 static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
318 struct device_attribute *attr, char *buf) \
319 { return sf_name(ctl_id,class_dev,buf); }
321 #define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
322 static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
323 struct device_attribute *attr, const char *buf, size_t count) \
324 { return sf_name(ctl_id,class_dev,buf,count); }
326 #define CREATE_BATCH(ctl_id) \
327 CREATE_SHOW_INSTANCE(show_name,ctl_id) \
328 CREATE_SHOW_INSTANCE(show_type,ctl_id) \
329 CREATE_SHOW_INSTANCE(show_min,ctl_id) \
330 CREATE_SHOW_INSTANCE(show_max,ctl_id) \
331 CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
332 CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
333 CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
334 CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
335 CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
336 CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
399 struct pvr2_sysfs_func_set
{
400 ssize_t (*show_name
)(struct device
*,
401 struct device_attribute
*attr
, char *);
402 ssize_t (*show_type
)(struct device
*,
403 struct device_attribute
*attr
, char *);
404 ssize_t (*show_min
)(struct device
*,
405 struct device_attribute
*attr
, char *);
406 ssize_t (*show_max
)(struct device
*,
407 struct device_attribute
*attr
, char *);
408 ssize_t (*show_enum
)(struct device
*,
409 struct device_attribute
*attr
, char *);
410 ssize_t (*show_bits
)(struct device
*,
411 struct device_attribute
*attr
, char *);
412 ssize_t (*show_val_norm
)(struct device
*,
413 struct device_attribute
*attr
, char *);
414 ssize_t (*store_val_norm
)(struct device
*,
415 struct device_attribute
*attr
,
416 const char *,size_t);
417 ssize_t (*show_val_custom
)(struct device
*,
418 struct device_attribute
*attr
, char *);
419 ssize_t (*store_val_custom
)(struct device
*,
420 struct device_attribute
*attr
,
421 const char *,size_t);
424 #define INIT_BATCH(ctl_id) \
426 .show_name = show_name_##ctl_id, \
427 .show_type = show_type_##ctl_id, \
428 .show_min = show_min_##ctl_id, \
429 .show_max = show_max_##ctl_id, \
430 .show_enum = show_enum_##ctl_id, \
431 .show_bits = show_bits_##ctl_id, \
432 .show_val_norm = show_val_norm_##ctl_id, \
433 .store_val_norm = store_val_norm_##ctl_id, \
434 .show_val_custom = show_val_custom_##ctl_id, \
435 .store_val_custom = store_val_custom_##ctl_id, \
438 static struct pvr2_sysfs_func_set funcs[] = {
502 static void pvr2_sysfs_add_control(struct pvr2_sysfs
*sfp
,int ctl_id
)
504 struct pvr2_sysfs_ctl_item
*cip
;
505 struct pvr2_sysfs_func_set
*fp
;
506 struct pvr2_ctrl
*cptr
;
507 unsigned int cnt
,acnt
;
510 if ((ctl_id
< 0) || (ctl_id
>= ARRAY_SIZE(funcs
))) {
515 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,ctl_id
);
518 cip
= kzalloc(sizeof(*cip
),GFP_KERNEL
);
520 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip
);
525 cip
->item_next
= NULL
;
526 if (sfp
->item_last
) {
527 sfp
->item_last
->item_next
= cip
;
529 sfp
->item_first
= cip
;
531 sfp
->item_last
= cip
;
533 cip
->attr_name
.attr
.name
= "name";
534 cip
->attr_name
.attr
.mode
= S_IRUGO
;
535 cip
->attr_name
.show
= fp
->show_name
;
537 cip
->attr_type
.attr
.name
= "type";
538 cip
->attr_type
.attr
.mode
= S_IRUGO
;
539 cip
->attr_type
.show
= fp
->show_type
;
541 cip
->attr_min
.attr
.name
= "min_val";
542 cip
->attr_min
.attr
.mode
= S_IRUGO
;
543 cip
->attr_min
.show
= fp
->show_min
;
545 cip
->attr_max
.attr
.name
= "max_val";
546 cip
->attr_max
.attr
.mode
= S_IRUGO
;
547 cip
->attr_max
.show
= fp
->show_max
;
549 cip
->attr_val
.attr
.name
= "cur_val";
550 cip
->attr_val
.attr
.mode
= S_IRUGO
;
552 cip
->attr_custom
.attr
.name
= "custom_val";
553 cip
->attr_custom
.attr
.mode
= S_IRUGO
;
555 cip
->attr_enum
.attr
.name
= "enum_val";
556 cip
->attr_enum
.attr
.mode
= S_IRUGO
;
557 cip
->attr_enum
.show
= fp
->show_enum
;
559 cip
->attr_bits
.attr
.name
= "bit_val";
560 cip
->attr_bits
.attr
.mode
= S_IRUGO
;
561 cip
->attr_bits
.show
= fp
->show_bits
;
563 if (pvr2_ctrl_is_writable(cptr
)) {
564 cip
->attr_val
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
565 cip
->attr_custom
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
569 cip
->attr_gen
[acnt
++] = &cip
->attr_name
.attr
;
570 cip
->attr_gen
[acnt
++] = &cip
->attr_type
.attr
;
571 cip
->attr_gen
[acnt
++] = &cip
->attr_val
.attr
;
572 cip
->attr_val
.show
= fp
->show_val_norm
;
573 cip
->attr_val
.store
= fp
->store_val_norm
;
574 if (pvr2_ctrl_has_custom_symbols(cptr
)) {
575 cip
->attr_gen
[acnt
++] = &cip
->attr_custom
.attr
;
576 cip
->attr_custom
.show
= fp
->show_val_custom
;
577 cip
->attr_custom
.store
= fp
->store_val_custom
;
579 switch (pvr2_ctrl_get_type(cptr
)) {
581 // Control is an enumeration
582 cip
->attr_gen
[acnt
++] = &cip
->attr_enum
.attr
;
585 // Control is an integer
586 cip
->attr_gen
[acnt
++] = &cip
->attr_min
.attr
;
587 cip
->attr_gen
[acnt
++] = &cip
->attr_max
.attr
;
589 case pvr2_ctl_bitmask
:
590 // Control is an bitmask
591 cip
->attr_gen
[acnt
++] = &cip
->attr_bits
.attr
;
596 cnt
= scnprintf(cip
->name
,sizeof(cip
->name
)-1,"ctl_%s",
597 pvr2_ctrl_get_name(cptr
));
599 cip
->grp
.name
= cip
->name
;
600 cip
->grp
.attrs
= cip
->attr_gen
;
602 ret
= sysfs_create_group(&sfp
->class_dev
->kobj
,&cip
->grp
);
604 printk(KERN_WARNING
"%s: sysfs_create_group error: %d\n",
608 cip
->created_ok
= !0;
611 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
612 static ssize_t
debuginfo_show(struct device
*, struct device_attribute
*,
614 static ssize_t
debugcmd_show(struct device
*, struct device_attribute
*,
616 static ssize_t
debugcmd_store(struct device
*, struct device_attribute
*,
617 const char *, size_t count
);
619 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs
*sfp
)
621 struct pvr2_sysfs_debugifc
*dip
;
624 dip
= kzalloc(sizeof(*dip
),GFP_KERNEL
);
626 dip
->attr_debugcmd
.attr
.name
= "debugcmd";
627 dip
->attr_debugcmd
.attr
.mode
= S_IRUGO
|S_IWUSR
|S_IWGRP
;
628 dip
->attr_debugcmd
.show
= debugcmd_show
;
629 dip
->attr_debugcmd
.store
= debugcmd_store
;
630 dip
->attr_debuginfo
.attr
.name
= "debuginfo";
631 dip
->attr_debuginfo
.attr
.mode
= S_IRUGO
;
632 dip
->attr_debuginfo
.show
= debuginfo_show
;
634 ret
= device_create_file(sfp
->class_dev
,&dip
->attr_debugcmd
);
636 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
639 dip
->debugcmd_created_ok
= !0;
641 ret
= device_create_file(sfp
->class_dev
,&dip
->attr_debuginfo
);
643 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
646 dip
->debuginfo_created_ok
= !0;
651 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs
*sfp
)
653 if (!sfp
->debugifc
) return;
654 if (sfp
->debugifc
->debuginfo_created_ok
) {
655 device_remove_file(sfp
->class_dev
,
656 &sfp
->debugifc
->attr_debuginfo
);
658 if (sfp
->debugifc
->debugcmd_created_ok
) {
659 device_remove_file(sfp
->class_dev
,
660 &sfp
->debugifc
->attr_debugcmd
);
662 kfree(sfp
->debugifc
);
663 sfp
->debugifc
= NULL
;
665 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
668 static void pvr2_sysfs_add_controls(struct pvr2_sysfs
*sfp
)
670 unsigned int idx
,cnt
;
671 cnt
= pvr2_hdw_get_ctrl_count(sfp
->channel
.hdw
);
672 for (idx
= 0; idx
< cnt
; idx
++) {
673 pvr2_sysfs_add_control(sfp
,idx
);
678 static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs
*sfp
)
680 struct pvr2_sysfs_ctl_item
*cip1
,*cip2
;
681 for (cip1
= sfp
->item_first
; cip1
; cip1
= cip2
) {
682 cip2
= cip1
->item_next
;
683 if (cip1
->created_ok
) {
684 sysfs_remove_group(&sfp
->class_dev
->kobj
,&cip1
->grp
);
686 pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1
);
692 static void pvr2_sysfs_class_release(struct class *class)
694 struct pvr2_sysfs_class
*clp
;
695 clp
= container_of(class,struct pvr2_sysfs_class
,class);
696 pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp
);
701 static void pvr2_sysfs_release(struct device
*class_dev
)
703 pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev
);
708 static void class_dev_destroy(struct pvr2_sysfs
*sfp
)
710 if (!sfp
->class_dev
) return;
711 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
712 pvr2_sysfs_tear_down_debugifc(sfp
);
713 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
714 pvr2_sysfs_tear_down_controls(sfp
);
715 if (sfp
->bus_info_created_ok
) {
716 device_remove_file(sfp
->class_dev
,
717 &sfp
->attr_bus_info
);
719 if (sfp
->v4l_minor_number_created_ok
) {
720 device_remove_file(sfp
->class_dev
,
721 &sfp
->attr_v4l_minor_number
);
723 if (sfp
->v4l_radio_minor_number_created_ok
) {
724 device_remove_file(sfp
->class_dev
,
725 &sfp
->attr_v4l_radio_minor_number
);
727 if (sfp
->unit_number_created_ok
) {
728 device_remove_file(sfp
->class_dev
,
729 &sfp
->attr_unit_number
);
731 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp
->class_dev
);
732 sfp
->class_dev
->driver_data
= NULL
;
733 device_unregister(sfp
->class_dev
);
734 sfp
->class_dev
= NULL
;
738 static ssize_t
v4l_minor_number_show(struct device
*class_dev
,
739 struct device_attribute
*attr
, char *buf
)
741 struct pvr2_sysfs
*sfp
;
742 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
743 if (!sfp
) return -EINVAL
;
744 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
745 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
746 pvr2_v4l_type_video
));
750 static ssize_t
bus_info_show(struct device
*class_dev
,
751 struct device_attribute
*attr
, char *buf
)
753 struct pvr2_sysfs
*sfp
;
754 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
755 if (!sfp
) return -EINVAL
;
756 return scnprintf(buf
,PAGE_SIZE
,"%s\n",
757 pvr2_hdw_get_bus_info(sfp
->channel
.hdw
));
761 static ssize_t
v4l_radio_minor_number_show(struct device
*class_dev
,
762 struct device_attribute
*attr
,
765 struct pvr2_sysfs
*sfp
;
766 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
767 if (!sfp
) return -EINVAL
;
768 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
769 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
770 pvr2_v4l_type_radio
));
774 static ssize_t
unit_number_show(struct device
*class_dev
,
775 struct device_attribute
*attr
, char *buf
)
777 struct pvr2_sysfs
*sfp
;
778 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
779 if (!sfp
) return -EINVAL
;
780 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
781 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
));
785 static void class_dev_create(struct pvr2_sysfs
*sfp
,
786 struct pvr2_sysfs_class
*class_ptr
)
788 struct usb_device
*usb_dev
;
789 struct device
*class_dev
;
792 usb_dev
= pvr2_hdw_get_dev(sfp
->channel
.hdw
);
793 if (!usb_dev
) return;
794 class_dev
= kzalloc(sizeof(*class_dev
),GFP_KERNEL
);
795 if (!class_dev
) return;
797 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev
);
799 class_dev
->class = &class_ptr
->class;
800 if (pvr2_hdw_get_sn(sfp
->channel
.hdw
)) {
801 snprintf(class_dev
->bus_id
, BUS_ID_SIZE
, "sn-%lu",
802 pvr2_hdw_get_sn(sfp
->channel
.hdw
));
803 } else if (pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) >= 0) {
804 snprintf(class_dev
->bus_id
, BUS_ID_SIZE
, "unit-%c",
805 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) + 'a');
811 class_dev
->parent
= &usb_dev
->dev
;
813 sfp
->class_dev
= class_dev
;
814 class_dev
->driver_data
= sfp
;
815 ret
= device_register(class_dev
);
817 printk(KERN_ERR
"%s: device_register failed\n",
823 sfp
->attr_v4l_minor_number
.attr
.name
= "v4l_minor_number";
824 sfp
->attr_v4l_minor_number
.attr
.mode
= S_IRUGO
;
825 sfp
->attr_v4l_minor_number
.show
= v4l_minor_number_show
;
826 sfp
->attr_v4l_minor_number
.store
= NULL
;
827 ret
= device_create_file(sfp
->class_dev
,
828 &sfp
->attr_v4l_minor_number
);
830 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
833 sfp
->v4l_minor_number_created_ok
= !0;
836 sfp
->attr_v4l_radio_minor_number
.attr
.name
= "v4l_radio_minor_number";
837 sfp
->attr_v4l_radio_minor_number
.attr
.mode
= S_IRUGO
;
838 sfp
->attr_v4l_radio_minor_number
.show
= v4l_radio_minor_number_show
;
839 sfp
->attr_v4l_radio_minor_number
.store
= NULL
;
840 ret
= device_create_file(sfp
->class_dev
,
841 &sfp
->attr_v4l_radio_minor_number
);
843 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
846 sfp
->v4l_radio_minor_number_created_ok
= !0;
849 sfp
->attr_unit_number
.attr
.name
= "unit_number";
850 sfp
->attr_unit_number
.attr
.mode
= S_IRUGO
;
851 sfp
->attr_unit_number
.show
= unit_number_show
;
852 sfp
->attr_unit_number
.store
= NULL
;
853 ret
= device_create_file(sfp
->class_dev
,&sfp
->attr_unit_number
);
855 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
858 sfp
->unit_number_created_ok
= !0;
861 sfp
->attr_bus_info
.attr
.name
= "bus_info_str";
862 sfp
->attr_bus_info
.attr
.mode
= S_IRUGO
;
863 sfp
->attr_bus_info
.show
= bus_info_show
;
864 sfp
->attr_bus_info
.store
= NULL
;
865 ret
= device_create_file(sfp
->class_dev
,
866 &sfp
->attr_bus_info
);
868 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
871 sfp
->bus_info_created_ok
= !0;
874 pvr2_sysfs_add_controls(sfp
);
875 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
876 pvr2_sysfs_add_debugifc(sfp
);
877 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
881 static void pvr2_sysfs_internal_check(struct pvr2_channel
*chp
)
883 struct pvr2_sysfs
*sfp
;
884 sfp
= container_of(chp
,struct pvr2_sysfs
,channel
);
885 if (!sfp
->channel
.mc_head
->disconnect_flag
) return;
886 pvr2_trace(PVR2_TRACE_STRUCT
,"Destroying pvr2_sysfs id=%p",sfp
);
887 class_dev_destroy(sfp
);
888 pvr2_channel_done(&sfp
->channel
);
893 struct pvr2_sysfs
*pvr2_sysfs_create(struct pvr2_context
*mp
,
894 struct pvr2_sysfs_class
*class_ptr
)
896 struct pvr2_sysfs
*sfp
;
897 sfp
= kzalloc(sizeof(*sfp
),GFP_KERNEL
);
898 if (!sfp
) return sfp
;
899 pvr2_trace(PVR2_TRACE_STRUCT
,"Creating pvr2_sysfs id=%p",sfp
);
900 pvr2_channel_init(&sfp
->channel
,mp
);
901 sfp
->channel
.check_func
= pvr2_sysfs_internal_check
;
903 class_dev_create(sfp
,class_ptr
);
908 static int pvr2_sysfs_hotplug(struct device
*cd
,char **envp
,
909 int numenvp
,char *buf
,int size
)
911 /* Even though we don't do anything here, we still need this function
912 because sysfs will still try to call it. */
916 struct pvr2_sysfs_class
*pvr2_sysfs_class_create(void)
918 struct pvr2_sysfs_class
*clp
;
919 clp
= kzalloc(sizeof(*clp
),GFP_KERNEL
);
920 if (!clp
) return clp
;
921 pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp
);
922 clp
->class.name
= "pvrusb2";
923 clp
->class.class_release
= pvr2_sysfs_class_release
;
924 clp
->class.dev_release
= pvr2_sysfs_release
;
925 clp
->class.dev_uevent
= pvr2_sysfs_hotplug
;
926 if (class_register(&clp
->class)) {
928 "Registration failed for pvr2_sysfs_class id=%p",clp
);
936 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class
*clp
)
938 class_unregister(&clp
->class);
942 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
943 static ssize_t
debuginfo_show(struct device
*class_dev
,
944 struct device_attribute
*attr
, char *buf
)
946 struct pvr2_sysfs
*sfp
;
947 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
948 if (!sfp
) return -EINVAL
;
949 pvr2_hdw_trigger_module_log(sfp
->channel
.hdw
);
950 return pvr2_debugifc_print_info(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
954 static ssize_t
debugcmd_show(struct device
*class_dev
,
955 struct device_attribute
*attr
, char *buf
)
957 struct pvr2_sysfs
*sfp
;
958 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
959 if (!sfp
) return -EINVAL
;
960 return pvr2_debugifc_print_status(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
964 static ssize_t
debugcmd_store(struct device
*class_dev
,
965 struct device_attribute
*attr
,
966 const char *buf
, size_t count
)
968 struct pvr2_sysfs
*sfp
;
971 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
972 if (!sfp
) return -EINVAL
;
974 ret
= pvr2_debugifc_docmd(sfp
->channel
.hdw
,buf
,count
);
975 if (ret
< 0) return ret
;
978 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
982 Stuff for Emacs to see, in order to encourage consistent editing style:
983 *** Local Variables: ***
985 *** fill-column: 75 ***
987 *** c-basic-offset: 8 ***