Commit ed7c25d31efabff5b92ee5149480eea9a54f2672
1 parent
7cb1cd96
fix #1: import 1.2 from sourceforge
Showing
8 changed files
with
358 additions
and
200 deletions
INSTALL
| ... | ... | @@ -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) | ... | ... |
README
| 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
TODO
0 → 100644
VERSION
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); | ... | ... |