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