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 30static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf) 31{ 32 return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); 33} 34static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); 35 36 37static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) 38{ 39 return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards); 40} 41static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); 42 43 44static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf) 45{ 46 return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); 47} 48static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL); 49 50 51static 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 56static 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} 65static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store); 66 67 68void 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 82void 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 107static 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} 125static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL); 126 127static 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} 141static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL); 142 143 144static 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} 159static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL); 160 161 162static 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} 176static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL); 177 178 179static 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} 204static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL); 205 206 207static 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} 221static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL); 222 223 224static 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} 238static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL); 239 240 241static 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} 255static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL); 256 257 258static 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} 272static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL); 273 274 275static 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} 289static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL); 290 291 292static 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} 306static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL); 307 308 309static 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} 323static 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 */ 329void 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 */ 352void 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 369static 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} 391static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL); 392 393 394static 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} 416static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL); 417 418 419static 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} 450static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL); 451 452 453static 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} 475static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL); 476 477 478static 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} 500static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL); 501 502 503static 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} 525static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL); 526 527 528static 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} 550static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL); 551 552 553static 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} 575static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL); 576 577 578static 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} 600static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL); 601 602 603static 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} 625static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL); 626 627 628static 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} 652static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL); 653 654 655static 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 671static struct attribute_group dgnc_tty_attribute_group = { 672 .name = NULL, 673 .attrs = dgnc_sysfs_tty_entries, 674}; 675 676 677void 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 693void dgnc_remove_tty_sysfs(struct device *c) 694{ 695 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); 696} 697 698