Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dgrp_sysfs.c
Go to the documentation of this file.
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 "dgrp_common.h"
18 
19 #include <linux/kernel.h>
20 #include <linux/version.h>
21 #include <linux/module.h>
22 #include <linux/ctype.h>
23 #include <linux/string.h>
24 #include <linux/serial_reg.h>
25 #include <linux/pci.h>
26 #include <linux/kdev_t.h>
27 
28 
29 #define PORTSERVER_DIVIDEND 1843200
30 #define SERIAL_TYPE_NORMAL 1
31 #define SERIAL_TYPE_CALLOUT 2
32 #define SERIAL_TYPE_XPRINT 3
33 
34 
35 static struct class *dgrp_class;
36 static struct device *dgrp_class_nodes_dev;
37 static struct device *dgrp_class_global_settings_dev;
38 
39 
40 static ssize_t dgrp_class_version_show(struct class *class,
41  struct class_attribute *attr, char *buf)
42 {
43  return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION);
44 }
45 static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL);
46 
47 
48 static ssize_t dgrp_class_register_with_sysfs_show(struct device *c,
49  struct device_attribute *attr,
50  char *buf)
51 {
52  return snprintf(buf, PAGE_SIZE, "1\n");
53 }
54 static DEVICE_ATTR(register_with_sysfs, 0400,
55  dgrp_class_register_with_sysfs_show, NULL);
56 
57 
58 static ssize_t dgrp_class_rawreadok_show(struct device *c,
59  struct device_attribute *attr,
60  char *buf)
61 {
62  return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok);
63 }
64 static ssize_t dgrp_class_rawreadok_store(struct device *c,
65  struct device_attribute *attr,
66  const char *buf, size_t count)
67 {
68  sscanf(buf, "0x%x\n", &dgrp_rawreadok);
69  return count;
70 }
71 static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show,
72  dgrp_class_rawreadok_store);
73 
74 
75 static ssize_t dgrp_class_pollrate_show(struct device *c,
76  struct device_attribute *attr,
77  char *buf)
78 {
79  return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick);
80 }
81 
82 static ssize_t dgrp_class_pollrate_store(struct device *c,
83  struct device_attribute *attr,
84  const char *buf, size_t count)
85 {
86  sscanf(buf, "0x%x\n", &dgrp_poll_tick);
87  return count;
88 }
89 static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
90  dgrp_class_pollrate_store);
91 
92 static struct attribute *dgrp_sysfs_global_settings_entries[] = {
93  &dev_attr_pollrate.attr,
94  &dev_attr_rawreadok.attr,
95  &dev_attr_register_with_sysfs.attr,
96  NULL
97 };
98 
99 
100 static struct attribute_group dgrp_global_settings_attribute_group = {
101  .name = NULL,
102  .attrs = dgrp_sysfs_global_settings_entries,
103 };
104 
105 
106 
108 {
109  int ret = 0;
110  int max_majors = 1U << (32 - MINORBITS);
111 
112  dgrp_class = class_create(THIS_MODULE, "digi_realport");
113  ret = class_create_file(dgrp_class, &class_attr_driver_version);
114 
115  dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
116  MKDEV(0, max_majors + 1), NULL, "driver_settings");
117 
118  ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
119  &dgrp_global_settings_attribute_group);
120  if (ret) {
121  pr_alert("%s: failed to create sysfs global settings device attributes.\n",
122  __func__);
123  sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
124  &dgrp_global_settings_attribute_group);
125  return;
126  }
127 
128  dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
129  MKDEV(0, max_majors + 2), NULL, "nodes");
130 
131 }
132 
133 
135 {
136  struct nd_struct *nd;
137  int max_majors = 1U << (32 - MINORBITS);
138 
141 
142  sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
143  &dgrp_global_settings_attribute_group);
144 
145  class_remove_file(dgrp_class, &class_attr_driver_version);
146 
147  device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
148  device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
149  class_destroy(dgrp_class);
150 }
151 
152 static ssize_t dgrp_node_state_show(struct device *c,
153  struct device_attribute *attr, char *buf)
154 {
155  struct nd_struct *nd;
156 
157  if (!c)
158  return 0;
159  nd = (struct nd_struct *) dev_get_drvdata(c);
160  if (!nd)
161  return 0;
162 
163  return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
164 }
165 
166 static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
167 
168 static ssize_t dgrp_node_description_show(struct device *c,
169  struct device_attribute *attr,
170  char *buf)
171 {
172  struct nd_struct *nd;
173 
174  if (!c)
175  return 0;
176  nd = (struct nd_struct *) dev_get_drvdata(c);
177  if (!nd)
178  return 0;
179 
180  if (nd->nd_state == NS_READY && nd->nd_ps_desc)
181  return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
182  return 0;
183 }
184 static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
185 
186 static ssize_t dgrp_node_hw_version_show(struct device *c,
187  struct device_attribute *attr,
188  char *buf)
189 {
190  struct nd_struct *nd;
191 
192  if (!c)
193  return 0;
194  nd = (struct nd_struct *) dev_get_drvdata(c);
195  if (!nd)
196  return 0;
197 
198  if (nd->nd_state == NS_READY)
199  return snprintf(buf, PAGE_SIZE, "%d.%d\n",
200  (nd->nd_hw_ver >> 8) & 0xff,
201  nd->nd_hw_ver & 0xff);
202 
203  return 0;
204 }
205 static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
206 
207 static ssize_t dgrp_node_hw_id_show(struct device *c,
208  struct device_attribute *attr, char *buf)
209 {
210  struct nd_struct *nd;
211 
212  if (!c)
213  return 0;
214  nd = (struct nd_struct *) dev_get_drvdata(c);
215  if (!nd)
216  return 0;
217 
218 
219  if (nd->nd_state == NS_READY)
220  return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
221  return 0;
222 }
223 static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
224 
225 static ssize_t dgrp_node_sw_version_show(struct device *c,
226  struct device_attribute *attr,
227  char *buf)
228 {
229  struct nd_struct *nd;
230 
231  if (!c)
232  return 0;
233 
234  nd = (struct nd_struct *) dev_get_drvdata(c);
235  if (!nd)
236  return 0;
237 
238  if (nd->nd_state == NS_READY)
239  return snprintf(buf, PAGE_SIZE, "%d.%d\n",
240  (nd->nd_sw_ver >> 8) & 0xff,
241  nd->nd_sw_ver & 0xff);
242 
243  return 0;
244 }
245 static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
246 
247 
248 static struct attribute *dgrp_sysfs_node_entries[] = {
249  &dev_attr_state.attr,
250  &dev_attr_description_info.attr,
251  &dev_attr_hw_version_info.attr,
252  &dev_attr_hw_id_info.attr,
253  &dev_attr_sw_version_info.attr,
254  NULL
255 };
256 
257 
258 static struct attribute_group dgrp_node_attribute_group = {
259  .name = NULL,
260  .attrs = dgrp_sysfs_node_entries,
261 };
262 
263 
265 {
266  int ret;
267  char name[10];
268 
269  if (nd->nd_ID)
270  ID_TO_CHAR(nd->nd_ID, name);
271  else
272  sprintf(name, "node%ld", nd->nd_major);
273 
274  nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
275  MKDEV(0, nd->nd_major), NULL, name);
276 
277  ret = sysfs_create_group(&nd->nd_class_dev->kobj,
278  &dgrp_node_attribute_group);
279 
280  if (ret) {
281  pr_alert("%s: failed to create sysfs node device attributes.\n",
282  __func__);
283  sysfs_remove_group(&nd->nd_class_dev->kobj,
284  &dgrp_node_attribute_group);
285  return;
286  }
287 
288  dev_set_drvdata(nd->nd_class_dev, nd);
289 
290 }
291 
292 
294 {
295  if (nd->nd_class_dev) {
296  sysfs_remove_group(&nd->nd_class_dev->kobj,
297  &dgrp_node_attribute_group);
298 
299  device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
300  nd->nd_class_dev = NULL;
301  }
302 }
303 
304 
305 
306 static ssize_t dgrp_tty_state_show(struct device *d,
307  struct device_attribute *attr, char *buf)
308 {
309  struct un_struct *un;
310 
311  if (!d)
312  return 0;
313  un = (struct un_struct *) dev_get_drvdata(d);
314  if (!un)
315  return 0;
316 
317  return snprintf(buf, PAGE_SIZE, "%s\n",
318  un->un_open_count ? "Open" : "Closed");
319 }
320 static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
321 
322 static ssize_t dgrp_tty_baud_show(struct device *d,
323  struct device_attribute *attr, char *buf)
324 {
325  struct ch_struct *ch;
326  struct un_struct *un;
327 
328  if (!d)
329  return 0;
330  un = (struct un_struct *) dev_get_drvdata(d);
331  if (!un)
332  return 0;
333  ch = un->un_ch;
334  if (!ch)
335  return 0;
336  return snprintf(buf, PAGE_SIZE, "%d\n",
337  un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
338 }
339 static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
340 
341 
342 static ssize_t dgrp_tty_msignals_show(struct device *d,
343  struct device_attribute *attr, char *buf)
344 {
345  struct ch_struct *ch;
346  struct un_struct *un;
347 
348  if (!d)
349  return 0;
350  un = (struct un_struct *) dev_get_drvdata(d);
351  if (!un)
352  return 0;
353  ch = un->un_ch;
354  if (!ch)
355  return 0;
356 
357  if (ch->ch_open_count) {
358  return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
359  (ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
360  (ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
361  (ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
362  (ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
363  (ch->ch_s_mlast & DM_CD) ? "DCD" : "",
364  (ch->ch_s_mlast & DM_RI) ? "RI" : "");
365  }
366  return 0;
367 }
368 static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
369 
370 
371 static ssize_t dgrp_tty_iflag_show(struct device *d,
372  struct device_attribute *attr, char *buf)
373 {
374  struct ch_struct *ch;
375  struct un_struct *un;
376 
377  if (!d)
378  return 0;
379  un = (struct un_struct *) dev_get_drvdata(d);
380  if (!un)
381  return 0;
382  ch = un->un_ch;
383  if (!ch)
384  return 0;
385  return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
386 }
387 static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
388 
389 
390 static ssize_t dgrp_tty_cflag_show(struct device *d,
391  struct device_attribute *attr, char *buf)
392 {
393  struct ch_struct *ch;
394  struct un_struct *un;
395 
396  if (!d)
397  return 0;
398  un = (struct un_struct *) dev_get_drvdata(d);
399  if (!un)
400  return 0;
401  ch = un->un_ch;
402  if (!ch)
403  return 0;
404  return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
405 }
406 static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
407 
408 
409 static ssize_t dgrp_tty_oflag_show(struct device *d,
410  struct device_attribute *attr, char *buf)
411 {
412  struct ch_struct *ch;
413  struct un_struct *un;
414 
415  if (!d)
416  return 0;
417  un = (struct un_struct *) dev_get_drvdata(d);
418  if (!un)
419  return 0;
420  ch = un->un_ch;
421  if (!ch)
422  return 0;
423  return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
424 }
425 static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
426 
427 
428 static ssize_t dgrp_tty_digi_flag_show(struct device *d,
429  struct device_attribute *attr, char *buf)
430 {
431  struct ch_struct *ch;
432  struct un_struct *un;
433 
434  if (!d)
435  return 0;
436  un = (struct un_struct *) dev_get_drvdata(d);
437  if (!un)
438  return 0;
439  ch = un->un_ch;
440  if (!ch)
441  return 0;
442  return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
443 }
444 static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
445 
446 
447 static ssize_t dgrp_tty_rxcount_show(struct device *d,
448  struct device_attribute *attr, char *buf)
449 {
450  struct ch_struct *ch;
451  struct un_struct *un;
452 
453  if (!d)
454  return 0;
455  un = (struct un_struct *) dev_get_drvdata(d);
456  if (!un)
457  return 0;
458  ch = un->un_ch;
459  if (!ch)
460  return 0;
461  return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
462 }
463 static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
464 
465 
466 static ssize_t dgrp_tty_txcount_show(struct device *d,
467  struct device_attribute *attr, char *buf)
468 {
469  struct ch_struct *ch;
470  struct un_struct *un;
471 
472  if (!d)
473  return 0;
474  un = (struct un_struct *) dev_get_drvdata(d);
475  if (!un)
476  return 0;
477  ch = un->un_ch;
478  if (!ch)
479  return 0;
480  return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
481 }
482 static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
483 
484 
485 static ssize_t dgrp_tty_name_show(struct device *d,
486  struct device_attribute *attr, char *buf)
487 {
488  struct nd_struct *nd;
489  struct ch_struct *ch;
490  struct un_struct *un;
491  char name[10];
492 
493  if (!d)
494  return 0;
495  un = (struct un_struct *) dev_get_drvdata(d);
496  if (!un)
497  return 0;
498  ch = un->un_ch;
499  if (!ch)
500  return 0;
501  nd = ch->ch_nd;
502  if (!nd)
503  return 0;
504 
505  ID_TO_CHAR(nd->nd_ID, name);
506 
507  return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
508  un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
509  name, ch->ch_portnum);
510 }
511 static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
512 
513 
514 static struct attribute *dgrp_sysfs_tty_entries[] = {
515  &dev_attr_state_info.attr,
516  &dev_attr_baud_info.attr,
517  &dev_attr_msignals_info.attr,
518  &dev_attr_iflag_info.attr,
519  &dev_attr_cflag_info.attr,
520  &dev_attr_oflag_info.attr,
521  &dev_attr_digi_flag_info.attr,
522  &dev_attr_rxcount_info.attr,
523  &dev_attr_txcount_info.attr,
524  &dev_attr_custom_name.attr,
525  NULL
526 };
527 
528 
529 static struct attribute_group dgrp_tty_attribute_group = {
530  .name = NULL,
531  .attrs = dgrp_sysfs_tty_entries,
532 };
533 
534 
535 void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
536 {
537  int ret;
538 
539  ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
540  if (ret) {
541  pr_alert("%s: failed to create sysfs tty device attributes.\n",
542  __func__);
543  sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
544  return;
545  }
546 
547  dev_set_drvdata(c, un);
548 
549 }
550 
551 
553 {
554  sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
555 }