Programar el puerto serie en Linux

CÓMO Programar el puerto serie en Linux
por Peter H. Baumann, Peter.Baumann@dlr.de
traducción de Pedro Pablo Fábrega pfabrega@arrakis.es
v0.3, 14 Junio 1997

Este documento describe cómo programar comunicaciones con dispositivos
sobre puerto serie en una máquina Linux.
______________________________________________________________________

Índice General:

1. Introducción

1.1. Copyright

1.2. Versiones futuras de este Documento

1.3. Revisión

2. Comenzando

2.1. Depuración

2.2. Configuración del Puerto

2.3. Conceptos de entrada para dispositivos serie

2.3.1. Proceso de Entrada Canónico

2.3.2. Proceso de Entrada No Canónico

2.3.3. Entrada Asíncrona

2.3.4. Espera de Entradas Origen Múltiple

3. Programas Ejemplo

3.1. Proceso de Entrada Canónico

3.2. Proceso de Entrada NO Canónico

3.3. Entrada Asíncrona

3.4. Espera de Entradas de Origen Múltiple.

4. Otras fuentes de Información

5. Contribuciones

5.1. Traducción

6. Anexo: El INSFLUG
______________________________________________________________________

1. Introducción

Este es el COMO Programar el puerto serie en Linux. Todo sobre cómo
programar comunicaciones con otros dispositivos/ordenadores sobre una
línea serie, bajo Linux. Explicaremos diferentes técnicas: E/S
Canónica (sólo se transmiten/reciben líneas completas), E/S asíncrona,
y espera para una entrada de origen múltiple.

Este documento no describe cómo configurar un puerto serie, ya que
esto ha sido descrito por Greg Hankins en el Serial-HOWTO (–
Disponible en castellano como Serie-COMO.–)
Tengo que hacer notar encarecidamente que no soy un experto en este
campo, pero he tenido problemas con un proyecto que necesitaba tales
comunicaciones. Los ejemplos de código añadidos aquí se derivaron del
código de miniterm disponible en la guía de programadores del Linux
Documentation Project:

(ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/ y
espejos) en el directorio de ejemplos. Si alguien tiene algún
comentario, con gusto lo incorporaré a este documento (ver sección
«»).

Todos los ejemplos fueron comprobados usando un núcleo Linux 2.0.29
sobre un i386.

1.1. Copyright

El CÓMO Programar el puerto serie en Linux es propiedad inteletual (C)
1997 de Peter Baumann. Los documentos Linux HOWTO – Linux COMO pueden
ser reproducidos y distribuidos completos o en parte, en cualquier
medio físico o electrónico, con la única condición de que mantengan
esta nota de propiedad intelectual en todas sus copias. La
redistribución comercial está permitida y fomentada; de todas formas
al autor le gustaría que se le notificaran tales distribuciones.

Todas las traducciones, trabajos derivados o trabajos agregados que
incorporen cualquier documento Linux HOWTO-Linux COMO debe estar
cubierto por esta nota de propiedad intelectual. En resumen, no puede
crear un trabajo derivado de un HOWTO-COMO e imponer restricciones
adicionales a su distribución. Se pueden conceder excepciones a estas
reglas bajo ciertas condiciones; por favor contacte con el coordinador
de los HOWTO en la dirección dada abajo.

Resumiendo, queremos promover la difusión de esta información a través
de tantos canales com sea posible. No obstante queremos retener la
propiedad intelectual de los docuentos HOWTO-COMO, y nos gustaría que
se nos notificara cualquier plan para redistribuir los HOWTO-COMO.

Si tiene preguntas, por favor contacte con Greg Hankins, el
coordinador de los HOWTO de Linux, en gregh@sunsite.unc.edu mediante
correo electrónico.

1.2. Versiones futuras de este Documento

Las nuevas versiones de COMO Programar el puerto serie en Linux
estarán disponibles en:
ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/Serial-Programming-HOWTO y
sus espejos. Hay otros formatos, como versiones PostScript y DVI en
el directorio other-formats.

CÓMO Programar el puerto serie en Linux también está disponible en
http://sunsite.unc.edu/LDP/HOWTO/Serial-Programming-HOWTO.html y será
enviado a comp.os.linux.answers mensualmente.

1.3. Revisión

Por favor, mándeme cualesquiera corrección, pregunta, comentario,
sugerencia o material adicional. Me gustaría mejorar este HOWTO-COMO.
Dígame exactamente qué es lo que no entiende, o qué debería estar más
claro. Me puede encontrar en Peter.Baumann@dlr.de vía email. Por
favor, incluya el número de versión del CÓMO Programar el puerto serie
en Linux cuando escriba. Esta es la versión 0.3.

2. Comenzando

2.1. Depuración

La mejor forma de depurar su código es configurar otra máquina Linux y
conectar los dos ordenadores mediante un cable null-módem.

Use miniterm, disponible en el LDP Programmers Guide:
(ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/
en el directorio de ejemplos) para transmitir caracteres a su máquina
Linux. Miniterm se puede compilar con mucha facilidad y transmitirá
todas las entradas en bruto del teclado por el puerto serie.

Sólo las sentencias define (#define MODEMDEVICE «/dev/ttyS0») tienen
que ser comprobadas. Ponga ttyS0 para COM1, ttyS1 para COM2, etc.. Es
esencial para comprobar que todos los caracteres se transmiten en
bruto (sin un procesamiento de salida) por la línea. Para comprobar su
conexión, inicie miniterm en ambos ordemadores y teclee algo. Los
caracteres introducidos en un ordenador deberían aparecer en el otro y
viceversa. La entrada no tendrá eco en la pantalla del ordenador en el
que escribamos.

Para hacer un cable null-modem tiene que cruzar las líneas TxD
(transmit) y RxD (receive). Para una descripción del cable vea el
Serie-COMO.

También es posible ejecutar estas comprobaciones con un sólo
ordenador, si tiene un puerto serie no utilizado. Puede ejecutar dos
miniterm en sendas consolas virtuales. Si libera un puerto serie
desconectando el ratón, recuerde redirigir /dev/mouse, si existe. Si
usa una tarjeta multipuerto serie, esté seguro de configurarla
correctamente. Yo tenía la mía mal configurada, y todo funcionaba bien
mientras hacía las comprobaciones en un sólo ordenador. Cuando lo
conecté a otro, el puerto empezó a perder caracteres. La ejecución de
dos programas en un ordenador nunca es completamente asíncrona.

2.2. Configuración del Puerto

Los dispositivos /dev/ttyS* tienen como misión conectar terminales a
su linux, y están configurados para este uso al arrancar. Hay que
tener esto presente cuando se programen comunicaciones con un
dispositivo. Por ejemplo, los puertos están configurados para escribir
en pantalla cada carácter enviado desde el dispositivo, que
normalmente tiene que ser cambiado para la transmisión de datos.

Todos los parámetros se pueden configurar fácilmente con un programa.
La configuración se guarda en una estructura struct termios, que está
definida en :

#define NCCS 19
struct termios {
tcflag_t c_iflag; /* parametros de modo entrada */
tcflag_t c_oflag; /* parametros de modo salida */
tcflag_t c_cflag; /* parametros de modo control */
tcflag_t c_lflag; /* parametros de modo local */
cc_t c_line; /* disciplina de la linea */
cc_t c_cc[NCCS]; /* caracteres de control */
};

Este archivo también incluye todas las definiciones de parámetros. Los
parámetros de modo entrada de c_iflag manejan todos los procesos de
entrada, lo cual significa que los caracteres enviados desde el
dispositivo pueden ser procesados antes de ser leídos con read.

De forma similar c_oflag maneja los procesos de salida. c_cflag
contiene la configuración del puerto, como la velocidad en baudios,
bits por carácter, bits de parada, etc… Los parámetros de modo local
se guardan en c_lflag. Determinan si el carácter tiene eco, señales
enviadas al programa, etc…

Finalmente la tabla c_cc define el carácter de control para el fin de
fichero, parada, etc… Los valores por defecto de los caracteres de
control están definidos en . Los parámetros están
descritos en la página del manual termios(3).

La estructura termios contiene los elementos c_line. Estos elementos
no se mencionan ni las páginas del manual para termios de Linux ni en
las páginas de manual de Solaris 2.5. ¿Podría alguien arrojar alguna
luz sobre esto? ¿No debería estar incluido en la estructura termio?

2.3. Conceptos de entrada para dispositivos serie

Hay tres diferentes conceptos de entrada que queremos presentar. El
concepto apropiado se tiene que escoger para la aplicación a la que lo
queremos destinar. Siempre que sea posible no haga un bucle para leer
un sólo carácter a fin de obtener una cadena completa. Cuando he hecho
esto, he perdido caracteres, mientras que un read para toda la cadena
no mostró errores.

2.3.1. Proceso de Entrada Canónico

Es el modo de proceso normal para terminales, pero puede ser útil
también para comunicaciones con otros dispositivos. Toda la entrada es
procesada en unidades de líneas, lo que significa que un read sólo
devolverá una línea completa de entrada. Una línea está, por defecto,
finalizada con un NL(ASCII LF), y fin de fichero, o un carácter fin de
línea. Un CR (el fin de línea por defecto de DOS/Windows) no terminará
una línea con la configuración por defecto.

El proceso de entrada canónica puede, también, manejar los caracteres
borrado, borrado de palabra, reimprimir carácter, traducir CR a NL,
etc..

2.3.2. Proceso de Entrada No Canónico

El Proceso de Entrada No Canónico manejará un conjunto fijo de
caracteres por lectura, y permite un carácter temporizador. Este modo
se debería usar si su aplicación siempre lee un número fijo de
caracteres, o si el dispositivo conectado envía ráfagas de caracteres.

2.3.3. Entrada Asíncrona

Los dos modos descritos anteriomente se pueden usar en modos síncrono
y asíncrono. El modo síncrono viene por defecto, donde la sentencia
read se bloquará hasta que la lectura esté completa. En modo asíncrono
la sentencia read devolverá inmediatamente y enviará una señal al
programa llamador cuando esté completa. Esta señal puede ser recibida
por un manejador de señales.

2.3.4. Espera de Entradas Origen Múltiple

No es un modo diferente de entrada, pero puede ser útil si está
manejando dispositivos múltiples. En mi aplicación manejaba entradas
sobre un socket TCP/IP y entradas sobre una conexión serie de otro
ordenador de forma casi simultánea. El programa ejemplo dado abajo
esperará una entrada de dos orígenes distintos. Si la entrada de una
fuente está disponible, entonces será procesada, y el programa
esperará otra entrada nueva.

La aproximación presentada abajo parece más bien compleja, pero es
importante tener en cuenta que Linux es un sistema operativo
multiproceso. La llamada al sistema select no carga la CPU mientras
espera una entrada, mientras que un bucle hasta que hay una una
entrada disponible ralentizaría demasiado el resto de procesos que se
ejecuten a la misma vez.

3. Programas Ejemplo

Todos los ejemplos provienen de miniterm.c. El buffer está limitado a
255 caracteres, como la longitud máxima de cadena para el proceso de
entrada canónica. ( o ).

Vea los comentarios que hay en el código para una explicación del uso
de los diferentes modos de entrada. Espero que el código sea
comprensible. El ejemplo de entrada canónica está mejor comentado, el
resto de los ejemplos están comentados sólo donde difieren del ejemplo
de entrada canónica para remarcar las diferencias.

Las descripciones no son completas, por eso le invito a experimentar
con los ejemplos para obtener mejores soluciones para su aplicación.

¡No olvide dar los permisos apropiados a los puertos serie:

chmod a+rw /dev/ttyS1

3.1. Proceso de Entrada Canónico

#include
#include
#include
#include
#include

/* la tasa de baudios esta definida en , que esta
incluida */

#define BAUDRATE B38400

/* cambie esta definicion por el puerto correcto */
#define MODEMDEVICE «/dev/ttyS1»

#define _POSIX_SOURCE 1 /* fuentes cumple POSIX */

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
int fd,c, res;
struct termios oldtio,newtio;
char buf[255];

/*
Abre el dispositivo modem para lectura y escritura y no como controlador
tty porque no queremos que nos mate si el ruido de la linea envia
un CTRL-C.
*/

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) { perror(MODEMDEVICE); exit(-1); } tcgetattr(fd,&oldtio); /* almacenamos la configuracion actual del puerto */ bzero(newtio, sizeof(newtio)); /* limpiamos struct para recibir los nuevos parametros del puerto */ /* BAUDRATE: Fija la tasa bps. Podria tambien usar cfsetispeed y cfsetospeed. CRTSCTS : control de flujo de salida por hardware (usado solo si el cable tiene todas las lineas necesarias Vea sect. 7 de Serial-HOWTO) CS8 : 8n1 (8bit,no paridad,1 bit de parada) CLOCAL : conexion local, sin control de modem CREAD : activa recepcion de caracteres */ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; /* IGNPAR : ignora los bytes con error de paridad ICRNL : mapea CR a NL (en otro caso una entrada CR del otro ordenador no terminaria la entrada) en otro caso hace un dispositivo en bruto (sin otro proceso de entrada) */ newtio.c_iflag = IGNPAR | ICRNL; /* Salida en bruto. */ newtio.c_oflag = 0; /* ICANON : activa entrada canonica desactiva todas las funcionalidades del eco, y no envia segnales al programa llamador */ newtio.c_lflag = ICANON; /* inicializa todos los caracteres de control los valores por defecto se pueden encontrar en /usr/include/termios.h, y vienen dadas en los comentarios, pero no los necesitamos aqui */ newtio.c_cc[VINTR] = 0; /* Ctrl-c */ newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ newtio.c_cc[VERASE] = 0; /* del */ newtio.c_cc[VKILL] = 0; /* @ */ newtio.c_cc[VEOF] = 4; /* Ctrl-d */ newtio.c_cc[VTIME] = 0; /* temporizador entre caracter, no usado */ newtio.c_cc[VMIN] = 1; /* bloqu.lectura hasta llegada de caracter. 1 */ newtio.c_cc[VSWTC] = 0; /* '\0' */ newtio.c_cc[VSTART] = 0; /* Ctrl-q */ newtio.c_cc[VSTOP] = 0; /* Ctrl-s */ newtio.c_cc[VSUSP] = 0; /* Ctrl-z */ newtio.c_cc[VEOL] = 0; /* '\0' */ newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */ newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */ newtio.c_cc[VWERASE] = 0; /* Ctrl-w */ newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */ newtio.c_cc[VEOL2] = 0; /* '\0' */ /* ahora limpiamos la linea del modem y activamos la configuracion del puerto */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); /* configuracion del terminal realizada, ahora manejamos las entradas. En este ejemplo, al introducir una 'z' al inicio de linea terminara el programa. */ while (STOP==FALSE) { /* bucle hasta condicion de terminar */ /* bloque de ejecucion de programa hasta que llega un caracter de fin de linea, incluso si llegan mas de 255 caracteres. Si el numero de caracteres leidos es menor que el numero de caracteres disponibles, las siguientes lecturas devolveran los caracteres restantes. 'res' tomara el valor del numero actual de caracteres leidos. */ res = read(fd,buf,255); buf[res]=0; /* envio de fin de cadena, a fin de poder usar printf */ printf(":%s:%d\n", buf, res); if (buf[0]=='z') STOP=TRUE; } /* restaura la anterior configuracion del puerto */ tcsetattr(fd,TCSANOW,&oldtio); } 3.2. Proceso de Entrada NO Canónico En el modo de proceso de entrada no canónico, la entrada no está ensamblada en líneas y el procesamiento de la entrada (erase, kill, delete, etc.) no ocurre. Dos parámetros controlan el comportamiento de este modo: c_cc[VTIME] fija el temporizador de carácter, y fija el número mínimo de caracteres a recibir antes de satisfacer la lectura. Si MIN > 0 y TIME = 0, MIN fija el número de caracteres a recibir
antes de que la lectura esté realizada. Como TIME es cero, el
temporizador no se usa.

Si MIN = 0 y TIME > 0, TIME indica un tiempo de espera. La lectura se
realizará si es leído un sólo carácter, o si se excede TIME (t =TIME
*0.1 s). Si TIME se excede, no se devuelve ningún carácter.

Si MIN > 0 y TIME > 0, TIME indica un temporizador entre caracteres.
La lectura se realizará si se reciben MIN caracteres o el tiempo entre
dos caracteres excede TIME. El temporizador se reinicia cada vez que
se recibe un carácter y sólo se hace activo una vez que se ha recibido
el primer carácter.

Si MIN = 0 y TIME = 0, la lectura se realizará inmediatamente.
Devolverá el número de caracteres disponibles en el momento, o el
número de caracteres solicitados. De acuerdo con Antonino (ver
contribuciones), podría poner un fcntl(fd, F_SETFL, FNDELAY); antes de
leer para obtener el mismo resultado.

Modificando newtio.c_cc[VTIME] y newtio.c_cc[VMIN] se pueden comprobar
todos los modos descritos arriba.

#include
#include
#include
#include
#include

#define BAUDRATE B38400
#define MODEMDEVICE «/dev/ttyS1»
#define _POSIX_SOURCE 1 /* fuentes cumple POSIX */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
int fd,c, res;
struct termios oldtio,newtio;
char buf[255];

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) { perror(MODEMDEVICE); exit(-1); } tcgetattr(fd,&oldtio); /* salva configuracion actual del puerto */ bzero(newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* pone el modo entrada (no-canonico, sin eco,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* temporizador entre caracter, no usado */ newtio.c_cc[VMIN] = 5; /* bloquea lectura hasta recibir 5 chars */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); while (STOP==FALSE) { /* bucle para entrada */ res = read(fd,buf,255); /* devuelve tras introducir 5 */ buf[res]=0; /* asi podemos printf... */ printf(":%s:%d\n", buf, res); if (buf[0]=='z') STOP=TRUE; } tcsetattr(fd,TCSANOW,&oldtio); } 3.3. Entrada Asíncrona #include
#include
#include
#include
#include
#include

#define BAUDRATE B38400
#define MODEMDEVICE «/dev/ttyS1»
#define _POSIX_SOURCE 1 /* fuentes cumple POSIX */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

void signal_handler_IO (int status); /* definicion del manejador de segnal */
int wait_flag=TRUE; /* TRUE mientras no segnal recibida */

main()
{
int fd,c, res;
struct termios oldtio,newtio;
struct sigaction saio; /* definicion de accion de segnal */
char buf[255];

/* abre el dispositivo en modo no bloqueo (read volvera inmediatamente) */

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd <0) { perror(MODEMDEVICE); exit(-1); } /* instala el manejador de segnal antes de hacer asincrono el dispositivo */ saio.sa_handler = signal_handler_IO; saio.sa_mask = 0; saio.sa_flags = 0; saio.sa_restorer = NULL; sigaction(SIGIO,&saio,NULL); /* permite al proceso recibir SIGIO */ fcntl(fd, F_SETOWN, getpid()); /* Hace el descriptor de archivo asincrono (la pagina del manual dice solo O_APPEND y O_NONBLOCK, funcionara con F_SETFL...) */ fcntl(fd, F_SETFL, FASYNC); tcgetattr(fd,&oldtio); /* salvamos conf. actual del puerto */ /* fija la nueva configuracion del puerto para procesos de entrada canonica */ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR | ICRNL; newtio.c_oflag = 0; newtio.c_lflag = ICANON; newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); /* bucle de espera para entrada. Normalmente se haria algo util aqui */ while (STOP==FALSE) { printf(".\n");usleep(100000); /* tras recibir SIGIO, wait_flag = FALSE, la entrada esta disponible y puede ser leida */ if (wait_flag==FALSE) { res = read(fd,buf,255); buf[res]=0; printf(":%s:%d\n", buf, res); if (res==1) STOP=TRUE; /* para el bucle si solo entra un CR */ wait_flag = TRUE; /* espera una nueva entrada */ } } /* restaura la configuracion original del puerto */ tcsetattr(fd,TCSANOW,&oldtio); } /*************************************************************************** * manipulacion de segnales. pone wait_flag a FALSE, para indicar al bucle * * anterior que los caracteres han sido recibidos * ***************************************************************************/ void signal_handler_IO (int status) { printf("recibida segnal SIGIO.\n"); wait_flag = FALSE; } 3.4. Espera de Entradas de Origen Múltiple. Esta sección está al mínimo. Sólo intenta ser un indicación, y por tanto el ejemplo de código es pequeño. Esto no sólo funcionará con puertos serie, sino que también lo hará con cualquier conjunto de descriptores de archivo. La llamada select y las macros asociadas usan un fd_set. Esto es una tabla de bits, que tiene una entrada de bit para cada número de descriptor de archivo válido. select aceptará un fd_set con los bits fijados para los descriptores de archivos relevantes y devuelve un fd_set, en el cual los bits para el descriptor del archivo están fijados donde ocurre una entrada, salida o excepción. Todas la manipulaciones de fd_set se llevan a cabo mediante las macros proporcionadas. Ver también la página del manual select(2). #include
#include
#include

main()
{
int fd1, fd2; /* origenes de entrada 1 y 2 */
fd_set readfs; /* descriptor de archivo */
int maxfd; /* mixmum file desciptor used */
int loop=1; /* bucle mientras TRUE */

/*
open_input_source abre un dispositivo, fija el puerto correctamente
y devuelve un descriptor de archivo
*/

fd1 = open_input_source(«/dev/ttyS1»); /* COM2 */
if (fd1<0) exit(0); fd2 = open_input_source("/dev/ttyS2"); /* COM3 */ if (fd2<0) exit(0); maxfd = MAX (fd1, fd2)+1; /* entrada maxima de bits (fd) a probar */ /* bucle para entrada */ while (loop) { FD_SET(fd1, &readfs); /* comprobacion origen 1 */ FD_SET(fd2, &readfs); /* comprobacion origen 2 */ /* bloqueo hasta que la entrada esta disponible */ select(maxfd, &readfs, NULL, NULL, NULL); if (FD_ISSET(fd1)) /* entrada de origen 1 esta disponible */ handle_input_from_source1(); if (FD_ISSET(fd2)) /* entrada de origen 2 esta disponible */ handle_input_from_source2(); } } El ejemplo dado bloquea indefinidamente hasta que una entrada de una de las fuentes está disponible. Si necesita un temporizador para la entrada, sólo sustituya la llamada select por: int res; struct timeval Timeout; /* fija el valor del temporizador en el bucle de entrada */ Timeout.tv_usec = 0; /* milisegundos */ Timeout.tv_sec = 1; /* segundos */ res = select(maxfd, &readfs, NULL, NULL, &Timeout); if (res==0) /* numero de descriptores de archivo con input = 0, temporizador sobrepasado */ Este ejemplo concluye el tiempo de espera tras un segundo. Si este tiempo transcurre, select devolverá 0, pero tenga cuidado porque Timeout se decrementa por el tiempo actualmente esperado para la entrada por select. Si el valor de retardo es cero, select volverá inmediatamente. 4. Otras fuentes de Información · El Linux Serie-COMO describe cómo configurar un puerto serie y contiene información sobre hardware. · Serial Programming Guide for POSIX Compliant Operating Systems, por Michael Sweet. · La página del manual termios(3) describe todos los parámetros de la estructura termios. 5. Contribuciones Como se mencionó en la introducción, no soy un experto en este campo, pero he tenido mis propios problemas, y encontré la solución con la ayuda de otras personas. Gracias por la ayuda de Mr. Strudthoff de European Transonic Windtunnel, Cologne, Michael Carter, mcarter@rocke.electro.swri.edu, y Peter Waltenberg, p.waltenberg@karaka.chch.cri.nz Antonino Ianella, antonino@usa.net escribió el Serial-Port-Programming Mini HOWTO, a la misma vez que yo preparaba este documento. Greg Hankins me pidió que incorporara el Mini-Howto de Antonino en este documento. La estructura de este documento y el formateo SGML provienen del Serial-HOWTO de Greg Hankins. 5.1. Traducción Este documento ha sido traducido por Pedro Pablo Fábrega Martínez, pfabrega@arrakis.es Si encontráis mejoras, añadidos o fallos, de cualquier tipo, indicádmelo para mejorar el documento. Insultos > /dev/null

6. Anexo: El INSFLUG

El INSFLUG forma parte del grupo internacional Linux Documentation
Project, encargándose de las traducciones al castellano de los Howtos
(Comos), así como la producción de documentos originales en aquellos
casos en los que no existe análogo en inglés.

En el INSFLUG se orienta preferentemente a la traducción de documentos
breves, como los COMOs y PUFs (Preguntas de Uso Frecuente, las FAQs.
:) ), etc.

Diríjase a la sede del INSFLUG para más información al respecto.

En la sede del INSFLUG encontrará siempre las últimas versiones de las
traducciones: www.insflug.org. Asegúrese de comprobar cuál es la
última versión disponible en el Insflug antes de bajar un documento de
un servidor réplica.

Se proporciona también una lista de los servidores réplica (mirror)
del Insflug más cercanos a Vd., e información relativa a otros
recursos en castellano.

Francisco José Montilla, pacopepe@insflug.org.

Los comentarios están cerrados.