00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "jed_defs.h"
00023
00024 #include <stdio.h>
00025 #include <string.h>
00026
00027 #include "toolkits/media/jed_serial.h"
00028
00029 #ifdef SERIALPORT_ENABLED
00030 #include "toolkits/media/_unix_io.h"
00031 #endif
00032
00033
00034
00035
00036
00037 PUERTO_SERIAL::PUERTO_SERIAL(char *cad,
00038 const int v, const int p, const int s,
00039 const int d, const int f)
00040 {
00041 #if PLATAFORMA == i386_WIN32_VC
00042 com_fd = 0;
00043 #endif
00044 #ifdef UNIX_ENABLED
00045 com_fd = 0;
00046 #endif
00047 abierto = FALSE;
00048
00049 strcpy(nombre_puerto, cad);
00050 velocidad = PSV9600;
00051 paridad = PSP_NONE;
00052 stop_bits = PSS_UNO;
00053 data_bits = PSD8;
00054 flujo = PSF_NONE;
00055
00056 configurar(v, p, s, d, f);
00057 }
00058
00059 PUERTO_SERIAL::~PUERTO_SERIAL()
00060 {
00061 cerrar();
00062 }
00063
00064 void
00065 PUERTO_SERIAL::consultar(int &v, int &p, int &s, int &d, int &f)
00066
00067
00068
00069 {
00070 v = velocidad;
00071 p = paridad;
00072 s = stop_bits;
00073 d = data_bits;
00074 f = flujo;
00075 }
00076
00077 BOOLEAN
00078 PUERTO_SERIAL::configurar(const int v, const int p, const int s,
00079 const int d, const int f)
00080
00081
00082
00083 {
00084 int old_v, old_p, old_s, old_d, old_f;
00085
00086 old_v = velocidad;
00087 old_p = paridad;
00088 old_s = stop_bits;
00089 old_d = data_bits;
00090 old_f = flujo;
00091
00092 velocidad = v;
00093 paridad = p;
00094 stop_bits = s;
00095 data_bits = d;
00096 flujo = f;
00097
00098 if ( abierto && !active_configuracion() ) {
00099 fprintf(stderr, "<PUERTO_SERIAL> Warning: No se ha logrado establecer "
00100 "la nueva configuracion!\n");
00101 fflush(stderr);
00102 velocidad = old_v;
00103 paridad = old_p;
00104 stop_bits = old_s;
00105 data_bits = old_d;
00106 flujo = old_f;
00107 }
00108
00109 return TRUE;
00110 }
00111
00112 BOOLEAN
00113 PUERTO_SERIAL::active_configuracion(void)
00114 {
00115 #ifndef SERIALPORT_ENABLED
00116 return FALSE;
00117 #endif
00118
00119 #ifdef SERIALPORT_ENABLED
00120
00121 #if PLATAFORMA == i386_WIN32_VC
00122 DCB conf;
00123
00124
00125 if ( !GetCommState(com_fd, &conf) ) {
00126 fprintf(stderr,
00127 "<SERIAL> - Error: no se puede leer la configuracion de %s.\n",
00128 nombre_puerto);
00129 fflush(stderr);
00130 return FALSE;
00131 }
00132 switch ( velocidad ) {
00133 case PSV110: conf.BaudRate = CBR_110; break;
00134 case PSV300: conf.BaudRate = CBR_300; break;
00135 case PSV600: conf.BaudRate = CBR_600; break;
00136 case PSV1200: conf.BaudRate = CBR_1200; break;
00137 case PSV2400: conf.BaudRate = CBR_2400; break;
00138 case PSV4800: conf.BaudRate = CBR_4800; break;
00139 case PSV9600: conf.BaudRate = CBR_9600; break;
00140 case PSV14400: conf.BaudRate = CBR_14400; break;
00141 case PSV19200: conf.BaudRate = CBR_19200; break;
00142 case PSV38400: conf.BaudRate = CBR_38400; break;
00143 case PSV56000: conf.BaudRate = CBR_56000; break;
00144 case PSV57600: conf.BaudRate = CBR_57600; break;
00145 case PSV115200: conf.BaudRate = CBR_115200; break;
00146 case PSV128000: conf.BaudRate = CBR_128000; break;
00147 case PSV256000: conf.BaudRate = CBR_256000; break;
00148 default: return FALSE;
00149 }
00150 conf.fBinary = TRUE;
00151 if ( paridad == PSP_NONE ) {
00152 conf.fParity = FALSE;
00153 }
00154 else {
00155 conf.fParity = TRUE;
00156 }
00157 if ( flujo == PSF_HARDWARE ) {
00158 conf.fOutX = TRUE;
00159 conf.fInX = TRUE;
00160 }
00161 else {
00162 conf.fOutX = FALSE;
00163 conf.fInX = FALSE;
00164 }
00165 conf.fNull = FALSE;
00166 if ( flujo == PSF_SOFTWARE ) {
00167 conf.fRtsControl = RTS_CONTROL_ENABLE;
00168 }
00169 else {
00170 conf.fRtsControl = RTS_CONTROL_DISABLE;
00171 }
00172 conf.fAbortOnError = FALSE;
00173 switch ( paridad ) {
00174 case PSP_NONE: conf.Parity = NOPARITY; break;
00175 case PSP_EVEN: conf.Parity = EVENPARITY; break;
00176 case PSP_ODD: conf.Parity = ODDPARITY; break;
00177 case PSP_MARK: conf.Parity = MARKPARITY; break;
00178 case PSP_SPACE: conf.Parity = SPACEPARITY; break;
00179 default: return FALSE;
00180 }
00181 switch ( stop_bits ) {
00182 case PSS_UNO: conf.StopBits = ONESTOPBIT; break;
00183 case PSS_DOS: conf.StopBits = TWOSTOPBITS; break;
00184 case PSS_UNO_Y_MEDIO: conf.StopBits = ONE5STOPBITS; break;
00185 default: return FALSE;
00186 }
00187 conf.ByteSize = (BYTE)data_bits;
00188
00189
00190 if ( !SetCommState(com_fd, &conf) ) {
00191 fprintf(stderr,
00192 "<SERIAL> - Error: no se puede grabar la nueva configuracion a %s.\n",
00193 nombre_puerto);
00194 fflush(stderr);
00195 return FALSE;
00196 }
00197 COMMTIMEOUTS to_conf;
00198
00199 to_conf.ReadIntervalTimeout = 1000;
00200 to_conf.ReadTotalTimeoutMultiplier = 300;
00201 to_conf.ReadTotalTimeoutConstant = 300;
00202 to_conf.WriteTotalTimeoutMultiplier = 300;
00203 to_conf.WriteTotalTimeoutConstant = 300;
00204
00205 if ( !SetCommTimeouts(com_fd, &to_conf) ) {
00206 fprintf(stderr, "<SERIAL> - Error: no se pudo especificar el timeout!\n");
00207 fflush(stderr);
00208 return FALSE;
00209 }
00210 return TRUE;
00211 #endif
00212
00213 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == ALPHA || PLATAFORMA == SPARC64_LINUX_GCC
00214 struct termio serial_data = {
00215 0, 0, CS8|CREAD|CLOCAL, 0, 0, {0, 0, 0, 0, 1, 100, 0, 0}
00216 };
00217
00218 switch ( velocidad ) {
00219 case PSV110: serial_data.c_cflag |= B110; break;
00220 case PSV300: serial_data.c_cflag |= B300; break;
00221 case PSV1200: serial_data.c_cflag |= B1200; break;
00222 case PSV2400: serial_data.c_cflag |= B2400; break;
00223 case PSV4800: serial_data.c_cflag |= B4800; break;
00224 case PSV9600: serial_data.c_cflag |= B9600; break;
00225 case PSV19200:
00226 serial_data.c_cflag |= B19200;
00227 serial_data.c_cc[VMIN]=0;
00228 serial_data.c_cc[VTIME]=20;
00229 break;
00230 case PSV38400: serial_data.c_cflag |= B38400; break;
00231 default: return FALSE;
00232 }
00233
00234 ioctl((int)com_fd, (int)TCSETA, &serial_data);
00235 ioctl(com_fd, TIOCNOTTY);
00236 SLEEP_MICROSEC(2000);
00237 return TRUE;
00238 #endif
00239
00240 #if (PLATAFORMA == SGI) || (PLATAFORMA == SUN) || (PLATAFORMA == CRAY_J90) || (PLATAFORMA == CYGNUS_WIN32) || (PLATAFORMA == POWERPC_AIX_VACPP)
00241 return FALSE;
00242 #endif
00243
00244 #endif // SERIALPORT_ENABLED
00245 }
00246
00247 BOOLEAN
00248 PUERTO_SERIAL::abrir(void)
00251 {
00252
00253 if ( abierto ) {
00254 cerrar();
00255 }
00256
00257 #ifndef SERIALPORT_ENABLED
00258 fprintf(stderr,
00259 "<PUERTO_SERIAL> AQUYNZA no soporta puertos seriales en esta plataforma.\n"
00260 );
00261 #if PLATAFORMA == CRAY_J90
00262 fprintf(stderr,
00263 " Tenga en cuenta, que al menos para el conocimiento de los\n"
00264 " autores AQUYNZA, los supercomputadores CRAY no poseen\n"
00265 " puertos seriales RS232 o algo parecido.\n"
00266 );
00267 #endif
00268 #if PLATAFORMA == SGI
00269 fprintf(stderr,
00270 " Es sabido que algunas maquinas Silicon Graphics poseen\n"
00271 " puertos seriales RS232 o similares, y tambien que se\n"
00272 " tiene un API de programacion de los mismos en delta C++.\n"
00273 " Sin embargo, por no tener maquinas disponibles, esto no ha\n"
00274 " sido desarrollado ni implementado en aquynza.\n"
00275 " Se invita a quien lo necesesite a implementar esto.\n"
00276 );
00277 #endif
00278 fflush(stderr);
00279 return FALSE;
00280 #endif
00281
00282 #ifdef SERIALPORT_ENABLED
00283
00284
00285 #if PLATAFORMA == i386_WIN32_VC
00286 DWORD code;
00287
00288 com_fd = CreateFile(nombre_puerto, GENERIC_READ | GENERIC_WRITE,
00289 0,
00290 NULL,
00291 OPEN_EXISTING,
00292 FILE_ATTRIBUTE_NORMAL |
00293 FILE_FLAG_OVERLAPPED,
00294 NULL );
00295
00296 code = GetLastError();
00297
00298 if ( code == ERROR_FILE_NOT_FOUND ){
00299 fprintf(stderr, "ERROR_FILE_NOT_FOUND. \n", nombre_puerto);
00300 fflush(stderr);
00301 com_fd = 0;
00302 return FALSE;
00303 }
00304
00305 if ( com_fd == INVALID_HANDLE_VALUE) {
00306 fprintf(stderr, "INVALID_HANDLE. \n", nombre_puerto);
00307 fflush(stderr);
00308 com_fd = 0;
00309 return FALSE;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 #endif
00321
00322 #ifdef UNIX_ENABLED
00323
00324
00325
00326
00327 com_fd = open(nombre_puerto, O_RDWR | O_NONBLOCK);
00328
00329 if ( com_fd < 0 ) {
00330 fprintf(stderr, "<PUERTO_SERIAL> ERROR: No puedo abrir el puerto "
00331 "\"%s\". \n", nombre_puerto);
00332 fflush(stderr);
00333 return FALSE;
00334 }
00335 #endif
00336
00337
00338 if ( !active_configuracion() ) {
00339 fprintf(stderr, "<PUERTO_SERIAL> ERROR:\nEl puerto se abrio, pero no "
00340 "permitio activar la configuracion actual!\n");
00341 fflush(stderr);
00342 cerrar();
00343 return FALSE;
00344 }
00345 abierto = TRUE;
00346
00347 return TRUE;
00348 #endif // SERIALPORT_ENABLED
00349 }
00350
00351 #ifdef SERIALPORT_ENABLED
00352 #ifdef UNIX_ENABLED
00353 BOOLEAN
00354 PUERTO_SERIAL::abrir_asincronico(void)
00357 {
00358 com_fd = open(nombre_puerto, O_RDWR | O_NOCTTY | O_NONBLOCK);
00359 if ( com_fd < 0 ) {
00360 fprintf(stderr, "<PUERTO_SERIAL> ERROR: No puedo abrir el puerto "
00361 "\"%s\". \n", nombre_puerto);
00362 fflush(stderr);
00363 return FALSE;
00364 }
00365
00366
00367 if ( !active_configuracion() ) {
00368 fprintf(stderr, "<PUERTO_SERIAL> ERROR: El puerto se abrio, pero no "
00369 "permitio activar la configuracion actual!\n");
00370 fflush(stderr);
00371 cerrar();
00372 return FALSE;
00373 }
00374 abierto = TRUE;
00375 return TRUE;
00376 }
00377 #endif
00378 #endif
00379
00380 void
00381 PUERTO_SERIAL::cerrar(void)
00382 {
00383 #ifdef SERIALPORT_ENABLED
00384 #if PLATAFORMA == i386_WIN32_VC
00385 if ( abierto ) {
00386 if ( !CloseHandle(com_fd) ) {
00387 fprintf(stderr,
00388 "<SERIAL> - Warning: ha fallado el cierre del puerto %s.\n",
00389 nombre_puerto);
00390 fflush(stderr);
00391 }
00392 abierto = FALSE;
00393 }
00394 #endif
00395
00396 #ifdef UNIX_ENABLED
00397 if ( abierto ) {
00398 close(com_fd);
00399 abierto = FALSE;
00400 }
00401 #endif
00402 #endif
00403
00404 }
00405
00406 #ifndef SERIALPORT_ENABLED
00407 BOOLEAN
00408 PUERTO_SERIAL::escribir(char * , int )
00413 {
00414 return FALSE;
00415 }
00416 #endif // !SERIALPORT_ENABLED
00417
00418
00419 #ifdef SERIALPORT_ENABLED
00420 BOOLEAN
00421 PUERTO_SERIAL::escribir(char *buffer, int tam_buffer)
00425 {
00426 #if PLATAFORMA == i386_WIN32_VC
00427 BOOL status;
00428 DWORD be;
00429
00430 status = WriteFile(com_fd, (LPCVOID)buffer, (DWORD)tam_buffer, &be, NULL);
00431
00432 if ( status ) {
00433 return TRUE;
00434 }
00435 else {
00436 fprintf(stderr, "<SERIAL> - ERROR: Escribiendo datos!\n");
00437 fflush(stderr);
00438 return FALSE;
00439 }
00440 #endif
00441
00442 #ifdef UNIX_ENABLED
00443 int enviados;
00444
00445 enviados = write(com_fd, buffer, tam_buffer);
00446 fsync(com_fd);
00447 if ( enviados != tam_buffer ) {
00448 return FALSE;
00449 }
00450 return TRUE;
00451 #endif
00452 }
00453 #endif // SERIALPORT_ENABLED
00454
00455 #ifndef SERIALPORT_ENABLED
00456 int
00457 PUERTO_SERIAL::leer(char * , int )
00462 {
00463 return FALSE;
00464 }
00465 #endif
00466
00467 #ifdef SERIALPORT_ENABLED
00468 int
00469 PUERTO_SERIAL::leer(char *buffer, int tam_buffer)
00476 {
00477 #if PLATAFORMA == i386_WIN32_VC
00478 BOOL status;
00479 DWORD be;
00480
00481 status = ReadFile(com_fd, (LPVOID)buffer, (DWORD)tam_buffer, &be, NULL);
00482 printf("<SERIAL> Recibo datos de longitud %d!\n", be);
00483 fflush(stdout);
00484
00485 if ( status ) {
00486 return (int)be;
00487 }
00488 else {
00489 fprintf(stderr, "<SERIAL> - ERROR: Leyendo datos!\n");
00490 fflush(stderr);
00491 return 0;
00492 }
00493 #endif
00494
00495 #ifdef UNIX_ENABLED
00496 return read(com_fd, buffer, tam_buffer);
00497 #endif
00498
00499
00500
00501 #ifdef NONONO
00502 long intentos_fallidos = 0;
00503 int faltan = tam_buffer;
00504 int caracteres_leidos;
00505
00506 while ( faltan > 0 ) {
00507 caracteres_leidos = read(com_fd, &buffer[tam_buffer-faltan], faltan);
00508 if ( caracteres_leidos != -1 ) {
00509 faltan -= caracteres_leidos;
00510 }
00511 else {
00512 if ( intentos_fallidos++ > MAX_RETRIES ) {
00513 return -(tam_buffer-faltan);
00514 }
00515 }
00516 }
00517 return tam_buffer;
00518 #endif
00519 }
00520 #endif // SERIALPORT_ENABLED
00521
00522 #if PLATAFORMA == i386_WIN32_VC
00523
00524 LONG WINAPI
00525 receptor_eventos_serial(HWND w, UINT tipo_mensaje, UINT uParam, LONG lParam)
00532 {
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 printf("."); fflush(stdout);
00545 return DefWindowProc(w, tipo_mensaje, uParam, lParam);
00546 }
00547
00548 HWND
00549 PUERTO_SERIAL::instalar_sistema_asincronico_serial(void)
00550 {
00551 static int lista = 0;
00552 static HWND receptora = NULL;
00553
00554
00555 if ( lista ) return receptora;
00556
00557
00558
00559
00560 WNDCLASS atributos_de_ventana = {
00561 CS_GLOBALCLASS,
00562 (WNDPROC)receptor_eventos_serial,
00563 0,
00564 0,
00565 0,
00566 NULL,
00567 NULL,
00568 NULL,
00569 "",
00570 "AQUYNZA_Serial_event_handler"
00571 };
00572
00573 if ( !RegisterClass(&atributos_de_ventana) ) {
00574 fprintf(stderr, "ERROR: No puedo crear la clase!\n");
00575 fflush(stdout);
00576 return NULL;
00577 }
00578
00579
00580 receptora = CreateWindowEx(
00581 WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT,
00582
00583 "AQUYNZA_Serial_event_handler",
00584 "AQUYNZA Serial event handler",
00585 WS_ICONIC |
00586 WS_CAPTION | WS_MINIMIZEBOX |WS_MAXIMIZEBOX |
00587 WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
00588 0, 0, 10, 10,
00589 NULL,
00590 NULL,
00591 0,
00592 (LPVOID)NULL
00593 );
00594
00595 if ( !receptora ) {
00596 fprintf(stderr,
00597 "ERROR: No pudo crearse la ventana receptora de eventos!\n");
00598 fflush(stderr);
00599 }
00600
00601 lista = 1;
00602 ShowWindow(receptora, SW_SHOWDEFAULT);
00603 return receptora;
00604 }
00605
00606 #endif
00607
00608 #ifndef SERIALPORT_ENABLED
00609 void
00610 PUERTO_SERIAL::registro_asincronico(
00611 void (* )(void *, int), void *
00612 )
00613 {
00614 ;
00615 }
00616 #endif // !SERIALPORT_ENABLED
00617
00618 #ifdef SERIALPORT_ENABLED
00619 void
00620 PUERTO_SERIAL::registro_asincronico(
00621 #ifdef UNIX_ENABLED
00622 void (*f)(void *, int), void *User_data
00623 #endif
00624 #if PLATAFORMA == i386_WIN32_VC
00625 void (* )(void *, int), void *
00626 #endif
00627 )
00634 {
00635 #ifdef UNIX_ENABLED
00636 instalar_sistema_asincronico();
00637
00638
00639 registrar_entrada(com_fd, f, User_data);
00640 printf("Registro COM asincronico para %s en fd %d\n",
00641 nombre_puerto, com_fd);
00642 fflush(stdout);
00643 #endif
00644 #if PLATAFORMA == i386_WIN32_VC
00645 instalar_sistema_asincronico_serial();
00646
00647 MSG msg;
00648
00649 OVERLAPPED o;
00650 DWORD cosas;
00651
00652 o.Offset = 0;
00653 o.OffsetHigh = 0;
00654 o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00655
00656 SetCommMask(com_fd, EV_RXCHAR);
00657
00658
00659 for ( ;; ) {
00660 if (WaitCommEvent(com_fd, &cosas, &o) ) {
00661 printf("Ay ombe' wepaje!\n"); fflush(stdout);
00662 }
00663
00664 if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
00665 if ( msg.message == WM_QUIT ) break;
00666 TranslateMessage (&msg);
00667 DispatchMessage (&msg);
00668 }
00669 }
00670
00671 #endif
00672 }
00673 #endif // SERIALPORT_ENABLED
00674
00675
00676
00677
00678