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