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