staging: dgnc: Check sscanf return value
[firefly-linux-kernel-4.4.55.git] / drivers / staging / dgnc / dgnc_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  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
21  *
22  *      This is shared code between Digi's CVS archive and the
23  *      Linux Kernel sources.
24  *      Changing the source just for reformatting needlessly breaks
25  *      our CVS diff history.
26  *
27  *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
28  *      Thank you.
29  *
30  */
31
32
33 #include <linux/kernel.h>
34 #include <linux/module.h>
35 #include <linux/ctype.h>
36 #include <linux/string.h>
37 #include <linux/serial_reg.h>
38 #include <linux/device.h>
39 #include <linux/pci.h>
40 #include <linux/kdev_t.h>
41
42 #include "dgnc_driver.h"
43 #include "dgnc_mgmt.h"
44
45
46 static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf)
47 {
48         return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
49 }
50 static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL);
51
52
53 static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf)
54 {
55         return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards);
56 }
57 static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL);
58
59
60 static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf)
61 {
62         return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
63 }
64 static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL);
65
66 static ssize_t dgnc_driver_debug_show(struct device_driver *ddp, char *buf)
67 {
68         return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_debug);
69 }
70
71 static ssize_t dgnc_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
72 {
73         int ret;
74
75         ret = sscanf(buf, "0x%x\n", &dgnc_debug);
76         if (ret != 1)
77                 return -EINVAL;
78         return count;
79 }
80 static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgnc_driver_debug_show, dgnc_driver_debug_store);
81
82
83 static ssize_t dgnc_driver_rawreadok_show(struct device_driver *ddp, char *buf)
84 {
85         return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_rawreadok);
86 }
87
88 static ssize_t dgnc_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
89 {
90         int ret;
91
92         ret = sscanf(buf, "0x%x\n", &dgnc_rawreadok);
93         if (ret != 1)
94                 return -EINVAL;
95         return count;
96 }
97 static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgnc_driver_rawreadok_show, dgnc_driver_rawreadok_store);
98
99
100 static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf)
101 {
102         return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick);
103 }
104
105 static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
106 {
107         int ret;
108
109         ret = sscanf(buf, "%d\n", &dgnc_poll_tick);
110         if (ret != 1)
111                 return -EINVAL;
112         return count;
113 }
114 static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store);
115
116
117 void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
118 {
119         int rc = 0;
120         struct device_driver *driverfs = &dgnc_driver->driver;
121
122         rc |= driver_create_file(driverfs, &driver_attr_version);
123         rc |= driver_create_file(driverfs, &driver_attr_boards);
124         rc |= driver_create_file(driverfs, &driver_attr_maxboards);
125         rc |= driver_create_file(driverfs, &driver_attr_debug);
126         rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
127         rc |= driver_create_file(driverfs, &driver_attr_pollrate);
128         if (rc) {
129                 printk(KERN_ERR "DGNC: sysfs driver_create_file failed!\n");
130         }
131 }
132
133
134 void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
135 {
136         struct device_driver *driverfs = &dgnc_driver->driver;
137
138         driver_remove_file(driverfs, &driver_attr_version);
139         driver_remove_file(driverfs, &driver_attr_boards);
140         driver_remove_file(driverfs, &driver_attr_maxboards);
141         driver_remove_file(driverfs, &driver_attr_debug);
142         driver_remove_file(driverfs, &driver_attr_rawreadok);
143         driver_remove_file(driverfs, &driver_attr_pollrate);
144 }
145
146
147 #define DGNC_VERIFY_BOARD(p, bd)                                \
148         do {                                                    \
149                 if (!p)                                         \
150                         return 0;                               \
151                                                                 \
152                 bd = dev_get_drvdata(p);                        \
153                 if (!bd || bd->magic != DGNC_BOARD_MAGIC)       \
154                         return 0;                               \
155                 if (bd->state != BOARD_READY)                   \
156                         return 0;                               \
157         } while (0)
158
159
160
161 static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf)
162 {
163         struct dgnc_board *bd;
164         int count = 0;
165         int i = 0;
166
167         DGNC_VERIFY_BOARD(p, bd);
168
169         count += sprintf(buf + count, "\n      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
170         for (i = 0; i < 0x40 * 2; i++) {
171                 if (!(i % 16))
172                         count += sprintf(buf + count, "\n%04X ", i * 2);
173                 count += sprintf(buf + count, "%02X ", bd->vpd[i]);
174         }
175         count += sprintf(buf + count, "\n");
176
177         return count;
178 }
179 static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL);
180
181 static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf)
182 {
183         struct dgnc_board *bd;
184         int count = 0;
185
186         DGNC_VERIFY_BOARD(p, bd);
187
188         if (bd->serial_num[0] == '\0')
189                 count += sprintf(buf + count, "<UNKNOWN>\n");
190         else
191                 count += sprintf(buf + count, "%s\n", bd->serial_num);
192
193         return count;
194 }
195 static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL);
196
197
198 static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
199 {
200         struct dgnc_board *bd;
201         int count = 0;
202         int i = 0;
203
204         DGNC_VERIFY_BOARD(p, bd);
205
206         for (i = 0; i < bd->nasync; i++) {
207                 count += snprintf(buf + count, PAGE_SIZE - count,
208                         "%d %s\n", bd->channels[i]->ch_portnum,
209                         bd->channels[i]->ch_open_count ? "Open" : "Closed");
210         }
211         return count;
212 }
213 static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL);
214
215
216 static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
217 {
218         struct dgnc_board *bd;
219         int count = 0;
220         int i = 0;
221
222         DGNC_VERIFY_BOARD(p, bd);
223
224         for (i = 0; i < bd->nasync; i++) {
225                 count +=  snprintf(buf + count, PAGE_SIZE - count,
226                         "%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_old_baud);
227         }
228         return count;
229 }
230 static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL);
231
232
233 static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
234 {
235         struct dgnc_board *bd;
236         int count = 0;
237         int i = 0;
238
239         DGNC_VERIFY_BOARD(p, bd);
240
241         for (i = 0; i < bd->nasync; i++) {
242                 if (bd->channels[i]->ch_open_count) {
243                         count += snprintf(buf + count, PAGE_SIZE - count,
244                                 "%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
245                                 (bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
246                                 (bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
247                                 (bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
248                                 (bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
249                                 (bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
250                                 (bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
251                 } else {
252                         count += snprintf(buf + count, PAGE_SIZE - count,
253                                 "%d\n", bd->channels[i]->ch_portnum);
254                 }
255         }
256         return count;
257 }
258 static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL);
259
260
261 static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
262 {
263         struct dgnc_board *bd;
264         int count = 0;
265         int i = 0;
266
267         DGNC_VERIFY_BOARD(p, bd);
268
269         for (i = 0; i < bd->nasync; i++) {
270                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
271                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
272         }
273         return count;
274 }
275 static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL);
276
277
278 static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
279 {
280         struct dgnc_board *bd;
281         int count = 0;
282         int i = 0;
283
284         DGNC_VERIFY_BOARD(p, bd);
285
286         for (i = 0; i < bd->nasync; i++) {
287                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
288                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
289         }
290         return count;
291 }
292 static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL);
293
294
295 static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
296 {
297         struct dgnc_board *bd;
298         int count = 0;
299         int i = 0;
300
301         DGNC_VERIFY_BOARD(p, bd);
302
303         for (i = 0; i < bd->nasync; i++) {
304                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
305                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
306         }
307         return count;
308 }
309 static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL);
310
311
312 static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
313 {
314         struct dgnc_board *bd;
315         int count = 0;
316         int i = 0;
317
318         DGNC_VERIFY_BOARD(p, bd);
319
320         for (i = 0; i < bd->nasync; i++) {
321                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
322                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
323         }
324         return count;
325 }
326 static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL);
327
328
329 static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
330 {
331         struct dgnc_board *bd;
332         int count = 0;
333         int i = 0;
334
335         DGNC_VERIFY_BOARD(p, bd);
336
337         for (i = 0; i < bd->nasync; i++) {
338                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
339                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
340         }
341         return count;
342 }
343 static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL);
344
345
346 static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
347 {
348         struct dgnc_board *bd;
349         int count = 0;
350         int i = 0;
351
352         DGNC_VERIFY_BOARD(p, bd);
353
354         for (i = 0; i < bd->nasync; i++) {
355                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
356                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
357         }
358         return count;
359 }
360 static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL);
361
362
363 static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
364 {
365         struct dgnc_board *bd;
366         int count = 0;
367         int i = 0;
368
369         DGNC_VERIFY_BOARD(p, bd);
370
371         for (i = 0; i < bd->nasync; i++) {
372                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
373                         bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
374         }
375         return count;
376 }
377 static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
378
379
380 /* this function creates the sys files that will export each signal status
381  * to sysfs each value will be put in a separate filename
382  */
383 void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
384 {
385         int rc = 0;
386
387         dev_set_drvdata(&bd->pdev->dev, bd);
388         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
389         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
390         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
391         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
392         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
393         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
394         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
395         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
396         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
397         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
398         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_vpd);
399         rc |= device_create_file(&(bd->pdev->dev), &dev_attr_serial_number);
400         if (rc) {
401                 printk(KERN_ERR "DGNC: sysfs device_create_file failed!\n");
402         }
403 }
404
405
406 /* removes all the sys files created for that port */
407 void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
408 {
409         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
410         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
411         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
412         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
413         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
414         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
415         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
416         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
417         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
418         device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
419         device_remove_file(&(bd->pdev->dev), &dev_attr_vpd);
420         device_remove_file(&(bd->pdev->dev), &dev_attr_serial_number);
421 }
422
423
424 static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
425 {
426         struct dgnc_board *bd;
427         struct channel_t *ch;
428         struct un_t *un;
429
430         if (!d)
431                 return 0;
432         un = dev_get_drvdata(d);
433         if (!un || un->magic != DGNC_UNIT_MAGIC)
434                 return 0;
435         ch = un->un_ch;
436         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
437                 return 0;
438         bd = ch->ch_bd;
439         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
440                 return 0;
441         if (bd->state != BOARD_READY)
442                 return 0;
443
444         return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
445 }
446 static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL);
447
448
449 static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
450 {
451         struct dgnc_board *bd;
452         struct channel_t *ch;
453         struct un_t *un;
454
455         if (!d)
456                 return 0;
457         un = dev_get_drvdata(d);
458         if (!un || un->magic != DGNC_UNIT_MAGIC)
459                 return 0;
460         ch = un->un_ch;
461         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
462                 return 0;
463         bd = ch->ch_bd;
464         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
465                 return 0;
466         if (bd->state != BOARD_READY)
467                 return 0;
468
469         return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
470 }
471 static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL);
472
473
474 static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
475 {
476         struct dgnc_board *bd;
477         struct channel_t *ch;
478         struct un_t *un;
479
480         if (!d)
481                 return 0;
482         un = dev_get_drvdata(d);
483         if (!un || un->magic != DGNC_UNIT_MAGIC)
484                 return 0;
485         ch = un->un_ch;
486         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
487                 return 0;
488         bd = ch->ch_bd;
489         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
490                 return 0;
491         if (bd->state != BOARD_READY)
492                 return 0;
493
494         if (ch->ch_open_count) {
495                 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
496                         (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
497                         (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
498                         (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
499                         (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
500                         (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
501                         (ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
502         }
503         return 0;
504 }
505 static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL);
506
507
508 static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
509 {
510         struct dgnc_board *bd;
511         struct channel_t *ch;
512         struct un_t *un;
513
514         if (!d)
515                 return 0;
516         un = dev_get_drvdata(d);
517         if (!un || un->magic != DGNC_UNIT_MAGIC)
518                 return 0;
519         ch = un->un_ch;
520         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
521                 return 0;
522         bd = ch->ch_bd;
523         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
524                 return 0;
525         if (bd->state != BOARD_READY)
526                 return 0;
527
528         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
529 }
530 static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL);
531
532
533 static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
534 {
535         struct dgnc_board *bd;
536         struct channel_t *ch;
537         struct un_t *un;
538
539         if (!d)
540                 return 0;
541         un = dev_get_drvdata(d);
542         if (!un || un->magic != DGNC_UNIT_MAGIC)
543                 return 0;
544         ch = un->un_ch;
545         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
546                 return 0;
547         bd = ch->ch_bd;
548         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
549                 return 0;
550         if (bd->state != BOARD_READY)
551                 return 0;
552
553         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
554 }
555 static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL);
556
557
558 static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
559 {
560         struct dgnc_board *bd;
561         struct channel_t *ch;
562         struct un_t *un;
563
564         if (!d)
565                 return 0;
566         un = dev_get_drvdata(d);
567         if (!un || un->magic != DGNC_UNIT_MAGIC)
568                 return 0;
569         ch = un->un_ch;
570         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
571                 return 0;
572         bd = ch->ch_bd;
573         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
574                 return 0;
575         if (bd->state != BOARD_READY)
576                 return 0;
577
578         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
579 }
580 static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL);
581
582
583 static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
584 {
585         struct dgnc_board *bd;
586         struct channel_t *ch;
587         struct un_t *un;
588
589         if (!d)
590                 return 0;
591         un = dev_get_drvdata(d);
592         if (!un || un->magic != DGNC_UNIT_MAGIC)
593                 return 0;
594         ch = un->un_ch;
595         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
596                 return 0;
597         bd = ch->ch_bd;
598         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
599                 return 0;
600         if (bd->state != BOARD_READY)
601                 return 0;
602
603         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
604 }
605 static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL);
606
607
608 static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
609 {
610         struct dgnc_board *bd;
611         struct channel_t *ch;
612         struct un_t *un;
613
614         if (!d)
615                 return 0;
616         un = dev_get_drvdata(d);
617         if (!un || un->magic != DGNC_UNIT_MAGIC)
618                 return 0;
619         ch = un->un_ch;
620         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
621                 return 0;
622         bd = ch->ch_bd;
623         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
624                 return 0;
625         if (bd->state != BOARD_READY)
626                 return 0;
627
628         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
629 }
630 static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL);
631
632
633 static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
634 {
635         struct dgnc_board *bd;
636         struct channel_t *ch;
637         struct un_t *un;
638
639         if (!d)
640                 return 0;
641         un = dev_get_drvdata(d);
642         if (!un || un->magic != DGNC_UNIT_MAGIC)
643                 return 0;
644         ch = un->un_ch;
645         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
646                 return 0;
647         bd = ch->ch_bd;
648         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
649                 return 0;
650         if (bd->state != BOARD_READY)
651                 return 0;
652
653         return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
654 }
655 static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL);
656
657
658 static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
659 {
660         struct dgnc_board *bd;
661         struct channel_t *ch;
662         struct un_t *un;
663
664         if (!d)
665                 return 0;
666         un = dev_get_drvdata(d);
667         if (!un || un->magic != DGNC_UNIT_MAGIC)
668                 return 0;
669         ch = un->un_ch;
670         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
671                 return 0;
672         bd = ch->ch_bd;
673         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
674                 return 0;
675         if (bd->state != BOARD_READY)
676                 return 0;
677
678         return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
679 }
680 static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL);
681
682
683 static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
684 {
685         struct dgnc_board *bd;
686         struct channel_t *ch;
687         struct un_t *un;
688
689         if (!d)
690                 return 0;
691         un = dev_get_drvdata(d);
692         if (!un || un->magic != DGNC_UNIT_MAGIC)
693                 return 0;
694         ch = un->un_ch;
695         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
696                 return 0;
697         bd = ch->ch_bd;
698         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
699                 return 0;
700         if (bd->state != BOARD_READY)
701                 return 0;
702
703         return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
704                 (un->un_type == DGNC_PRINT) ? "pr" : "tty",
705                 bd->boardnum + 1, 'a' + ch->ch_portnum);
706 }
707 static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL);
708
709
710 static struct attribute *dgnc_sysfs_tty_entries[] = {
711         &dev_attr_state.attr,
712         &dev_attr_baud.attr,
713         &dev_attr_msignals.attr,
714         &dev_attr_iflag.attr,
715         &dev_attr_cflag.attr,
716         &dev_attr_oflag.attr,
717         &dev_attr_lflag.attr,
718         &dev_attr_digi_flag.attr,
719         &dev_attr_rxcount.attr,
720         &dev_attr_txcount.attr,
721         &dev_attr_custom_name.attr,
722         NULL
723 };
724
725
726 static struct attribute_group dgnc_tty_attribute_group = {
727         .name = NULL,
728         .attrs = dgnc_sysfs_tty_entries,
729 };
730
731
732 void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
733 {
734         int ret;
735
736         ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
737         if (ret) {
738                 dev_err(c, "dgnc: failed to create sysfs tty device attributes.\n");
739                 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
740                 return;
741         }
742
743         dev_set_drvdata(c, un);
744
745 }
746
747
748 void dgnc_remove_tty_sysfs(struct device *c)
749 {
750         sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
751 }
752