Merge tag 'pinctrl-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / dgrp / dgrp_sysfs.c
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
107 void dgrp_create_class_sysfs_files(void)
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
134 void dgrp_remove_class_sysfs_files(void)
135 {
136 struct nd_struct *nd;
137 int max_majors = 1U << (32 - MINORBITS);
138
139 list_for_each_entry(nd, &nd_struct_list, list)
140 dgrp_remove_node_class_sysfs_files(nd);
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
264 void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
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
293 void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
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
552 void dgrp_remove_tty_sysfs(struct device *c)
553 {
554 sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
555 }