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