Commit ed7c25d31efabff5b92ee5149480eea9a54f2672

Authored by Jeff Buchbinder
1 parent 7cb1cd96

fix #1: import 1.2 from sourceforge

... ... @@ -10,10 +10,9 @@ module:
10 10 insmod tty0tty.ko -To load module (using root or sudo)
11 11  
12 12  
13   -this version is not installable
  13 +this version is not auto installable
14 14  
15 15  
16 16 Requirements:
17 17  
18 18 for module build is necessary kernel-headers or kernel source
19   - ( in debian use apt-get install linux-image-2.6.26-2-amd64 for example)
... ...
1   -tty0tty - linux null modem emulator
2   -Forked to instance on github since original project is dead.
  1 +
  2 +
  3 +tty0tty - linux null modem emulator v1.2
3 4  
4 5  
5 6 This is the tty0tty directory tree:
... ... @@ -8,7 +9,7 @@ This is the tty0tty directory tree:
8 9 pts - null-modem using ptys (without handshake lines)
9 10  
10 11  
11   -pts:
  12 +pts (unix98):
12 13  
13 14 When run connect two pseudo-ttys and show the connection names:
14 15  
... ... @@ -23,7 +24,7 @@ pts:
23 24  
24 25 module:
25 26  
26   - The module is tested in kernel 3.2.0
  27 + The module is tested in kernel 3.10.2 (debian)
27 28  
28 29 When loaded, create 8 ttys interconnected:
29 30 /dev/tnt0 <=> /dev/tnt1
... ... @@ -46,6 +47,6 @@ module:
46 47 Requirements:
47 48  
48 49 for module build is necessary kernel-headers or kernel source
49   - ( in debian use apt-get install linux-image-2.6.26-2-amd64 for example)
50 50  
51 51  
  52 +For e-mail suggestions : lcgamboa@yahoo.com
... ...
THANKS 0 → 100644
  1 +Special Thanks:
  2 +
  3 +* Jesus
  4 + for my life
... ...
TODO 0 → 100644
  1 +
  2 +implement wake_up_interruptible(&tp->wait) on every change of MSR register to TIOCMIWAIT work
  3 +
... ...
1 1 PACKAGE=tty0tty
2 2 MAINVER=1
3   -MINORVER=1
4   -VERSION=1.1
  3 +MINORVER=2
  4 +VERSION=1.2
... ...
module/Makefile
  1 +# Comment/uncomment the following line to disable/enable debugging
  2 +DEBUG = n
1 3  
  4 +
  5 +# Add your debugging flag (or not) to CFLAGS
  6 +ifeq ($(DEBUG),y)
  7 + DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
  8 +else
  9 + DEBFLAGS = -O2
  10 +endif
  11 +
  12 +EXTRA_CFLAGS += $(DEBFLAGS) -I..
  13 +
  14 +ifneq ($(KERNELRELEASE),)
  15 +# call from kernel build system
  16 +
  17 +#obj-m := tiny_tty.o tiny_serial.o tty0tty.o
2 18 obj-m := tty0tty.o
3 19  
  20 +else
  21 +
  22 +KERNELDIR ?= /lib/modules/$(shell uname -r)/build
  23 +PWD := $(shell pwd)
  24 +
  25 +default:
  26 + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  27 +
  28 +endif
  29 +
  30 +
  31 +
4 32 clean:
5 33 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers
6 34  
  35 +depend .depend dep:
  36 + $(CC) $(CFLAGS) -M *.c > .depend
  37 +
  38 +
  39 +ifeq (.depend,$(wildcard .depend))
  40 +include .depend
  41 +endif
... ...
module/tty0tty.c
1 1 /* ########################################################################
2 2  
3   - tty0tty - linux null modem emulator (module)
  3 + tty0tty - linux null modem emulator (module) for kernel > 3.8
4 4  
5 5 ########################################################################
6 6  
7   - Copyright (c) : 2010 Luis Claudio Gambôa Lopes
  7 + Copyright (c) : 2013 Luis Claudio Gambôa Lopes
8 8  
9 9 Based in Tiny TTY driver - Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)
10 10  
... ... @@ -25,6 +25,8 @@
25 25 For e-mail suggestions : lcgamboa@yahoo.com
26 26 ######################################################################## */
27 27  
  28 +
  29 +
28 30 #include <linux/kernel.h>
29 31 #include <linux/errno.h>
30 32 #include <linux/init.h>
... ... @@ -36,7 +38,7 @@
36 38 #include <linux/tty_flip.h>
37 39 #include <linux/serial.h>
38 40 #include <linux/sched.h>
39   -#include <linux/uaccess.h>
  41 +#include <asm/uaccess.h>
40 42  
41 43  
42 44 #define DRIVER_VERSION "v1.2"
... ... @@ -48,31 +50,23 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
48 50 MODULE_DESCRIPTION( DRIVER_DESC );
49 51 MODULE_LICENSE("GPL");
50 52  
51   -#define TINY_TTY_PAIRS 4
52   -
53   -#define TINY_TTY_MAJOR 240 /* experimental range */
54   -#define TINY_TTY_MINORS (TINY_TTY_PAIRS * 2)
55 53  
56   -/* Serial ports are paired by adjacent index numbers -- 0 and 1, 2 and 3, 4 and 5.
57   - * I.e. same upper bits of index number; only different least-significant-bit.
58   - * XOR least-significant-bit to find index of paired serial port.
59   - */
60   -#define PAIRED_INDEX(INDEX) ((INDEX) ^ 1)
  54 +#define TTY0TTY_MAJOR 240 /* experimental range */
  55 +#define TTY0TTY_MINORS 8 /* device number, always even*/
61 56  
62 57 /* fake UART values */
63 58 //out
64 59 #define MCR_DTR 0x01
65 60 #define MCR_RTS 0x02
66 61 #define MCR_LOOP 0x04
67   -#define MCR_OUT1 0x08
68   -#define MCR_OUT2 0x10
69 62 //in
70 63 #define MSR_CTS 0x10
71 64 #define MSR_CD 0x20
72 65 #define MSR_DSR 0x40
73 66 #define MSR_RI 0x80
  67 +
74 68  
75   -#define WRITE_ROOM_MAX 64
  69 +static struct tty_port tport[TTY0TTY_MINORS];
76 70  
77 71 struct tty0tty_serial {
78 72 struct tty_struct *tty; /* pointer to the tty for this device */
... ... @@ -87,53 +81,27 @@ struct tty0tty_serial {
87 81 struct serial_struct serial;
88 82 wait_queue_head_t wait;
89 83 struct async_icount icount;
  84 +
90 85 };
91 86  
92   -static struct tty0tty_serial *tty0tty_table[TINY_TTY_MINORS]; /* initially all NULL */
93   -
94   -/* Function prototypes */
95   -static int tty0tty_write_room(struct tty_struct *tty);
96   -
97   -static inline void null_modem_signal_copy(struct tty0tty_serial * tty_to, const struct tty0tty_serial * tty_from)
98   -{
99   - unsigned int msr_to = 0;
100   - unsigned int mcr_from = 0;
101   -
102   - if (tty_to != NULL && tty_to->open_count > 0) {
103   - if (tty_from != NULL && tty_from->open_count > 0) {
104   - mcr_from = tty_from->mcr;
105   - }
106   - msr_to = tty_to->msr & ~(MSR_CD | MSR_CTS | MSR_DSR | MSR_RI);
  87 +static struct tty0tty_serial *tty0tty_table[TTY0TTY_MINORS]; /* initially all NULL */
107 88  
108   - /* RTS --> CTS */
109   - if (mcr_from & MCR_RTS) {
110   - msr_to |= MSR_CTS;
111   - }
112   - /* DTR --> DSR and DCD */
113   - if (mcr_from & MCR_DTR) {
114   - msr_to |= MSR_DSR;
115   - msr_to |= MSR_CD;
116   - }
117   -
118   - tty_to->msr = msr_to;
119   - }
120   -}
121 89  
122 90 static int tty0tty_open(struct tty_struct *tty, struct file *file)
123 91 {
124 92 struct tty0tty_serial *tty0tty;
125   - int index;
126   - int paired_index;
  93 + int index;
  94 + int msr=0;
  95 + int mcr=0;
127 96  
128 97 #ifdef SCULL_DEBUG
129 98 printk(KERN_DEBUG "%s - \n", __FUNCTION__);
130 99 #endif
131   - /* initialize the pointer in case something fails */
  100 + /* initialize the pointer in case something fails */
132 101 tty->driver_data = NULL;
133 102  
134 103 /* get the serial object associated with this tty pointer */
135 104 index = tty->index;
136   - paired_index = PAIRED_INDEX(index);
137 105 tty0tty = tty0tty_table[index];
138 106 if (tty0tty == NULL) {
139 107 /* first time accessing this device, let's create it */
... ... @@ -141,17 +109,48 @@ static int tty0tty_open(struct tty_struct *tty, struct file *file)
141 109 if (!tty0tty)
142 110 return -ENOMEM;
143 111  
144   -#ifdef __LINUX_SEMAPHORE_H
145   - sema_init(&tty0tty->sem, 1);
146   -#else
147   - init_MUTEX(&tty0tty->sem);
148   -#endif
  112 + sema_init(&tty0tty->sem,1);
149 113 tty0tty->open_count = 0;
150 114  
151 115 tty0tty_table[index] = tty0tty;
  116 +
  117 + }
  118 +
  119 + tport[index].tty=tty;
  120 + tty->port = &tport[index];
  121 +
  122 + if( (index % 2) == 0)
  123 + {
  124 + if(tty0tty_table[index+1] != NULL)
  125 + if (tty0tty_table[index+1]->open_count > 0)
  126 + mcr=tty0tty_table[index+1]->mcr;
  127 + }
  128 + else
  129 + {
  130 + if(tty0tty_table[index-1] != NULL)
  131 + if (tty0tty_table[index-1]->open_count > 0)
  132 + mcr=tty0tty_table[index-1]->mcr;
  133 + }
  134 +
  135 +//null modem connection
152 136  
153   - }
  137 + if( (mcr & MCR_RTS) == MCR_RTS )
  138 + {
  139 + msr |= MSR_CTS;
  140 + }
  141 +
  142 + if( (mcr & MCR_DTR) == MCR_DTR )
  143 + {
  144 + msr |= MSR_DSR;
  145 + msr |= MSR_CD;
  146 + }
  147 +
  148 + tty0tty->msr = msr;
  149 + tty0tty->mcr = 0;
  150 +
154 151  
  152 + /* register the tty driver */
  153 +
155 154 down(&tty0tty->sem);
156 155  
157 156 /* save our structure within the tty structure */
... ... @@ -160,18 +159,31 @@ static int tty0tty_open(struct tty_struct *tty, struct file *file)
160 159  
161 160 ++tty0tty->open_count;
162 161  
163   - null_modem_signal_copy(tty0tty, tty0tty_table[paired_index]);
164   -
165 162 up(&tty0tty->sem);
166 163 return 0;
167 164 }
168 165  
169 166 static void do_close(struct tty0tty_serial *tty0tty)
170   -{
171   - down(&tty0tty->sem);
  167 +{
  168 + unsigned int msr=0;
  169 +
172 170 #ifdef SCULL_DEBUG
173 171 printk(KERN_DEBUG "%s - \n", __FUNCTION__);
174 172 #endif
  173 + if( (tty0tty->tty->index % 2) == 0)
  174 + {
  175 + if(tty0tty_table[tty0tty->tty->index+1] != NULL)
  176 + if (tty0tty_table[tty0tty->tty->index+1]->open_count > 0)
  177 + tty0tty_table[tty0tty->tty->index+1]->msr=msr;
  178 + }
  179 + else
  180 + {
  181 + if(tty0tty_table[tty0tty->tty->index-1] != NULL)
  182 + if (tty0tty_table[tty0tty->tty->index-1]->open_count > 0)
  183 + tty0tty_table[tty0tty->tty->index-1]->msr=msr;
  184 + }
  185 +
  186 + down(&tty0tty->sem);
175 187 if (!tty0tty->open_count) {
176 188 /* port was never opened */
177 189 goto exit;
... ... @@ -180,8 +192,9 @@ static void do_close(struct tty0tty_serial *tty0tty)
180 192 --tty0tty->open_count;
181 193 exit:
182 194 up(&tty0tty->sem);
183   -
184   - return;
  195 +
  196 +
  197 + return;
185 198 }
186 199  
187 200 static void tty0tty_close(struct tty_struct *tty, struct file *file)
... ... @@ -189,7 +202,7 @@ static void tty0tty_close(struct tty_struct *tty, struct file *file)
189 202 struct tty0tty_serial *tty0tty = tty->driver_data;
190 203  
191 204 #ifdef SCULL_DEBUG
192   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  205 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
193 206 #endif
194 207 if (tty0tty)
195 208 do_close(tty0tty);
... ... @@ -200,15 +213,8 @@ static int tty0tty_write(struct tty_struct *tty, const unsigned char *buffer, in
200 213 struct tty0tty_serial *tty0tty = tty->driver_data;
201 214 int retval = -EINVAL;
202 215 struct tty_struct *ttyx = NULL;
203   - int paired_index;
204   - int room = 0;
205   -
206   - room = tty0tty_write_room(tty);
207   - if (room < 0)
208   - /* error case */
209   - return room;
210 216  
211   - if (!tty0tty)
  217 + if (!tty0tty)
212 218 return -ENODEV;
213 219  
214 220 down(&tty0tty->sem);
... ... @@ -217,21 +223,27 @@ static int tty0tty_write(struct tty_struct *tty, const unsigned char *buffer, in
217 223 /* port was not opened */
218 224 goto exit;
219 225  
220   - paired_index = PAIRED_INDEX(tty0tty->tty->index);
221   - if (tty0tty_table[paired_index] != NULL &&
222   - tty0tty_table[paired_index]->open_count > 0)
223   - ttyx = tty0tty_table[paired_index]->tty;
224   -
225   -// tty->low_latency=1;
226   -
227   - if (count > room)
228   - count = room;
229   - if(ttyx != NULL)
230   - {
231   - tty_insert_flip_string(ttyx, buffer, count);
232   - tty_flip_buffer_push(ttyx);
233   - }
234   - retval=count;
  226 + if( (tty0tty->tty->index % 2) == 0)
  227 + {
  228 + if(tty0tty_table[tty0tty->tty->index+1] != NULL)
  229 + if (tty0tty_table[tty0tty->tty->index+1]->open_count > 0)
  230 + ttyx=tty0tty_table[tty0tty->tty->index+1]->tty;
  231 + }
  232 + else
  233 + {
  234 + if(tty0tty_table[tty0tty->tty->index-1] != NULL)
  235 + if (tty0tty_table[tty0tty->tty->index-1]->open_count > 0)
  236 + ttyx=tty0tty_table[tty0tty->tty->index-1]->tty;
  237 + }
  238 +
  239 +// tty->low_latency=1;
  240 +
  241 + if(ttyx != NULL)
  242 + {
  243 + tty_insert_flip_string(ttyx->port, buffer, count);
  244 + tty_flip_buffer_push(ttyx->port);
  245 + retval=count;
  246 + }
235 247  
236 248 exit:
237 249 up(&tty0tty->sem);
... ... @@ -241,43 +253,28 @@ exit:
241 253 static int tty0tty_write_room(struct tty_struct *tty)
242 254 {
243 255 struct tty0tty_serial *tty0tty = tty->driver_data;
244   - struct tty0tty_serial *tty0tty_paired = NULL;
245   - int index;
246   - int paired_index;
247 256 int room = -EINVAL;
248 257  
249 258 if (!tty0tty)
250 259 return -ENODEV;
251 260  
252 261 down(&tty0tty->sem);
253   -
  262 +
254 263 if (!tty0tty->open_count) {
255 264 /* port was not opened */
256 265 goto exit;
257 266 }
258 267  
259   - /* get the serial object associated with this tty pointer */
260   - index = tty->index;
261   - paired_index = PAIRED_INDEX(index);
262   - tty0tty_paired = tty0tty_table[paired_index];
263   - if (tty0tty_paired == NULL || tty0tty_paired->open_count == 0) {
264   - /* Paired port is not open */
265   - /* Effectively dump all written bytes */
266   - room = WRITE_ROOM_MAX;
267   - goto exit;
268   - }
269   -
270 268 /* calculate how much room is left in the device */
271   - room = WRITE_ROOM_MAX - tty0tty_paired->tty->read_cnt;
272   - if (room < 0) {
273   - room = 0;
274   - }
  269 + room = 255;
275 270  
276 271 exit:
277 272 up(&tty0tty->sem);
278 273 return room;
279 274 }
280 275  
  276 +
  277 +
281 278 #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
282 279  
283 280 static void tty0tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
... ... @@ -285,14 +282,15 @@ static void tty0tty_set_termios(struct tty_struct *tty, struct ktermios *old_ter
285 282 unsigned int cflag;
286 283  
287 284 #ifdef SCULL_DEBUG
288   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  285 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
289 286 #endif
290   - cflag = tty->termios->c_cflag;
  287 +
  288 + cflag = tty->termios.c_cflag;
291 289  
292 290 /* check that they really want us to change something */
293 291 if (old_termios) {
294 292 if ((cflag == old_termios->c_cflag) &&
295   - (RELEVANT_IFLAG(tty->termios->c_iflag) ==
  293 + (RELEVANT_IFLAG(tty->termios.c_iflag) ==
296 294 RELEVANT_IFLAG(old_termios->c_iflag))) {
297 295 #ifdef SCULL_DEBUG
298 296 printk(KERN_DEBUG " - nothing to change...\n");
... ... @@ -368,6 +366,7 @@ static void tty0tty_set_termios(struct tty_struct *tty, struct ktermios *old_ter
368 366 }
369 367  
370 368  
  369 +//static int tty0tty_tiocmget(struct tty_struct *tty, struct file *file)
371 370 static int tty0tty_tiocmget(struct tty_struct *tty)
372 371 {
373 372 struct tty0tty_serial *tty0tty = tty->driver_data;
... ... @@ -377,76 +376,101 @@ static int tty0tty_tiocmget(struct tty_struct *tty)
377 376 unsigned int mcr = tty0tty->mcr;
378 377  
379 378  
380   - result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */
381   - ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */
382   - ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */
383   - ((mcr & MCR_OUT1) ? TIOCM_OUT1 : 0) | /* OUT1 is set */
384   - ((mcr & MCR_OUT2) ? TIOCM_OUT2 : 0) | /* OUT2 is set */
385   - ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */
386   - ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/
387   - ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */
388   - ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */
  379 + result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */
  380 + ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */
  381 + ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */
  382 + ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */
  383 + ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/
  384 + ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */
  385 + ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */
389 386  
390 387 return result;
391 388 }
392 389  
393   -static int tty0tty_tiocmset(struct tty_struct *tty,
394   - unsigned int set, unsigned int clear)
  390 +
  391 +
  392 +
  393 +
  394 +//static int tty0tty_tiocmset(struct tty_struct *tty, struct file *file,
  395 +static int tty0tty_tiocmset(struct tty_struct *tty,
  396 + unsigned int set, unsigned int clear)
395 397 {
396 398 struct tty0tty_serial *tty0tty = tty->driver_data;
397 399 unsigned int mcr = tty0tty->mcr;
398   - int paired_index;
399   -
  400 + unsigned int msr=0;
  401 +
400 402 #ifdef SCULL_DEBUG
401   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  403 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
402 404 #endif
403 405  
404   - /* Set bits */
405   - if (set & TIOCM_RTS) {
406   - mcr |= MCR_RTS;
407   - }
408   - if (set & TIOCM_DTR) {
409   - mcr |= MCR_DTR;
410   - }
411   - if (set & TIOCM_OUT1) {
412   - mcr |= MCR_OUT1;
413   - }
414   - if (set & TIOCM_OUT2) {
415   - mcr |= MCR_OUT2;
416   - }
  406 + if( (tty0tty->tty->index % 2) == 0)
  407 + {
  408 + if(tty0tty_table[tty0tty->tty->index+1] != NULL)
  409 + if (tty0tty_table[tty0tty->tty->index+1]->open_count > 0)
  410 + msr=tty0tty_table[tty0tty->tty->index+1]->msr;
  411 + }
  412 + else
  413 + {
  414 + if(tty0tty_table[tty0tty->tty->index-1] != NULL)
  415 + if (tty0tty_table[tty0tty->tty->index-1]->open_count > 0)
  416 + msr=tty0tty_table[tty0tty->tty->index-1]->msr;
  417 + }
  418 +
  419 +//null modem connection
417 420  
418   - /* Clear bits */
419   - if (clear & TIOCM_RTS) {
420   - mcr &= ~MCR_RTS;
421   - }
422   - if (clear & TIOCM_DTR) {
423   - mcr &= ~MCR_DTR;
424   - }
425   - if (clear & TIOCM_OUT1) {
426   - mcr &= ~MCR_OUT1;
427   - }
428   - if (clear & TIOCM_OUT2) {
429   - mcr &= ~MCR_OUT2;
430   - }
  421 + if (set & TIOCM_RTS)
  422 + {
  423 + mcr |= MCR_RTS;
  424 + msr |= MSR_CTS;
  425 + }
  426 +
  427 + if (set & TIOCM_DTR)
  428 + {
  429 + mcr |= MCR_DTR;
  430 + msr |= MSR_DSR;
  431 + msr |= MSR_CD;
  432 + }
  433 +
  434 + if (clear & TIOCM_RTS)
  435 + {
  436 + mcr &= ~MCR_RTS;
  437 + msr &= ~MSR_CTS;
  438 + }
  439 +
  440 + if (clear & TIOCM_DTR)
  441 + {
  442 + mcr &= ~MCR_DTR;
  443 + msr &= ~MSR_DSR;
  444 + msr &= ~MSR_CD;
  445 + }
  446 +
431 447  
432 448 /* set the new MCR value in the device */
433 449 tty0tty->mcr = mcr;
434   -
435   - //null modem connection
436   - paired_index = PAIRED_INDEX(tty0tty->tty->index);
437   - null_modem_signal_copy(tty0tty_table[paired_index], tty0tty);
438   -
  450 +
  451 + if( (tty0tty->tty->index % 2) == 0)
  452 + {
  453 + if(tty0tty_table[tty0tty->tty->index+1] != NULL)
  454 + if (tty0tty_table[tty0tty->tty->index+1]->open_count > 0)
  455 + tty0tty_table[tty0tty->tty->index+1]->msr=msr;
  456 + }
  457 + else
  458 + {
  459 + if(tty0tty_table[tty0tty->tty->index-1] != NULL)
  460 + if (tty0tty_table[tty0tty->tty->index-1]->open_count > 0)
  461 + tty0tty_table[tty0tty->tty->index-1]->msr=msr;
  462 + }
439 463 return 0;
440 464 }
441 465  
442 466  
443   -static int tty0tty_ioctl_tiocgserial(struct tty_struct *tty,
444   - unsigned int cmd, unsigned long arg)
  467 +static int tty0tty_ioctl_tiocgserial(struct tty_struct *tty,
  468 + unsigned int cmd, unsigned long arg)
445 469 {
446 470 struct tty0tty_serial *tty0tty = tty->driver_data;
447 471  
448 472 #ifdef SCULL_DEBUG
449   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  473 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
450 474 #endif
451 475 if (cmd == TIOCGSERIAL) {
452 476 struct serial_struct tmp;
... ... @@ -477,12 +501,12 @@ static int tty0tty_ioctl_tiocgserial(struct tty_struct *tty,
477 501 }
478 502  
479 503 static int tty0tty_ioctl_tiocmiwait(struct tty_struct *tty,
480   - unsigned int cmd, unsigned long arg)
  504 + unsigned int cmd, unsigned long arg)
481 505 {
482 506 struct tty0tty_serial *tty0tty = tty->driver_data;
483 507  
484 508 #ifdef SCULL_DEBUG
485   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  509 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
486 510 #endif
487 511 if (cmd == TIOCMIWAIT) {
488 512 DECLARE_WAITQUEUE(wait, current);
... ... @@ -518,12 +542,12 @@ static int tty0tty_ioctl_tiocmiwait(struct tty_struct *tty,
518 542 }
519 543  
520 544 static int tty0tty_ioctl_tiocgicount(struct tty_struct *tty,
521   - unsigned int cmd, unsigned long arg)
  545 + unsigned int cmd, unsigned long arg)
522 546 {
523 547 struct tty0tty_serial *tty0tty = tty->driver_data;
524 548  
525 549 #ifdef SCULL_DEBUG
526   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  550 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
527 551 #endif
528 552 if (cmd == TIOCGICOUNT) {
529 553 struct async_icount cnow = tty0tty->icount;
... ... @@ -549,7 +573,7 @@ static int tty0tty_ioctl_tiocgicount(struct tty_struct *tty,
549 573 }
550 574  
551 575 static int tty0tty_ioctl(struct tty_struct *tty,
552   - unsigned int cmd, unsigned long arg)
  576 + unsigned int cmd, unsigned long arg)
553 577 {
554 578 #ifdef SCULL_DEBUG
555 579 printk(KERN_DEBUG "%s - %04X \n", __FUNCTION__,cmd);
... ... @@ -577,17 +601,21 @@ static struct tty_operations serial_ops = {
577 601 .ioctl = tty0tty_ioctl,
578 602 };
579 603  
  604 +
  605 +
  606 +
580 607 static struct tty_driver *tty0tty_tty_driver;
581 608  
582 609 static int __init tty0tty_init(void)
583 610 {
584   -
585 611 int retval;
  612 + int i;
  613 +
586 614 #ifdef SCULL_DEBUG
587 615 printk(KERN_DEBUG "%s - \n", __FUNCTION__);
588 616 #endif
589 617 /* allocate the tty driver */
590   - tty0tty_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);
  618 + tty0tty_tty_driver = alloc_tty_driver(TTY0TTY_MINORS);
591 619 if (!tty0tty_tty_driver)
592 620 return -ENOMEM;
593 621  
... ... @@ -595,28 +623,32 @@ static int __init tty0tty_init(void)
595 623 tty0tty_tty_driver->owner = THIS_MODULE;
596 624 tty0tty_tty_driver->driver_name = "tty0tty";
597 625 tty0tty_tty_driver->name = "tnt";
598   - /* no more devfs subsystem */
599   - tty0tty_tty_driver->major = TINY_TTY_MAJOR;
  626 + /* no more devfs subsystem */
  627 + tty0tty_tty_driver->major = TTY0TTY_MAJOR;
600 628 tty0tty_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
601 629 tty0tty_tty_driver->subtype = SERIAL_TYPE_NORMAL;
602   - tty0tty_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW ;
603   - /* no more devfs subsystem */
  630 + tty0tty_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW ;
  631 + /* no more devfs subsystem */
604 632 tty0tty_tty_driver->init_termios = tty_std_termios;
605   - tty0tty_tty_driver->init_termios.c_iflag = 0;
606   - tty0tty_tty_driver->init_termios.c_oflag = 0;
607   - tty0tty_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
608   - tty0tty_tty_driver->init_termios.c_lflag = 0;
609   - tty0tty_tty_driver->init_termios.c_ispeed = 38400;
610   - tty0tty_tty_driver->init_termios.c_ospeed = 38400;
  633 + tty0tty_tty_driver->init_termios.c_iflag = 0;
  634 + tty0tty_tty_driver->init_termios.c_oflag = 0;
  635 + tty0tty_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
  636 + tty0tty_tty_driver->init_termios.c_lflag = 0;
  637 + tty0tty_tty_driver->init_termios.c_ispeed = 38400;
  638 + tty0tty_tty_driver->init_termios.c_ospeed = 38400;
611 639  
612 640  
613 641 tty_set_operations(tty0tty_tty_driver, &serial_ops);
  642 +
  643 + for(i=0;i<TTY0TTY_MINORS;i++)
  644 + {
  645 + tty_port_init(&tport[i]);
  646 + tty_port_link_device(&tport[i],tty0tty_tty_driver, i);
  647 + }
614 648  
615   -
616   - /* register the tty driver */
617   - retval = tty_register_driver(tty0tty_tty_driver);
  649 + retval = tty_register_driver(tty0tty_tty_driver);
618 650 if (retval) {
619   - printk(KERN_ERR "failed to register tty0tty tty driver\n");
  651 + printk(KERN_ERR "failed to register tty0tty tty driver");
620 652 put_tty_driver(tty0tty_tty_driver);
621 653 return retval;
622 654 }
... ... @@ -631,14 +663,17 @@ static void __exit tty0tty_exit(void)
631 663 int i;
632 664  
633 665 #ifdef SCULL_DEBUG
634   - printk(KERN_DEBUG "%s - \n", __FUNCTION__);
  666 + printk(KERN_DEBUG "%s - \n", __FUNCTION__);
635 667 #endif
636   - for (i = 0; i < TINY_TTY_MINORS; ++i)
  668 + for (i = 0; i < TTY0TTY_MINORS; ++i)
  669 + {
  670 + tty_port_destroy(&tport[i]);
637 671 tty_unregister_device(tty0tty_tty_driver, i);
  672 + }
638 673 tty_unregister_driver(tty0tty_tty_driver);
639 674  
640 675 /* shut down all of the timers and free the memory */
641   - for (i = 0; i < TINY_TTY_MINORS; ++i) {
  676 + for (i = 0; i < TTY0TTY_MINORS; ++i) {
642 677 tty0tty = tty0tty_table[i];
643 678 if (tty0tty) {
644 679 /* close the port */
... ...
pts/tty0tty.c
... ... @@ -4,7 +4,7 @@
4 4  
5 5 ########################################################################
6 6  
7   - Copyright (c) : 2010 Luis Claudio Gambôa Lopes
  7 + Copyright (c) : 2013 Luis Claudio Gambôa Lopes and Maximiliano Pin max.pin@bitroit.com
8 8  
9 9 This program is free software; you can redistribute it and/or modify
10 10 it under the terms of the GNU General Public License as published by
... ... @@ -29,9 +29,13 @@
29 29 #include <string.h>
30 30 #include <unistd.h>
31 31 #include <fcntl.h>
  32 +#include <sys/select.h>
  33 +#include <errno.h>
32 34  
33 35 #include <termio.h>
34 36  
  37 +static char buffer[1024];
  38 +
35 39 int
36 40 ptym_open(char *pts_name, char *pts_name_s , int pts_namesz)
37 41 {
... ... @@ -71,7 +75,7 @@ int
71 75 conf_ser(int serialDev)
72 76 {
73 77  
74   -int rc=0;
  78 +int rc;
75 79 struct termios params;
76 80  
77 81 // Get terminal atributes
... ... @@ -102,8 +106,55 @@ tcflush(serialDev, TCIOFLUSH);
102 106 return EXIT_SUCCESS;
103 107 }
104 108  
  109 +void
  110 +copydata(int fdfrom, int fdto)
  111 +{
  112 + ssize_t br, bw;
  113 + char *pbuf = buffer;
  114 + br = read(fdfrom, buffer, 1024);
  115 + if (br < 0)
  116 + {
  117 + if (errno == EAGAIN || errno == EIO)
  118 + {
  119 + br = 0;
  120 + }
  121 + else
  122 + {
  123 + perror("read");
  124 + exit(1);
  125 + }
  126 + }
  127 + if (br > 0)
  128 + {
  129 + do
  130 + {
  131 + do
  132 + {
  133 + bw = write(fdto, pbuf, br);
  134 + if (bw > 0)
  135 + {
  136 + pbuf += bw;
  137 + br -= bw;
  138 + }
  139 + } while (br > 0 && bw > 0);
  140 + } while (bw < 0 && errno == EAGAIN);
  141 + if (bw <= 0)
  142 + {
  143 + // kernel buffer may be full, but we can recover
  144 + fprintf(stderr, "Write error, br=%d bw=%d\n", br, bw);
  145 + usleep(500000);
  146 + // discard input
  147 + while (read(fdfrom, buffer, 1024) > 0)
  148 + ;
  149 + }
  150 + }
  151 + else
  152 + {
  153 + usleep(100000);
  154 + }
  155 +}
105 156  
106   -int main(void)
  157 +int main(int argc, char* argv[])
107 158 {
108 159 char master1[1024];
109 160 char slave1[1024];
... ... @@ -113,26 +164,56 @@ int main(void)
113 164 int fd1;
114 165 int fd2;
115 166  
116   - char c1,c2;
  167 + fd_set rfds;
  168 + int retval;
117 169  
118 170 fd1=ptym_open(master1,slave1,1024);
119 171  
120 172 fd2=ptym_open(master2,slave2,1024);
121 173  
122   - printf("(%s) <=> (%s)\n",slave1,slave2);
123   -
124   -
125   - conf_ser(fd1);
126   - conf_ser(fd2);
  174 + if (argc >= 3)
  175 + {
  176 + unlink(argv[1]);
  177 + unlink(argv[2]);
  178 + if (symlink(slave1, argv[1]) < 0)
  179 + {
  180 + fprintf(stderr, "Cannot create: %s\n", argv[1]);
  181 + return 1;
  182 + }
  183 + if (symlink(slave2, argv[2]) < 0) {
  184 + fprintf(stderr, "Cannot create: %s\n", argv[2]);
  185 + return 1;
  186 + }
  187 + printf("(%s) <=> (%s)\n",argv[1],argv[2]);
  188 + }
  189 + else {
  190 + printf("(%s) <=> (%s)\n",slave1,slave2);
  191 + }
127 192  
  193 + conf_ser(fd1);
  194 + conf_ser(fd2);
128 195  
129 196 while(1)
130 197 {
131   - if(read (fd1,&c1,1) == 1) write(fd2,&c1,1);
132   - usleep(20);
133   - if(read (fd2,&c2,1) == 1) write(fd1,&c2,1);
134   - usleep(20);
135   - };
  198 + FD_ZERO(&rfds);
  199 + FD_SET(fd1, &rfds);
  200 + FD_SET(fd2, &rfds);
  201 +
  202 + retval = select(fd2 + 1, &rfds, NULL, NULL, NULL);
  203 + if (retval == -1)
  204 + {
  205 + perror("select");
  206 + return 1;
  207 + }
  208 + if (FD_ISSET(fd1, &rfds))
  209 + {
  210 + copydata(fd1, fd2);
  211 + }
  212 + if (FD_ISSET(fd2, &rfds))
  213 + {
  214 + copydata(fd2, fd1);
  215 + }
  216 + }
136 217  
137 218 close(fd1);
138 219 close(fd2);
... ...