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
69 struct pvr2_sysfs_class {
70 struct class class;
71 };
72
show_name(struct device * class_dev,struct device_attribute * attr,char * buf)73 static 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
show_type(struct device * class_dev,struct device_attribute * attr,char * buf)87 static 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
show_min(struct device * class_dev,struct device_attribute * attr,char * buf)108 static 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
show_max(struct device * class_dev,struct device_attribute * attr,char * buf)121 static 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
show_def(struct device * class_dev,struct device_attribute * attr,char * buf)134 static 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
show_val_norm(struct device * class_dev,struct device_attribute * attr,char * buf)153 static 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
show_val_custom(struct device * class_dev,struct device_attribute * attr,char * buf)172 static 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
show_enum(struct device * class_dev,struct device_attribute * attr,char * buf)191 static 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
show_bits(struct device * class_dev,struct device_attribute * attr,char * buf)215 static 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
store_val_any(struct pvr2_sysfs_ctl_item * cip,int customfl,const char * buf,unsigned int count)240 static 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
store_val_norm(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)258 static 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
store_val_custom(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)272 static 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
pvr2_sysfs_add_control(struct pvr2_sysfs * sfp,int ctl_id)286 static 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 // Control is an enumeration
375 cip->attr_gen[acnt++] = &cip->attr_enum.attr;
376 break;
377 case pvr2_ctl_int:
378 // Control is an integer
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 // Control is an bitmask
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
406 static ssize_t debuginfo_show(struct device *, struct device_attribute *,
407 char *);
408 static ssize_t debugcmd_show(struct device *, struct device_attribute *,
409 char *);
410 static ssize_t debugcmd_store(struct device *, struct device_attribute *,
411 const char *, size_t count);
412
pvr2_sysfs_add_debugifc(struct pvr2_sysfs * sfp)413 static 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
pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs * sfp)449 static 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 /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
464
465
pvr2_sysfs_add_controls(struct pvr2_sysfs * sfp)466 static 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
pvr2_sysfs_tear_down_controls(struct pvr2_sysfs * sfp)476 static 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
pvr2_sysfs_class_release(struct class * class)490 static 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
pvr2_sysfs_release(struct device * class_dev)499 static 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
class_dev_destroy(struct pvr2_sysfs * sfp)506 static 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 /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
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
v4l_minor_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)548 static 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
bus_info_show(struct device * class_dev,struct device_attribute * attr,char * buf)560 static 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
hdw_name_show(struct device * class_dev,struct device_attribute * attr,char * buf)571 static 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
hdw_desc_show(struct device * class_dev,struct device_attribute * attr,char * buf)582 static 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
v4l_radio_minor_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)593 static 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
unit_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)606 static 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
class_dev_create(struct pvr2_sysfs * sfp,struct pvr2_sysfs_class * class_ptr)617 static 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 /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
741 }
742
743
pvr2_sysfs_internal_check(struct pvr2_channel * chp)744 static 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
pvr2_sysfs_create(struct pvr2_context * mp,struct pvr2_sysfs_class * class_ptr)756 struct 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
pvr2_sysfs_class_create(void)772 struct 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
pvr2_sysfs_class_destroy(struct pvr2_sysfs_class * clp)792 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
793 {
794 pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
795 if (clp)
796 class_unregister(&clp->class);
797 }
798
799
800 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
debuginfo_show(struct device * class_dev,struct device_attribute * attr,char * buf)801 static ssize_t debuginfo_show(struct device *class_dev,
802 struct device_attribute *attr, char *buf)
803 {
804 struct pvr2_sysfs *sfp;
805 sfp = dev_get_drvdata(class_dev);
806 if (!sfp) return -EINVAL;
807 pvr2_hdw_trigger_module_log(sfp->channel.hdw);
808 return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
809 }
810
811
debugcmd_show(struct device * class_dev,struct device_attribute * attr,char * buf)812 static ssize_t debugcmd_show(struct device *class_dev,
813 struct device_attribute *attr, char *buf)
814 {
815 struct pvr2_sysfs *sfp;
816 sfp = dev_get_drvdata(class_dev);
817 if (!sfp) return -EINVAL;
818 return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
819 }
820
821
debugcmd_store(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)822 static ssize_t debugcmd_store(struct device *class_dev,
823 struct device_attribute *attr,
824 const char *buf, size_t count)
825 {
826 struct pvr2_sysfs *sfp;
827 int ret;
828
829 sfp = dev_get_drvdata(class_dev);
830 if (!sfp) return -EINVAL;
831
832 ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
833 if (ret < 0) return ret;
834 return count;
835 }
836 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
837