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 if (sscanf(buf, "0x%x\n", &dgrp_poll_tick) != 1)
73 static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
74 dgrp_class_pollrate_store);
76 static struct attribute *dgrp_sysfs_global_settings_entries[] = {
77 &dev_attr_pollrate.attr,
78 &dev_attr_register_with_sysfs.attr,
83 static struct attribute_group dgrp_global_settings_attribute_group = {
85 .attrs = dgrp_sysfs_global_settings_entries,
90 int dgrp_create_class_sysfs_files(void)
93 int max_majors = 1U << (32 - MINORBITS);
95 dgrp_class = class_create(THIS_MODULE, "digi_realport");
96 if (IS_ERR(dgrp_class))
97 return PTR_ERR(dgrp_class);
98 ret = class_create_file(dgrp_class, &class_attr_driver_version);
102 dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
103 MKDEV(0, max_majors + 1), NULL, "driver_settings");
104 if (IS_ERR(dgrp_class_global_settings_dev)) {
105 ret = PTR_ERR(dgrp_class_global_settings_dev);
108 ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
109 &dgrp_global_settings_attribute_group);
111 pr_alert("%s: failed to create sysfs global settings device attributes.\n",
116 dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
117 MKDEV(0, max_majors + 2), NULL, "nodes");
118 if (IS_ERR(dgrp_class_nodes_dev)) {
119 ret = PTR_ERR(dgrp_class_nodes_dev);
125 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
126 &dgrp_global_settings_attribute_group);
128 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
130 class_remove_file(dgrp_class, &class_attr_driver_version);
132 class_destroy(dgrp_class);
137 void dgrp_remove_class_sysfs_files(void)
139 struct nd_struct *nd;
140 int max_majors = 1U << (32 - MINORBITS);
142 list_for_each_entry(nd, &nd_struct_list, list)
143 dgrp_remove_node_class_sysfs_files(nd);
145 sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
146 &dgrp_global_settings_attribute_group);
148 class_remove_file(dgrp_class, &class_attr_driver_version);
150 device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
151 device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
152 class_destroy(dgrp_class);
155 static ssize_t dgrp_node_state_show(struct device *c,
156 struct device_attribute *attr, char *buf)
158 struct nd_struct *nd;
162 nd = dev_get_drvdata(c);
166 return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
169 static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
171 static ssize_t dgrp_node_description_show(struct device *c,
172 struct device_attribute *attr,
175 struct nd_struct *nd;
179 nd = dev_get_drvdata(c);
183 if (nd->nd_state == NS_READY)
184 return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
187 static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
189 static ssize_t dgrp_node_hw_version_show(struct device *c,
190 struct device_attribute *attr,
193 struct nd_struct *nd;
197 nd = dev_get_drvdata(c);
201 if (nd->nd_state == NS_READY)
202 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
203 (nd->nd_hw_ver >> 8) & 0xff,
204 nd->nd_hw_ver & 0xff);
208 static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
210 static ssize_t dgrp_node_hw_id_show(struct device *c,
211 struct device_attribute *attr, char *buf)
213 struct nd_struct *nd;
217 nd = dev_get_drvdata(c);
222 if (nd->nd_state == NS_READY)
223 return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
226 static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
228 static ssize_t dgrp_node_sw_version_show(struct device *c,
229 struct device_attribute *attr,
232 struct nd_struct *nd;
237 nd = dev_get_drvdata(c);
241 if (nd->nd_state == NS_READY)
242 return snprintf(buf, PAGE_SIZE, "%d.%d\n",
243 (nd->nd_sw_ver >> 8) & 0xff,
244 nd->nd_sw_ver & 0xff);
248 static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
251 static struct attribute *dgrp_sysfs_node_entries[] = {
252 &dev_attr_state.attr,
253 &dev_attr_description_info.attr,
254 &dev_attr_hw_version_info.attr,
255 &dev_attr_hw_id_info.attr,
256 &dev_attr_sw_version_info.attr,
261 static struct attribute_group dgrp_node_attribute_group = {
263 .attrs = dgrp_sysfs_node_entries,
267 void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
273 ID_TO_CHAR(nd->nd_ID, name);
275 sprintf(name, "node%ld", nd->nd_major);
277 nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
278 MKDEV(0, nd->nd_major), NULL, "%s", name);
280 ret = sysfs_create_group(&nd->nd_class_dev->kobj,
281 &dgrp_node_attribute_group);
284 pr_alert("%s: failed to create sysfs node device attributes.\n",
286 sysfs_remove_group(&nd->nd_class_dev->kobj,
287 &dgrp_node_attribute_group);
291 dev_set_drvdata(nd->nd_class_dev, nd);
296 void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
298 if (nd->nd_class_dev) {
299 sysfs_remove_group(&nd->nd_class_dev->kobj,
300 &dgrp_node_attribute_group);
302 device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
303 nd->nd_class_dev = NULL;
309 static ssize_t dgrp_tty_state_show(struct device *d,
310 struct device_attribute *attr, char *buf)
312 struct un_struct *un;
316 un = dev_get_drvdata(d);
320 return snprintf(buf, PAGE_SIZE, "%s\n",
321 un->un_open_count ? "Open" : "Closed");
323 static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
325 static ssize_t dgrp_tty_baud_show(struct device *d,
326 struct device_attribute *attr, char *buf)
328 struct ch_struct *ch;
329 struct un_struct *un;
333 un = dev_get_drvdata(d);
339 return snprintf(buf, PAGE_SIZE, "%d\n",
340 un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
342 static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
345 static ssize_t dgrp_tty_msignals_show(struct device *d,
346 struct device_attribute *attr, char *buf)
348 struct ch_struct *ch;
349 struct un_struct *un;
353 un = dev_get_drvdata(d);
360 if (ch->ch_open_count) {
361 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
362 (ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
363 (ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
364 (ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
365 (ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
366 (ch->ch_s_mlast & DM_CD) ? "DCD" : "",
367 (ch->ch_s_mlast & DM_RI) ? "RI" : "");
371 static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
374 static ssize_t dgrp_tty_iflag_show(struct device *d,
375 struct device_attribute *attr, char *buf)
377 struct ch_struct *ch;
378 struct un_struct *un;
382 un = dev_get_drvdata(d);
388 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
390 static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
393 static ssize_t dgrp_tty_cflag_show(struct device *d,
394 struct device_attribute *attr, char *buf)
396 struct ch_struct *ch;
397 struct un_struct *un;
401 un = dev_get_drvdata(d);
407 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
409 static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
412 static ssize_t dgrp_tty_oflag_show(struct device *d,
413 struct device_attribute *attr, char *buf)
415 struct ch_struct *ch;
416 struct un_struct *un;
420 un = dev_get_drvdata(d);
426 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
428 static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
431 static ssize_t dgrp_tty_digi_flag_show(struct device *d,
432 struct device_attribute *attr, char *buf)
434 struct ch_struct *ch;
435 struct un_struct *un;
439 un = dev_get_drvdata(d);
445 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
447 static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
450 static ssize_t dgrp_tty_rxcount_show(struct device *d,
451 struct device_attribute *attr, char *buf)
453 struct ch_struct *ch;
454 struct un_struct *un;
458 un = dev_get_drvdata(d);
464 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
466 static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
469 static ssize_t dgrp_tty_txcount_show(struct device *d,
470 struct device_attribute *attr, char *buf)
472 struct ch_struct *ch;
473 struct un_struct *un;
477 un = dev_get_drvdata(d);
483 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
485 static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
488 static ssize_t dgrp_tty_name_show(struct device *d,
489 struct device_attribute *attr, char *buf)
491 struct nd_struct *nd;
492 struct ch_struct *ch;
493 struct un_struct *un;
498 un = dev_get_drvdata(d);
508 ID_TO_CHAR(nd->nd_ID, name);
510 return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
511 un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
512 name, ch->ch_portnum);
514 static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
517 static struct attribute *dgrp_sysfs_tty_entries[] = {
518 &dev_attr_state_info.attr,
519 &dev_attr_baud_info.attr,
520 &dev_attr_msignals_info.attr,
521 &dev_attr_iflag_info.attr,
522 &dev_attr_cflag_info.attr,
523 &dev_attr_oflag_info.attr,
524 &dev_attr_digi_flag_info.attr,
525 &dev_attr_rxcount_info.attr,
526 &dev_attr_txcount_info.attr,
527 &dev_attr_custom_name.attr,
532 static struct attribute_group dgrp_tty_attribute_group = {
534 .attrs = dgrp_sysfs_tty_entries,
538 void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
542 ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
544 pr_alert("%s: failed to create sysfs tty device attributes.\n",
546 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
550 dev_set_drvdata(c, un);
555 void dgrp_remove_tty_sysfs(struct device *c)
557 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);