]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/dgrp/dgrp_sysfs.c
Merge tag '3.15-fixes' of git://neil.brown.name/md
[mirror_ubuntu-artful-kernel.git] / drivers / staging / dgrp / dgrp_sysfs.c
1 /*
2 * Copyright 2004 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 */
16
17 #include "dgrp_common.h"
18
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/ctype.h>
22 #include <linux/string.h>
23 #include <linux/serial_reg.h>
24 #include <linux/pci.h>
25 #include <linux/kdev_t.h>
26
27
28 #define PORTSERVER_DIVIDEND 1843200
29 #define SERIAL_TYPE_NORMAL 1
30 #define SERIAL_TYPE_CALLOUT 2
31 #define SERIAL_TYPE_XPRINT 3
32
33
34 static struct class *dgrp_class;
35 static struct device *dgrp_class_nodes_dev;
36 static struct device *dgrp_class_global_settings_dev;
37
38
39 static ssize_t dgrp_class_version_show(struct class *class,
40 struct class_attribute *attr, char *buf)
41 {
42 return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION);
43 }
44 static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL);
45
46
47 static ssize_t dgrp_class_register_with_sysfs_show(struct device *c,
48 struct device_attribute *attr,
49 char *buf)
50 {
51 return snprintf(buf, PAGE_SIZE, "1\n");
52 }
53 static DEVICE_ATTR(register_with_sysfs, 0400,
54 dgrp_class_register_with_sysfs_show, NULL);
55
56
57 static ssize_t dgrp_class_pollrate_show(struct device *c,
58 struct device_attribute *attr,
59 char *buf)
60 {
61 return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick);
62 }
63
64 static ssize_t dgrp_class_pollrate_store(struct device *c,
65 struct device_attribute *attr,
66 const char *buf, size_t count)
67 {
68 if (sscanf(buf, "0x%x\n", &dgrp_poll_tick) != 1)
69 return -EINVAL;
70
71 return count;
72 }
73 static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
74 dgrp_class_pollrate_store);
75
76 static struct attribute *dgrp_sysfs_global_settings_entries[] = {
77 &dev_attr_pollrate.attr,
78 &dev_attr_register_with_sysfs.attr,
79 NULL
80 };
81
82
83 static struct attribute_group dgrp_global_settings_attribute_group = {
84 .name = NULL,
85 .attrs = dgrp_sysfs_global_settings_entries,
86 };
87
88
89
90 int dgrp_create_class_sysfs_files(void)
91 {
92 int ret = 0;
93 int max_majors = 1U << (32 - MINORBITS);
94
95 dgrp_class = class_create(THIS_MODULE, "digi_realport");
96 if (IS_ERR(dgrp_class))
97 return PTR_ERR(dgrp_class);
98 ret = class_create_file(dgrp_class, &class_attr_driver_version);
99 if (ret)
100 goto err_class;
101
102 dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
103 MKDEV(0, max_majors + 1), NULL, "driver_settings");
104 if (IS_ERR(dgrp_class_global_settings_dev)) {
105 ret = PTR_ERR(dgrp_class_global_settings_dev);
106 goto err_file;
107 }
108 ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
109 &dgrp_global_settings_attribute_group);
110 if (ret) {
111 pr_alert("%s: failed to create sysfs global settings device attributes.\n",
112 __func__);
113 goto err_dev1;
114 }
115
116 dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
117 MKDEV(0, max_majors + 2), NULL, "nodes");
118 if (IS_ERR(dgrp_class_nodes_dev)) {
119 ret = PTR_ERR(dgrp_class_nodes_dev);
120 goto err_group;
121 }
122
123 return 0;
124 err_group:
125 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
126 &dgrp_global_settings_attribute_group);
127 err_dev1:
128 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
129 err_file:
130 class_remove_file(dgrp_class, &class_attr_driver_version);
131 err_class:
132 class_destroy(dgrp_class);
133 return ret;
134 }
135
136
137 void dgrp_remove_class_sysfs_files(void)
138 {
139 struct nd_struct *nd;
140 int max_majors = 1U << (32 - MINORBITS);
141
142 list_for_each_entry(nd, &nd_struct_list, list)
143 dgrp_remove_node_class_sysfs_files(nd);
144
145 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
146 &dgrp_global_settings_attribute_group);
147
148 class_remove_file(dgrp_class, &class_attr_driver_version);
149
150 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
151 device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
152 class_destroy(dgrp_class);
153 }
154
155 static ssize_t dgrp_node_state_show(struct device *c,
156 struct device_attribute *attr, char *buf)
157 {
158 struct nd_struct *nd;
159
160 if (!c)
161 return 0;
162 nd = dev_get_drvdata(c);
163 if (!nd)
164 return 0;
165
166 return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
167 }
168
169 static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
170
171 static ssize_t dgrp_node_description_show(struct device *c,
172 struct device_attribute *attr,
173 char *buf)
174 {
175 struct nd_struct *nd;
176
177 if (!c)
178 return 0;
179 nd = dev_get_drvdata(c);
180 if (!nd)
181 return 0;
182
183 if (nd->nd_state == NS_READY)
184 return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
185 return 0;
186 }
187 static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
188
189 static ssize_t dgrp_node_hw_version_show(struct device *c,
190 struct device_attribute *attr,
191 char *buf)
192 {
193 struct nd_struct *nd;
194
195 if (!c)
196 return 0;
197 nd = dev_get_drvdata(c);
198 if (!nd)
199 return 0;
200
201 if (nd->nd_state == NS_READY)
202 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
203 (nd->nd_hw_ver >> 8) & 0xff,
204 nd->nd_hw_ver & 0xff);
205
206 return 0;
207 }
208 static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
209
210 static ssize_t dgrp_node_hw_id_show(struct device *c,
211 struct device_attribute *attr, char *buf)
212 {
213 struct nd_struct *nd;
214
215 if (!c)
216 return 0;
217 nd = dev_get_drvdata(c);
218 if (!nd)
219 return 0;
220
221
222 if (nd->nd_state == NS_READY)
223 return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
224 return 0;
225 }
226 static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
227
228 static ssize_t dgrp_node_sw_version_show(struct device *c,
229 struct device_attribute *attr,
230 char *buf)
231 {
232 struct nd_struct *nd;
233
234 if (!c)
235 return 0;
236
237 nd = dev_get_drvdata(c);
238 if (!nd)
239 return 0;
240
241 if (nd->nd_state == NS_READY)
242 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
243 (nd->nd_sw_ver >> 8) & 0xff,
244 nd->nd_sw_ver & 0xff);
245
246 return 0;
247 }
248 static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
249
250
251 static struct attribute *dgrp_sysfs_node_entries[] = {
252 &dev_attr_state.attr,
253 &dev_attr_description_info.attr,
254 &dev_attr_hw_version_info.attr,
255 &dev_attr_hw_id_info.attr,
256 &dev_attr_sw_version_info.attr,
257 NULL
258 };
259
260
261 static struct attribute_group dgrp_node_attribute_group = {
262 .name = NULL,
263 .attrs = dgrp_sysfs_node_entries,
264 };
265
266
267 void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
268 {
269 int ret;
270 char name[10];
271
272 if (nd->nd_ID)
273 ID_TO_CHAR(nd->nd_ID, name);
274 else
275 sprintf(name, "node%ld", nd->nd_major);
276
277 nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
278 MKDEV(0, nd->nd_major), NULL, "%s", name);
279
280 ret = sysfs_create_group(&nd->nd_class_dev->kobj,
281 &dgrp_node_attribute_group);
282
283 if (ret) {
284 pr_alert("%s: failed to create sysfs node device attributes.\n",
285 __func__);
286 sysfs_remove_group(&nd->nd_class_dev->kobj,
287 &dgrp_node_attribute_group);
288 return;
289 }
290
291 dev_set_drvdata(nd->nd_class_dev, nd);
292
293 }
294
295
296 void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
297 {
298 if (nd->nd_class_dev) {
299 sysfs_remove_group(&nd->nd_class_dev->kobj,
300 &dgrp_node_attribute_group);
301
302 device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
303 nd->nd_class_dev = NULL;
304 }
305 }
306
307
308
309 static ssize_t dgrp_tty_state_show(struct device *d,
310 struct device_attribute *attr, char *buf)
311 {
312 struct un_struct *un;
313
314 if (!d)
315 return 0;
316 un = dev_get_drvdata(d);
317 if (!un)
318 return 0;
319
320 return snprintf(buf, PAGE_SIZE, "%s\n",
321 un->un_open_count ? "Open" : "Closed");
322 }
323 static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
324
325 static ssize_t dgrp_tty_baud_show(struct device *d,
326 struct device_attribute *attr, char *buf)
327 {
328 struct ch_struct *ch;
329 struct un_struct *un;
330
331 if (!d)
332 return 0;
333 un = dev_get_drvdata(d);
334 if (!un)
335 return 0;
336 ch = un->un_ch;
337 if (!ch)
338 return 0;
339 return snprintf(buf, PAGE_SIZE, "%d\n",
340 un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
341 }
342 static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
343
344
345 static ssize_t dgrp_tty_msignals_show(struct device *d,
346 struct device_attribute *attr, char *buf)
347 {
348 struct ch_struct *ch;
349 struct un_struct *un;
350
351 if (!d)
352 return 0;
353 un = dev_get_drvdata(d);
354 if (!un)
355 return 0;
356 ch = un->un_ch;
357 if (!ch)
358 return 0;
359
360 if (ch->ch_open_count) {
361 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
362 (ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
363 (ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
364 (ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
365 (ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
366 (ch->ch_s_mlast & DM_CD) ? "DCD" : "",
367 (ch->ch_s_mlast & DM_RI) ? "RI" : "");
368 }
369 return 0;
370 }
371 static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
372
373
374 static ssize_t dgrp_tty_iflag_show(struct device *d,
375 struct device_attribute *attr, char *buf)
376 {
377 struct ch_struct *ch;
378 struct un_struct *un;
379
380 if (!d)
381 return 0;
382 un = dev_get_drvdata(d);
383 if (!un)
384 return 0;
385 ch = un->un_ch;
386 if (!ch)
387 return 0;
388 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
389 }
390 static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
391
392
393 static ssize_t dgrp_tty_cflag_show(struct device *d,
394 struct device_attribute *attr, char *buf)
395 {
396 struct ch_struct *ch;
397 struct un_struct *un;
398
399 if (!d)
400 return 0;
401 un = dev_get_drvdata(d);
402 if (!un)
403 return 0;
404 ch = un->un_ch;
405 if (!ch)
406 return 0;
407 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
408 }
409 static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
410
411
412 static ssize_t dgrp_tty_oflag_show(struct device *d,
413 struct device_attribute *attr, char *buf)
414 {
415 struct ch_struct *ch;
416 struct un_struct *un;
417
418 if (!d)
419 return 0;
420 un = dev_get_drvdata(d);
421 if (!un)
422 return 0;
423 ch = un->un_ch;
424 if (!ch)
425 return 0;
426 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
427 }
428 static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
429
430
431 static ssize_t dgrp_tty_digi_flag_show(struct device *d,
432 struct device_attribute *attr, char *buf)
433 {
434 struct ch_struct *ch;
435 struct un_struct *un;
436
437 if (!d)
438 return 0;
439 un = dev_get_drvdata(d);
440 if (!un)
441 return 0;
442 ch = un->un_ch;
443 if (!ch)
444 return 0;
445 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
446 }
447 static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
448
449
450 static ssize_t dgrp_tty_rxcount_show(struct device *d,
451 struct device_attribute *attr, char *buf)
452 {
453 struct ch_struct *ch;
454 struct un_struct *un;
455
456 if (!d)
457 return 0;
458 un = dev_get_drvdata(d);
459 if (!un)
460 return 0;
461 ch = un->un_ch;
462 if (!ch)
463 return 0;
464 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
465 }
466 static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
467
468
469 static ssize_t dgrp_tty_txcount_show(struct device *d,
470 struct device_attribute *attr, char *buf)
471 {
472 struct ch_struct *ch;
473 struct un_struct *un;
474
475 if (!d)
476 return 0;
477 un = dev_get_drvdata(d);
478 if (!un)
479 return 0;
480 ch = un->un_ch;
481 if (!ch)
482 return 0;
483 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
484 }
485 static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
486
487
488 static ssize_t dgrp_tty_name_show(struct device *d,
489 struct device_attribute *attr, char *buf)
490 {
491 struct nd_struct *nd;
492 struct ch_struct *ch;
493 struct un_struct *un;
494 char name[10];
495
496 if (!d)
497 return 0;
498 un = dev_get_drvdata(d);
499 if (!un)
500 return 0;
501 ch = un->un_ch;
502 if (!ch)
503 return 0;
504 nd = ch->ch_nd;
505 if (!nd)
506 return 0;
507
508 ID_TO_CHAR(nd->nd_ID, name);
509
510 return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
511 un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
512 name, ch->ch_portnum);
513 }
514 static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
515
516
517 static struct attribute *dgrp_sysfs_tty_entries[] = {
518 &dev_attr_state_info.attr,
519 &dev_attr_baud_info.attr,
520 &dev_attr_msignals_info.attr,
521 &dev_attr_iflag_info.attr,
522 &dev_attr_cflag_info.attr,
523 &dev_attr_oflag_info.attr,
524 &dev_attr_digi_flag_info.attr,
525 &dev_attr_rxcount_info.attr,
526 &dev_attr_txcount_info.attr,
527 &dev_attr_custom_name.attr,
528 NULL
529 };
530
531
532 static struct attribute_group dgrp_tty_attribute_group = {
533 .name = NULL,
534 .attrs = dgrp_sysfs_tty_entries,
535 };
536
537
538 void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
539 {
540 int ret;
541
542 ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
543 if (ret) {
544 pr_alert("%s: failed to create sysfs tty device attributes.\n",
545 __func__);
546 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
547 return;
548 }
549
550 dev_set_drvdata(c, un);
551
552 }
553
554
555 void dgrp_remove_tty_sysfs(struct device *c)
556 {
557 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
558 }