aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/irda/ircomm/ircomm_tty.c256
1 files changed, 138 insertions, 118 deletions
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 086d5ef098fd..811984d9324b 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -34,6 +34,7 @@
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/fs.h> 35#include <linux/fs.h>
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/seq_file.h>
37#include <linux/termios.h> 38#include <linux/termios.h>
38#include <linux/tty.h> 39#include <linux/tty.h>
39#include <linux/interrupt.h> 40#include <linux/interrupt.h>
@@ -72,8 +73,7 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
72static void ircomm_tty_flow_indication(void *instance, void *sap, 73static void ircomm_tty_flow_indication(void *instance, void *sap,
73 LOCAL_FLOW cmd); 74 LOCAL_FLOW cmd);
74#ifdef CONFIG_PROC_FS 75#ifdef CONFIG_PROC_FS
75static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, 76static const struct file_operations ircomm_tty_proc_fops;
76 int *eof, void *unused);
77#endif /* CONFIG_PROC_FS */ 77#endif /* CONFIG_PROC_FS */
78static struct tty_driver *driver; 78static struct tty_driver *driver;
79 79
@@ -98,7 +98,7 @@ static const struct tty_operations ops = {
98 .hangup = ircomm_tty_hangup, 98 .hangup = ircomm_tty_hangup,
99 .wait_until_sent = ircomm_tty_wait_until_sent, 99 .wait_until_sent = ircomm_tty_wait_until_sent,
100#ifdef CONFIG_PROC_FS 100#ifdef CONFIG_PROC_FS
101 .read_proc = ircomm_tty_read_proc, 101 .proc_fops = &ircomm_tty_proc_fops,
102#endif /* CONFIG_PROC_FS */ 102#endif /* CONFIG_PROC_FS */
103}; 103};
104 104
@@ -1245,150 +1245,170 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
1245} 1245}
1246 1246
1247#ifdef CONFIG_PROC_FS 1247#ifdef CONFIG_PROC_FS
1248static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) 1248static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
1249{ 1249{
1250 int ret=0; 1250 char sep;
1251 1251
1252 ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]); 1252 seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]);
1253 1253
1254 ret += sprintf(buf+ret, "Service type: "); 1254 seq_puts(m, "Service type: ");
1255 if (self->service_type & IRCOMM_9_WIRE) 1255 if (self->service_type & IRCOMM_9_WIRE)
1256 ret += sprintf(buf+ret, "9_WIRE"); 1256 seq_puts(m, "9_WIRE");
1257 else if (self->service_type & IRCOMM_3_WIRE) 1257 else if (self->service_type & IRCOMM_3_WIRE)
1258 ret += sprintf(buf+ret, "3_WIRE"); 1258 seq_puts(m, "3_WIRE");
1259 else if (self->service_type & IRCOMM_3_WIRE_RAW) 1259 else if (self->service_type & IRCOMM_3_WIRE_RAW)
1260 ret += sprintf(buf+ret, "3_WIRE_RAW"); 1260 seq_puts(m, "3_WIRE_RAW");
1261 else 1261 else
1262 ret += sprintf(buf+ret, "No common service type!\n"); 1262 seq_puts(m, "No common service type!\n");
1263 ret += sprintf(buf+ret, "\n"); 1263 seq_putc(m, '\n');
1264 1264
1265 ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name); 1265 seq_printf(m, "Port name: %s\n", self->settings.port_name);
1266 1266
1267 ret += sprintf(buf+ret, "DTE status: "); 1267 seq_printf(m, "DTE status:");
1268 if (self->settings.dte & IRCOMM_RTS) 1268 sep = ' ';
1269 ret += sprintf(buf+ret, "RTS|"); 1269 if (self->settings.dte & IRCOMM_RTS) {
1270 if (self->settings.dte & IRCOMM_DTR) 1270 seq_printf(m, "%cRTS", sep);
1271 ret += sprintf(buf+ret, "DTR|"); 1271 sep = '|';
1272 if (self->settings.dte) 1272 }
1273 ret--; /* remove the last | */ 1273 if (self->settings.dte & IRCOMM_DTR) {
1274 ret += sprintf(buf+ret, "\n"); 1274 seq_printf(m, "%cDTR", sep);
1275 1275 sep = '|';
1276 ret += sprintf(buf+ret, "DCE status: "); 1276 }
1277 if (self->settings.dce & IRCOMM_CTS) 1277 seq_putc(m, '\n');
1278 ret += sprintf(buf+ret, "CTS|"); 1278
1279 if (self->settings.dce & IRCOMM_DSR) 1279 seq_puts(m, "DCE status:");
1280 ret += sprintf(buf+ret, "DSR|"); 1280 sep = ' ';
1281 if (self->settings.dce & IRCOMM_CD) 1281 if (self->settings.dce & IRCOMM_CTS) {
1282 ret += sprintf(buf+ret, "CD|"); 1282 seq_printf(m, "%cCTS", sep);
1283 if (self->settings.dce & IRCOMM_RI) 1283 sep = '|';
1284 ret += sprintf(buf+ret, "RI|"); 1284 }
1285 if (self->settings.dce) 1285 if (self->settings.dce & IRCOMM_DSR) {
1286 ret--; /* remove the last | */ 1286 seq_printf(m, "%cDSR", sep);
1287 ret += sprintf(buf+ret, "\n"); 1287 sep = '|';
1288 1288 }
1289 ret += sprintf(buf+ret, "Configuration: "); 1289 if (self->settings.dce & IRCOMM_CD) {
1290 seq_printf(m, "%cCD", sep);
1291 sep = '|';
1292 }
1293 if (self->settings.dce & IRCOMM_RI) {
1294 seq_printf(m, "%cRI", sep);
1295 sep = '|';
1296 }
1297 seq_putc(m, '\n');
1298
1299 seq_puts(m, "Configuration: ");
1290 if (!self->settings.null_modem) 1300 if (!self->settings.null_modem)
1291 ret += sprintf(buf+ret, "DTE <-> DCE\n"); 1301 seq_puts(m, "DTE <-> DCE\n");
1292 else 1302 else
1293 ret += sprintf(buf+ret, 1303 seq_puts(m, "DTE <-> DTE (null modem emulation)\n");
1294 "DTE <-> DTE (null modem emulation)\n"); 1304
1295 1305 seq_printf(m, "Data rate: %d\n", self->settings.data_rate);
1296 ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate); 1306
1297 1307 seq_puts(m, "Flow control:");
1298 ret += sprintf(buf+ret, "Flow control: "); 1308 sep = ' ';
1299 if (self->settings.flow_control & IRCOMM_XON_XOFF_IN) 1309 if (self->settings.flow_control & IRCOMM_XON_XOFF_IN) {
1300 ret += sprintf(buf+ret, "XON_XOFF_IN|"); 1310 seq_printf(m, "%cXON_XOFF_IN", sep);
1301 if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT) 1311 sep = '|';
1302 ret += sprintf(buf+ret, "XON_XOFF_OUT|"); 1312 }
1303 if (self->settings.flow_control & IRCOMM_RTS_CTS_IN) 1313 if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT) {
1304 ret += sprintf(buf+ret, "RTS_CTS_IN|"); 1314 seq_printf(m, "%cXON_XOFF_OUT", sep);
1305 if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT) 1315 sep = '|';
1306 ret += sprintf(buf+ret, "RTS_CTS_OUT|"); 1316 }
1307 if (self->settings.flow_control & IRCOMM_DSR_DTR_IN) 1317 if (self->settings.flow_control & IRCOMM_RTS_CTS_IN) {
1308 ret += sprintf(buf+ret, "DSR_DTR_IN|"); 1318 seq_printf(m, "%cRTS_CTS_IN", sep);
1309 if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT) 1319 sep = '|';
1310 ret += sprintf(buf+ret, "DSR_DTR_OUT|"); 1320 }
1311 if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN) 1321 if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT) {
1312 ret += sprintf(buf+ret, "ENQ_ACK_IN|"); 1322 seq_printf(m, "%cRTS_CTS_OUT", sep);
1313 if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT) 1323 sep = '|';
1314 ret += sprintf(buf+ret, "ENQ_ACK_OUT|"); 1324 }
1315 if (self->settings.flow_control) 1325 if (self->settings.flow_control & IRCOMM_DSR_DTR_IN) {
1316 ret--; /* remove the last | */ 1326 seq_printf(m, "%cDSR_DTR_IN", sep);
1317 ret += sprintf(buf+ret, "\n"); 1327 sep = '|';
1318 1328 }
1319 ret += sprintf(buf+ret, "Flags: "); 1329 if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT) {
1320 if (self->flags & ASYNC_CTS_FLOW) 1330 seq_printf(m, "%cDSR_DTR_OUT", sep);
1321 ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|"); 1331 sep = '|';
1322 if (self->flags & ASYNC_CHECK_CD) 1332 }
1323 ret += sprintf(buf+ret, "ASYNC_CHECK_CD|"); 1333 if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN) {
1324 if (self->flags & ASYNC_INITIALIZED) 1334 seq_printf(m, "%cENQ_ACK_IN", sep);
1325 ret += sprintf(buf+ret, "ASYNC_INITIALIZED|"); 1335 sep = '|';
1326 if (self->flags & ASYNC_LOW_LATENCY) 1336 }
1327 ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|"); 1337 if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT) {
1328 if (self->flags & ASYNC_CLOSING) 1338 seq_printf(m, "%cENQ_ACK_OUT", sep);
1329 ret += sprintf(buf+ret, "ASYNC_CLOSING|"); 1339 sep = '|';
1330 if (self->flags & ASYNC_NORMAL_ACTIVE) 1340 }
1331 ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|"); 1341 seq_putc(m, '\n');
1332 if (self->flags) 1342
1333 ret--; /* remove the last | */ 1343 seq_puts(m, "Flags:");
1334 ret += sprintf(buf+ret, "\n"); 1344 sep = ' ';
1335 1345 if (self->flags & ASYNC_CTS_FLOW) {
1336 ret += sprintf(buf+ret, "Role: %s\n", self->client ? 1346 seq_printf(m, "%cASYNC_CTS_FLOW", sep);
1337 "client" : "server"); 1347 sep = '|';
1338 ret += sprintf(buf+ret, "Open count: %d\n", self->open_count); 1348 }
1339 ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size); 1349 if (self->flags & ASYNC_CHECK_CD) {
1340 ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size); 1350 seq_printf(m, "%cASYNC_CHECK_CD", sep);
1351 sep = '|';
1352 }
1353 if (self->flags & ASYNC_INITIALIZED) {
1354 seq_printf(m, "%cASYNC_INITIALIZED", sep);
1355 sep = '|';
1356 }
1357 if (self->flags & ASYNC_LOW_LATENCY) {
1358 seq_printf(m, "%cASYNC_LOW_LATENCY", sep);
1359 sep = '|';
1360 }
1361 if (self->flags & ASYNC_CLOSING) {
1362 seq_printf(m, "%cASYNC_CLOSING", sep);
1363 sep = '|';
1364 }
1365 if (self->flags & ASYNC_NORMAL_ACTIVE) {
1366 seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep);
1367 sep = '|';
1368 }
1369 seq_putc(m, '\n');
1370
1371 seq_printf(m, "Role: %s\n", self->client ? "client" : "server");
1372 seq_printf(m, "Open count: %d\n", self->open_count);
1373 seq_printf(m, "Max data size: %d\n", self->max_data_size);
1374 seq_printf(m, "Max header size: %d\n", self->max_header_size);
1341 1375
1342 if (self->tty) 1376 if (self->tty)
1343 ret += sprintf(buf+ret, "Hardware: %s\n", 1377 seq_printf(m, "Hardware: %s\n",
1344 self->tty->hw_stopped ? "Stopped" : "Running"); 1378 self->tty->hw_stopped ? "Stopped" : "Running");
1345
1346 ret += sprintf(buf+ret, "\n");
1347 return ret;
1348} 1379}
1349 1380
1350 1381static int ircomm_tty_proc_show(struct seq_file *m, void *v)
1351/*
1352 * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
1353 *
1354 *
1355 *
1356 */
1357static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
1358 int *eof, void *unused)
1359{ 1382{
1360 struct ircomm_tty_cb *self; 1383 struct ircomm_tty_cb *self;
1361 int count = 0, l;
1362 off_t begin = 0;
1363 unsigned long flags; 1384 unsigned long flags;
1364 1385
1365 spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags); 1386 spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags);
1366 1387
1367 self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); 1388 self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
1368 while ((self != NULL) && (count < 4000)) { 1389 while (self != NULL) {
1369 if (self->magic != IRCOMM_TTY_MAGIC) 1390 if (self->magic != IRCOMM_TTY_MAGIC)
1370 break; 1391 break;
1371 1392
1372 l = ircomm_tty_line_info(self, buf + count); 1393 ircomm_tty_line_info(self, m);
1373 count += l;
1374 if (count+begin > offset+len)
1375 goto done;
1376 if (count+begin < offset) {
1377 begin += count;
1378 count = 0;
1379 }
1380
1381 self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty); 1394 self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
1382 } 1395 }
1383 *eof = 1;
1384done:
1385 spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags); 1396 spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags);
1397 return 0;
1398}
1386 1399
1387 if (offset >= count+begin) 1400static int ircomm_tty_proc_open(struct inode *inode, struct file *file)
1388 return 0; 1401{
1389 *start = buf + (offset-begin); 1402 return single_open(file, ircomm_tty_proc_show, NULL);
1390 return ((len < begin+count-offset) ? len : begin+count-offset);
1391} 1403}
1404
1405static const struct file_operations ircomm_tty_proc_fops = {
1406 .owner = THIS_MODULE,
1407 .open = ircomm_tty_proc_open,
1408 .read = seq_read,
1409 .llseek = seq_lseek,
1410 .release = single_release,
1411};
1392#endif /* CONFIG_PROC_FS */ 1412#endif /* CONFIG_PROC_FS */
1393 1413
1394MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); 1414MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");