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