dgnc_sysfs.c 18 KB

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