Merge tag 'metag-for-v3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan...
[cascardo/linux.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 }