2 * Copyright 2004 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
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)
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.
17 #include "dgrp_common.h"
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/ctype.h>
22 #include <linux/string.h>
23 #include <linux/serial_reg.h>
24 #include <linux/pci.h>
25 #include <linux/kdev_t.h>
28 #define PORTSERVER_DIVIDEND 1843200
29 #define SERIAL_TYPE_NORMAL 1
30 #define SERIAL_TYPE_CALLOUT 2
31 #define SERIAL_TYPE_XPRINT 3
34 static struct class *dgrp_class;
35 static struct device *dgrp_class_nodes_dev;
36 static struct device *dgrp_class_global_settings_dev;
39 static ssize_t dgrp_class_version_show(struct class *class,
40 struct class_attribute *attr, char *buf)
42 return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION);
44 static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL);
47 static ssize_t dgrp_class_register_with_sysfs_show(struct device *c,
48 struct device_attribute *attr,
51 return snprintf(buf, PAGE_SIZE, "1\n");
53 static DEVICE_ATTR(register_with_sysfs, 0400,
54 dgrp_class_register_with_sysfs_show, NULL);
57 static ssize_t dgrp_class_pollrate_show(struct device *c,
58 struct device_attribute *attr,
61 return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick);
64 static ssize_t dgrp_class_pollrate_store(struct device *c,
65 struct device_attribute *attr,
66 const char *buf, size_t count)
68 sscanf(buf, "0x%x\n", &dgrp_poll_tick);
71 static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
72 dgrp_class_pollrate_store);
74 static struct attribute *dgrp_sysfs_global_settings_entries[] = {
75 &dev_attr_pollrate.attr,
76 &dev_attr_register_with_sysfs.attr,
81 static struct attribute_group dgrp_global_settings_attribute_group = {
83 .attrs = dgrp_sysfs_global_settings_entries,
88 int dgrp_create_class_sysfs_files(void)
91 int max_majors = 1U << (32 - MINORBITS);
93 dgrp_class = class_create(THIS_MODULE, "digi_realport");
94 if (IS_ERR(dgrp_class))
95 return PTR_ERR(dgrp_class);
96 ret = class_create_file(dgrp_class, &class_attr_driver_version);
100 dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
101 MKDEV(0, max_majors + 1), NULL, "driver_settings");
102 if (IS_ERR(dgrp_class_global_settings_dev)) {
103 ret = PTR_ERR(dgrp_class_global_settings_dev);
106 ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
107 &dgrp_global_settings_attribute_group);
109 pr_alert("%s: failed to create sysfs global settings device attributes.\n",
114 dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
115 MKDEV(0, max_majors + 2), NULL, "nodes");
116 if (IS_ERR(dgrp_class_nodes_dev)) {
117 ret = PTR_ERR(dgrp_class_nodes_dev);
123 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
124 &dgrp_global_settings_attribute_group);
126 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
128 class_remove_file(dgrp_class, &class_attr_driver_version);
130 class_destroy(dgrp_class);
135 void dgrp_remove_class_sysfs_files(void)
137 struct nd_struct *nd;
138 int max_majors = 1U << (32 - MINORBITS);
140 list_for_each_entry(nd, &nd_struct_list, list)
141 dgrp_remove_node_class_sysfs_files(nd);
143 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
144 &dgrp_global_settings_attribute_group);
146 class_remove_file(dgrp_class, &class_attr_driver_version);
148 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
149 device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
150 class_destroy(dgrp_class);
153 static ssize_t dgrp_node_state_show(struct device *c,
154 struct device_attribute *attr, char *buf)
156 struct nd_struct *nd;
160 nd = (struct nd_struct *) dev_get_drvdata(c);
164 return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
167 static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
169 static ssize_t dgrp_node_description_show(struct device *c,
170 struct device_attribute *attr,
173 struct nd_struct *nd;
177 nd = (struct nd_struct *) dev_get_drvdata(c);
181 if (nd->nd_state == NS_READY)
182 return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
185 static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
187 static ssize_t dgrp_node_hw_version_show(struct device *c,
188 struct device_attribute *attr,
191 struct nd_struct *nd;
195 nd = (struct nd_struct *) dev_get_drvdata(c);
199 if (nd->nd_state == NS_READY)
200 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
201 (nd->nd_hw_ver >> 8) & 0xff,
202 nd->nd_hw_ver & 0xff);
206 static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
208 static ssize_t dgrp_node_hw_id_show(struct device *c,
209 struct device_attribute *attr, char *buf)
211 struct nd_struct *nd;
215 nd = (struct nd_struct *) dev_get_drvdata(c);
220 if (nd->nd_state == NS_READY)
221 return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
224 static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
226 static ssize_t dgrp_node_sw_version_show(struct device *c,
227 struct device_attribute *attr,
230 struct nd_struct *nd;
235 nd = (struct nd_struct *) dev_get_drvdata(c);
239 if (nd->nd_state == NS_READY)
240 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
241 (nd->nd_sw_ver >> 8) & 0xff,
242 nd->nd_sw_ver & 0xff);
246 static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
249 static struct attribute *dgrp_sysfs_node_entries[] = {
250 &dev_attr_state.attr,
251 &dev_attr_description_info.attr,
252 &dev_attr_hw_version_info.attr,
253 &dev_attr_hw_id_info.attr,
254 &dev_attr_sw_version_info.attr,
259 static struct attribute_group dgrp_node_attribute_group = {
261 .attrs = dgrp_sysfs_node_entries,
265 void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
271 ID_TO_CHAR(nd->nd_ID, name);
273 sprintf(name, "node%ld", nd->nd_major);
275 nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
276 MKDEV(0, nd->nd_major), NULL, name);
278 ret = sysfs_create_group(&nd->nd_class_dev->kobj,
279 &dgrp_node_attribute_group);
282 pr_alert("%s: failed to create sysfs node device attributes.\n",
284 sysfs_remove_group(&nd->nd_class_dev->kobj,
285 &dgrp_node_attribute_group);
289 dev_set_drvdata(nd->nd_class_dev, nd);
294 void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
296 if (nd->nd_class_dev) {
297 sysfs_remove_group(&nd->nd_class_dev->kobj,
298 &dgrp_node_attribute_group);
300 device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
301 nd->nd_class_dev = NULL;
307 static ssize_t dgrp_tty_state_show(struct device *d,
308 struct device_attribute *attr, char *buf)
310 struct un_struct *un;
314 un = (struct un_struct *) dev_get_drvdata(d);
318 return snprintf(buf, PAGE_SIZE, "%s\n",
319 un->un_open_count ? "Open" : "Closed");
321 static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
323 static ssize_t dgrp_tty_baud_show(struct device *d,
324 struct device_attribute *attr, char *buf)
326 struct ch_struct *ch;
327 struct un_struct *un;
331 un = (struct un_struct *) dev_get_drvdata(d);
337 return snprintf(buf, PAGE_SIZE, "%d\n",
338 un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
340 static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
343 static ssize_t dgrp_tty_msignals_show(struct device *d,
344 struct device_attribute *attr, char *buf)
346 struct ch_struct *ch;
347 struct un_struct *un;
351 un = (struct un_struct *) dev_get_drvdata(d);
358 if (ch->ch_open_count) {
359 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
360 (ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
361 (ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
362 (ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
363 (ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
364 (ch->ch_s_mlast & DM_CD) ? "DCD" : "",
365 (ch->ch_s_mlast & DM_RI) ? "RI" : "");
369 static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
372 static ssize_t dgrp_tty_iflag_show(struct device *d,
373 struct device_attribute *attr, char *buf)
375 struct ch_struct *ch;
376 struct un_struct *un;
380 un = (struct un_struct *) dev_get_drvdata(d);
386 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
388 static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
391 static ssize_t dgrp_tty_cflag_show(struct device *d,
392 struct device_attribute *attr, char *buf)
394 struct ch_struct *ch;
395 struct un_struct *un;
399 un = (struct un_struct *) dev_get_drvdata(d);
405 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
407 static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
410 static ssize_t dgrp_tty_oflag_show(struct device *d,
411 struct device_attribute *attr, char *buf)
413 struct ch_struct *ch;
414 struct un_struct *un;
418 un = (struct un_struct *) dev_get_drvdata(d);
424 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
426 static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
429 static ssize_t dgrp_tty_digi_flag_show(struct device *d,
430 struct device_attribute *attr, char *buf)
432 struct ch_struct *ch;
433 struct un_struct *un;
437 un = (struct un_struct *) dev_get_drvdata(d);
443 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
445 static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
448 static ssize_t dgrp_tty_rxcount_show(struct device *d,
449 struct device_attribute *attr, char *buf)
451 struct ch_struct *ch;
452 struct un_struct *un;
456 un = (struct un_struct *) dev_get_drvdata(d);
462 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
464 static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
467 static ssize_t dgrp_tty_txcount_show(struct device *d,
468 struct device_attribute *attr, char *buf)
470 struct ch_struct *ch;
471 struct un_struct *un;
475 un = (struct un_struct *) dev_get_drvdata(d);
481 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
483 static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
486 static ssize_t dgrp_tty_name_show(struct device *d,
487 struct device_attribute *attr, char *buf)
489 struct nd_struct *nd;
490 struct ch_struct *ch;
491 struct un_struct *un;
496 un = (struct un_struct *) dev_get_drvdata(d);
506 ID_TO_CHAR(nd->nd_ID, name);
508 return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
509 un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
510 name, ch->ch_portnum);
512 static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
515 static struct attribute *dgrp_sysfs_tty_entries[] = {
516 &dev_attr_state_info.attr,
517 &dev_attr_baud_info.attr,
518 &dev_attr_msignals_info.attr,
519 &dev_attr_iflag_info.attr,
520 &dev_attr_cflag_info.attr,
521 &dev_attr_oflag_info.attr,
522 &dev_attr_digi_flag_info.attr,
523 &dev_attr_rxcount_info.attr,
524 &dev_attr_txcount_info.attr,
525 &dev_attr_custom_name.attr,
530 static struct attribute_group dgrp_tty_attribute_group = {
532 .attrs = dgrp_sysfs_tty_entries,
536 void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
540 ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
542 pr_alert("%s: failed to create sysfs tty device attributes.\n",
544 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
548 dev_set_drvdata(c, un);
553 void dgrp_remove_tty_sysfs(struct device *c)
555 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);