staging: dgnc: rename dgnc_tty_uninit() to dgnc_cleanup_tty()
[cascardo/linux.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
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/ctype.h>
19 #include <linux/string.h>
20 #include <linux/serial_reg.h>
21 #include <linux/device.h>
22 #include <linux/pci.h>
23 #include <linux/kdev_t.h>
24
25 #include "dgnc_driver.h"
26 #include "dgnc_mgmt.h"
27
28 static ssize_t version_show(struct device_driver *ddp, char *buf)
29 {
30         return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
31 }
32 static DRIVER_ATTR_RO(version);
33
34 static ssize_t boards_show(struct device_driver *ddp, char *buf)
35 {
36         return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_num_boards);
37 }
38 static DRIVER_ATTR_RO(boards);
39
40 static ssize_t maxboards_show(struct device_driver *ddp, char *buf)
41 {
42         return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
43 }
44 static DRIVER_ATTR_RO(maxboards);
45
46 static ssize_t pollrate_show(struct device_driver *ddp, char *buf)
47 {
48         return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick);
49 }
50
51 static ssize_t pollrate_store(struct device_driver *ddp,
52                               const char *buf, size_t count)
53 {
54         unsigned long flags;
55         int tick;
56         int ret;
57
58         ret = sscanf(buf, "%d\n", &tick);
59         if (ret != 1)
60                 return -EINVAL;
61
62         spin_lock_irqsave(&dgnc_poll_lock, flags);
63         dgnc_poll_tick = tick;
64         spin_unlock_irqrestore(&dgnc_poll_lock, flags);
65
66         return count;
67 }
68 static DRIVER_ATTR_RW(pollrate);
69
70 void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
71 {
72         int rc = 0;
73         struct device_driver *driverfs = &dgnc_driver->driver;
74
75         rc |= driver_create_file(driverfs, &driver_attr_version);
76         rc |= driver_create_file(driverfs, &driver_attr_boards);
77         rc |= driver_create_file(driverfs, &driver_attr_maxboards);
78         rc |= driver_create_file(driverfs, &driver_attr_pollrate);
79         if (rc)
80                 pr_err("DGNC: sysfs driver_create_file failed!\n");
81 }
82
83 void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
84 {
85         struct device_driver *driverfs = &dgnc_driver->driver;
86
87         driver_remove_file(driverfs, &driver_attr_version);
88         driver_remove_file(driverfs, &driver_attr_boards);
89         driver_remove_file(driverfs, &driver_attr_maxboards);
90         driver_remove_file(driverfs, &driver_attr_pollrate);
91 }
92
93 #define DGNC_VERIFY_BOARD(p, bd)                                \
94         do {                                                    \
95                 if (!p)                                         \
96                         return 0;                               \
97                                                                 \
98                 bd = dev_get_drvdata(p);                        \
99                 if (!bd || bd->magic != DGNC_BOARD_MAGIC)       \
100                         return 0;                               \
101                 if (bd->state != BOARD_READY)                   \
102                         return 0;                               \
103         } while (0)
104
105 static ssize_t vpd_show(struct device *p, struct device_attribute *attr,
106                         char *buf)
107 {
108         struct dgnc_board *bd;
109         int count = 0;
110         int i = 0;
111
112         DGNC_VERIFY_BOARD(p, bd);
113
114         count += sprintf(buf + count,
115                 "\n      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
116         for (i = 0; i < 0x40 * 2; i++) {
117                 if (!(i % 16))
118                         count += sprintf(buf + count, "\n%04X ", i * 2);
119                 count += sprintf(buf + count, "%02X ", bd->vpd[i]);
120         }
121         count += sprintf(buf + count, "\n");
122
123         return count;
124 }
125 static DEVICE_ATTR_RO(vpd);
126
127 static ssize_t serial_number_show(struct device *p,
128                                   struct device_attribute *attr, char *buf)
129 {
130         struct dgnc_board *bd;
131         int count = 0;
132
133         DGNC_VERIFY_BOARD(p, bd);
134
135         if (bd->serial_num[0] == '\0')
136                 count += sprintf(buf + count, "<UNKNOWN>\n");
137         else
138                 count += sprintf(buf + count, "%s\n", bd->serial_num);
139
140         return count;
141 }
142 static DEVICE_ATTR_RO(serial_number);
143
144 static ssize_t ports_state_show(struct device *p,
145                                 struct device_attribute *attr, char *buf)
146 {
147         struct dgnc_board *bd;
148         int count = 0;
149         int i = 0;
150
151         DGNC_VERIFY_BOARD(p, bd);
152
153         for (i = 0; i < bd->nasync; i++) {
154                 count += snprintf(buf + count, PAGE_SIZE - count,
155                         "%d %s\n", bd->channels[i]->ch_portnum,
156                         bd->channels[i]->ch_open_count ? "Open" : "Closed");
157         }
158         return count;
159 }
160 static DEVICE_ATTR_RO(ports_state);
161
162 static ssize_t ports_baud_show(struct device *p,
163                                struct device_attribute *attr, char *buf)
164 {
165         struct dgnc_board *bd;
166         int count = 0;
167         int i = 0;
168
169         DGNC_VERIFY_BOARD(p, bd);
170
171         for (i = 0; i < bd->nasync; i++) {
172                 count +=  snprintf(buf + count, PAGE_SIZE - count,
173                         "%d %d\n", bd->channels[i]->ch_portnum,
174                         bd->channels[i]->ch_old_baud);
175         }
176         return count;
177 }
178 static DEVICE_ATTR_RO(ports_baud);
179
180 static ssize_t ports_msignals_show(struct device *p,
181                                    struct device_attribute *attr, char *buf)
182 {
183         struct dgnc_board *bd;
184         int count = 0;
185         int i = 0;
186
187         DGNC_VERIFY_BOARD(p, bd);
188
189         for (i = 0; i < bd->nasync; i++) {
190                 struct channel_t *ch = bd->channels[i];
191
192                 if (ch->ch_open_count) {
193                         count += snprintf(buf + count, PAGE_SIZE - count,
194                                 "%d %s %s %s %s %s %s\n",
195                                 ch->ch_portnum,
196                                 (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
197                                 (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
198                                 (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
199                                 (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
200                                 (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
201                                 (ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
202                 } else {
203                         count += snprintf(buf + count, PAGE_SIZE - count,
204                                 "%d\n", ch->ch_portnum);
205                 }
206         }
207         return count;
208 }
209 static DEVICE_ATTR_RO(ports_msignals);
210
211 static ssize_t ports_iflag_show(struct device *p,
212                                 struct device_attribute *attr, char *buf)
213 {
214         struct dgnc_board *bd;
215         int count = 0;
216         int i = 0;
217
218         DGNC_VERIFY_BOARD(p, bd);
219
220         for (i = 0; i < bd->nasync; i++) {
221                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
222                         bd->channels[i]->ch_portnum,
223                         bd->channels[i]->ch_c_iflag);
224         }
225         return count;
226 }
227 static DEVICE_ATTR_RO(ports_iflag);
228
229 static ssize_t ports_cflag_show(struct device *p,
230                                 struct device_attribute *attr, char *buf)
231 {
232         struct dgnc_board *bd;
233         int count = 0;
234         int i = 0;
235
236         DGNC_VERIFY_BOARD(p, bd);
237
238         for (i = 0; i < bd->nasync; i++) {
239                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
240                         bd->channels[i]->ch_portnum,
241                         bd->channels[i]->ch_c_cflag);
242         }
243         return count;
244 }
245 static DEVICE_ATTR_RO(ports_cflag);
246
247 static ssize_t ports_oflag_show(struct device *p,
248                                 struct device_attribute *attr, char *buf)
249 {
250         struct dgnc_board *bd;
251         int count = 0;
252         int i = 0;
253
254         DGNC_VERIFY_BOARD(p, bd);
255
256         for (i = 0; i < bd->nasync; i++) {
257                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
258                         bd->channels[i]->ch_portnum,
259                         bd->channels[i]->ch_c_oflag);
260         }
261         return count;
262 }
263 static DEVICE_ATTR_RO(ports_oflag);
264
265 static ssize_t ports_lflag_show(struct device *p,
266                                 struct device_attribute *attr, char *buf)
267 {
268         struct dgnc_board *bd;
269         int count = 0;
270         int i = 0;
271
272         DGNC_VERIFY_BOARD(p, bd);
273
274         for (i = 0; i < bd->nasync; i++) {
275                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
276                         bd->channels[i]->ch_portnum,
277                         bd->channels[i]->ch_c_lflag);
278         }
279         return count;
280 }
281 static DEVICE_ATTR_RO(ports_lflag);
282
283 static ssize_t ports_digi_flag_show(struct device *p,
284                                     struct device_attribute *attr, char *buf)
285 {
286         struct dgnc_board *bd;
287         int count = 0;
288         int i = 0;
289
290         DGNC_VERIFY_BOARD(p, bd);
291
292         for (i = 0; i < bd->nasync; i++) {
293                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
294                         bd->channels[i]->ch_portnum,
295                         bd->channels[i]->ch_digi.digi_flags);
296         }
297         return count;
298 }
299 static DEVICE_ATTR_RO(ports_digi_flag);
300
301 static ssize_t ports_rxcount_show(struct device *p,
302                                   struct device_attribute *attr, char *buf)
303 {
304         struct dgnc_board *bd;
305         int count = 0;
306         int i = 0;
307
308         DGNC_VERIFY_BOARD(p, bd);
309
310         for (i = 0; i < bd->nasync; i++) {
311                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
312                         bd->channels[i]->ch_portnum,
313                         bd->channels[i]->ch_rxcount);
314         }
315         return count;
316 }
317 static DEVICE_ATTR_RO(ports_rxcount);
318
319 static ssize_t ports_txcount_show(struct device *p,
320                                   struct device_attribute *attr, char *buf)
321 {
322         struct dgnc_board *bd;
323         int count = 0;
324         int i = 0;
325
326         DGNC_VERIFY_BOARD(p, bd);
327
328         for (i = 0; i < bd->nasync; i++) {
329                 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
330                         bd->channels[i]->ch_portnum,
331                         bd->channels[i]->ch_txcount);
332         }
333         return count;
334 }
335 static DEVICE_ATTR_RO(ports_txcount);
336
337 /* this function creates the sys files that will export each signal status
338  * to sysfs each value will be put in a separate filename
339  */
340 void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
341 {
342         int rc = 0;
343
344         dev_set_drvdata(&bd->pdev->dev, bd);
345         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_state);
346         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_baud);
347         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals);
348         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag);
349         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag);
350         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag);
351         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag);
352         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
353         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
354         rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount);
355         rc |= device_create_file(&bd->pdev->dev, &dev_attr_vpd);
356         rc |= device_create_file(&bd->pdev->dev, &dev_attr_serial_number);
357         if (rc)
358                 dev_err(&bd->pdev->dev, "dgnc: sysfs device_create_file failed!\n");
359 }
360
361 /* removes all the sys files created for that port */
362 void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
363 {
364         device_remove_file(&bd->pdev->dev, &dev_attr_ports_state);
365         device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud);
366         device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals);
367         device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag);
368         device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag);
369         device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag);
370         device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag);
371         device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
372         device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
373         device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount);
374         device_remove_file(&bd->pdev->dev, &dev_attr_vpd);
375         device_remove_file(&bd->pdev->dev, &dev_attr_serial_number);
376 }
377
378 static ssize_t tty_state_show(struct device *d,
379                               struct device_attribute *attr, char *buf)
380 {
381         struct dgnc_board *bd;
382         struct channel_t *ch;
383         struct un_t *un;
384
385         if (!d)
386                 return 0;
387         un = dev_get_drvdata(d);
388         if (!un || un->magic != DGNC_UNIT_MAGIC)
389                 return 0;
390         ch = un->un_ch;
391         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
392                 return 0;
393         bd = ch->ch_bd;
394         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
395                 return 0;
396         if (bd->state != BOARD_READY)
397                 return 0;
398
399         return snprintf(buf, PAGE_SIZE, "%s",
400                         un->un_open_count ? "Open" : "Closed");
401 }
402 static DEVICE_ATTR_RO(tty_state);
403
404 static ssize_t tty_baud_show(struct device *d,
405                              struct device_attribute *attr, char *buf)
406 {
407         struct dgnc_board *bd;
408         struct channel_t *ch;
409         struct un_t *un;
410
411         if (!d)
412                 return 0;
413         un = dev_get_drvdata(d);
414         if (!un || un->magic != DGNC_UNIT_MAGIC)
415                 return 0;
416         ch = un->un_ch;
417         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
418                 return 0;
419         bd = ch->ch_bd;
420         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
421                 return 0;
422         if (bd->state != BOARD_READY)
423                 return 0;
424
425         return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
426 }
427 static DEVICE_ATTR_RO(tty_baud);
428
429 static ssize_t tty_msignals_show(struct device *d,
430                                  struct device_attribute *attr, char *buf)
431 {
432         struct dgnc_board *bd;
433         struct channel_t *ch;
434         struct un_t *un;
435
436         if (!d)
437                 return 0;
438         un = dev_get_drvdata(d);
439         if (!un || un->magic != DGNC_UNIT_MAGIC)
440                 return 0;
441         ch = un->un_ch;
442         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
443                 return 0;
444         bd = ch->ch_bd;
445         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
446                 return 0;
447         if (bd->state != BOARD_READY)
448                 return 0;
449
450         if (ch->ch_open_count) {
451                 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
452                         (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
453                         (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
454                         (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
455                         (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
456                         (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
457                         (ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
458         }
459         return 0;
460 }
461 static DEVICE_ATTR_RO(tty_msignals);
462
463 static ssize_t tty_iflag_show(struct device *d,
464                               struct device_attribute *attr, char *buf)
465 {
466         struct dgnc_board *bd;
467         struct channel_t *ch;
468         struct un_t *un;
469
470         if (!d)
471                 return 0;
472         un = dev_get_drvdata(d);
473         if (!un || un->magic != DGNC_UNIT_MAGIC)
474                 return 0;
475         ch = un->un_ch;
476         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
477                 return 0;
478         bd = ch->ch_bd;
479         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
480                 return 0;
481         if (bd->state != BOARD_READY)
482                 return 0;
483
484         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
485 }
486 static DEVICE_ATTR_RO(tty_iflag);
487
488 static ssize_t tty_cflag_show(struct device *d,
489                               struct device_attribute *attr, char *buf)
490 {
491         struct dgnc_board *bd;
492         struct channel_t *ch;
493         struct un_t *un;
494
495         if (!d)
496                 return 0;
497         un = dev_get_drvdata(d);
498         if (!un || un->magic != DGNC_UNIT_MAGIC)
499                 return 0;
500         ch = un->un_ch;
501         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
502                 return 0;
503         bd = ch->ch_bd;
504         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
505                 return 0;
506         if (bd->state != BOARD_READY)
507                 return 0;
508
509         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
510 }
511 static DEVICE_ATTR_RO(tty_cflag);
512
513 static ssize_t tty_oflag_show(struct device *d,
514                               struct device_attribute *attr, char *buf)
515 {
516         struct dgnc_board *bd;
517         struct channel_t *ch;
518         struct un_t *un;
519
520         if (!d)
521                 return 0;
522         un = dev_get_drvdata(d);
523         if (!un || un->magic != DGNC_UNIT_MAGIC)
524                 return 0;
525         ch = un->un_ch;
526         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
527                 return 0;
528         bd = ch->ch_bd;
529         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
530                 return 0;
531         if (bd->state != BOARD_READY)
532                 return 0;
533
534         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
535 }
536 static DEVICE_ATTR_RO(tty_oflag);
537
538 static ssize_t tty_lflag_show(struct device *d,
539                               struct device_attribute *attr, char *buf)
540 {
541         struct dgnc_board *bd;
542         struct channel_t *ch;
543         struct un_t *un;
544
545         if (!d)
546                 return 0;
547         un = dev_get_drvdata(d);
548         if (!un || un->magic != DGNC_UNIT_MAGIC)
549                 return 0;
550         ch = un->un_ch;
551         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
552                 return 0;
553         bd = ch->ch_bd;
554         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
555                 return 0;
556         if (bd->state != BOARD_READY)
557                 return 0;
558
559         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
560 }
561 static DEVICE_ATTR_RO(tty_lflag);
562
563 static ssize_t tty_digi_flag_show(struct device *d,
564                                   struct device_attribute *attr, char *buf)
565 {
566         struct dgnc_board *bd;
567         struct channel_t *ch;
568         struct un_t *un;
569
570         if (!d)
571                 return 0;
572         un = dev_get_drvdata(d);
573         if (!un || un->magic != DGNC_UNIT_MAGIC)
574                 return 0;
575         ch = un->un_ch;
576         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
577                 return 0;
578         bd = ch->ch_bd;
579         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
580                 return 0;
581         if (bd->state != BOARD_READY)
582                 return 0;
583
584         return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
585 }
586 static DEVICE_ATTR_RO(tty_digi_flag);
587
588 static ssize_t tty_rxcount_show(struct device *d,
589                                 struct device_attribute *attr, char *buf)
590 {
591         struct dgnc_board *bd;
592         struct channel_t *ch;
593         struct un_t *un;
594
595         if (!d)
596                 return 0;
597         un = dev_get_drvdata(d);
598         if (!un || un->magic != DGNC_UNIT_MAGIC)
599                 return 0;
600         ch = un->un_ch;
601         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
602                 return 0;
603         bd = ch->ch_bd;
604         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
605                 return 0;
606         if (bd->state != BOARD_READY)
607                 return 0;
608
609         return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
610 }
611 static DEVICE_ATTR_RO(tty_rxcount);
612
613 static ssize_t tty_txcount_show(struct device *d,
614                                 struct device_attribute *attr, char *buf)
615 {
616         struct dgnc_board *bd;
617         struct channel_t *ch;
618         struct un_t *un;
619
620         if (!d)
621                 return 0;
622         un = dev_get_drvdata(d);
623         if (!un || un->magic != DGNC_UNIT_MAGIC)
624                 return 0;
625         ch = un->un_ch;
626         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
627                 return 0;
628         bd = ch->ch_bd;
629         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
630                 return 0;
631         if (bd->state != BOARD_READY)
632                 return 0;
633
634         return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
635 }
636 static DEVICE_ATTR_RO(tty_txcount);
637
638 static ssize_t tty_custom_name_show(struct device *d,
639                                     struct device_attribute *attr, char *buf)
640 {
641         struct dgnc_board *bd;
642         struct channel_t *ch;
643         struct un_t *un;
644
645         if (!d)
646                 return 0;
647         un = dev_get_drvdata(d);
648         if (!un || un->magic != DGNC_UNIT_MAGIC)
649                 return 0;
650         ch = un->un_ch;
651         if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
652                 return 0;
653         bd = ch->ch_bd;
654         if (!bd || bd->magic != DGNC_BOARD_MAGIC)
655                 return 0;
656         if (bd->state != BOARD_READY)
657                 return 0;
658
659         return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
660                 (un->un_type == DGNC_PRINT) ? "pr" : "tty",
661                 bd->boardnum + 1, 'a' + ch->ch_portnum);
662 }
663 static DEVICE_ATTR_RO(tty_custom_name);
664
665 static struct attribute *dgnc_sysfs_tty_entries[] = {
666         &dev_attr_tty_state.attr,
667         &dev_attr_tty_baud.attr,
668         &dev_attr_tty_msignals.attr,
669         &dev_attr_tty_iflag.attr,
670         &dev_attr_tty_cflag.attr,
671         &dev_attr_tty_oflag.attr,
672         &dev_attr_tty_lflag.attr,
673         &dev_attr_tty_digi_flag.attr,
674         &dev_attr_tty_rxcount.attr,
675         &dev_attr_tty_txcount.attr,
676         &dev_attr_tty_custom_name.attr,
677         NULL
678 };
679
680 static struct attribute_group dgnc_tty_attribute_group = {
681         .name = NULL,
682         .attrs = dgnc_sysfs_tty_entries,
683 };
684
685 void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
686 {
687         int ret;
688
689         ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
690         if (ret) {
691                 dev_err(c, "dgnc: failed to create sysfs tty device attributes.\n");
692                 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
693                 return;
694         }
695
696         dev_set_drvdata(c, un);
697 }
698
699 void dgnc_remove_tty_sysfs(struct device *c)
700 {
701         sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
702 }
703