/* Hey EMACS -*- linux-c -*- */ /* $Id: link_ser.c 4466 2012-08-21 15:13:55Z debrouxl $ */ /* libticables2 - link cable library, a part of the TiLP project * Copyright (C) 1999-2005 Romain Lievin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* "Home-made serial" link & "Black TIGraphLink" link unit (low-level I/O routines) */ #include #include "../ticables.h" #include "../logging.h" #include "../error.h" #include "../gettext.h" #include "detect.h" #include "ioports.h" #define com_out (h->address + 4) #define com_in (h->address + 6) #define hCom (HANDLE)(h->priv) #define BUFFER_SIZE 1024 static int ser_prepare(CableHandle *h) { switch(h->port) { case PORT_1: h->address = 0x3f8; h->device = strdup("COM1"); break; case PORT_2: h->address = 0x2f8; h->device = strdup("COM2"); break; case PORT_3: h->address = 0x3e8; h->device = strdup("COM3"); break; case PORT_4: h->address = 0x3e8; h->device = strdup("COM4"); break; default: return ERR_ILLEGAL_ARG; } //detect OS // if(win32_check_os() == WIN_NT) // { // if(win32_check_dha()) // { // free(h->device); h->device = NULL; // return ERR_DHA_NOT_FOUND; // } // } // else if(win32_check_os() == WIN_64) // { // if(win32_check_rwp()) // { // free(h->device); h->device = NULL; // return ERR_DHA_NOT_FOUND; // } // } return 0; } static int ser_reset(CableHandle *h); static int ser_open(CableHandle *h) { // Under Win2k: if we do not open the serial device as a COM // port, it may be impossible to transfer data. // This problem exists with Win2k and some UARTs. // It seems I got the same problem as FlashZ when I changed my // motherboard. Are some port broken ? HANDLE hcom; TRYC(win32_comport_open(h->device, &hcom)); h->priv = (void *)hcom; //TRYC(io_open(com_out)); //TRYC(io_open(com_in)); return 0; } static int ser_close(CableHandle *h) { //TRYC(io_close(com_out)); //TRYC(io_close(com_in)); // { // HANDLE hcom = hCom; // TRYC(win32_comport_close(&hcom)); // h->priv = (void *)hcom; // } if (hCom) { CloseHandle(hCom); h->priv = (void *)INVALID_HANDLE_VALUE; } return 0; } static int ser_reset(CableHandle *h) { tiTIME clk; // wait for releasing of lines TO_START(clk); do { win_serbb_put(hCom, 3); if (TO_ELAPSED(clk, h->timeout)) return 0; } while ((win_serbb_get(hCom) & 0x30) != 0x30); return 0; } static int ser_probe(CableHandle *h) { unsigned int timeout = 1; tiTIME clk; // 1 win_serbb_put(hCom, 2); TO_START(clk); do { if (TO_ELAPSED(clk, timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x10)); win_serbb_put(hCom, 3); TO_START(clk); do { if (TO_ELAPSED(clk, timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x10) == 0x00); // 0 win_serbb_put(hCom, 1); TO_START(clk); do { if (TO_ELAPSED(clk, timeout)) return ERR_WRITE_TIMEOUT; } while (win_serbb_get(hCom) & 0x20); win_serbb_put(hCom, 3); TO_START(clk); do { if (TO_ELAPSED(clk, timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x20) == 0x00); return 0; } static int ser_put(CableHandle *h, uint8_t *data, uint32_t len) { int bit; unsigned int i; unsigned int j; tiTIME clk; for(j = 0; j < len; j++) { uint8_t byte = data[j]; for (bit = 0; bit < 8; bit++) { if (byte & 1) { win_serbb_put(hCom, 2); TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x10)); win_serbb_put(hCom, 3); TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x10) == 0x00); } else { win_serbb_put(hCom, 1); TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_WRITE_TIMEOUT; } while (win_serbb_get(hCom) & 0x20); win_serbb_put(hCom, 3); TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_WRITE_TIMEOUT; } while ((win_serbb_get(hCom) & 0x20) == 0x00); } byte >>= 1; //for (i = 0; i < h->delay; i++) win_serbb_get(hCom); } } return 0; } static int ser_get(CableHandle *h, uint8_t *data, uint32_t len) { int bit; unsigned int i; unsigned int j; tiTIME clk; for(j = 0; j < len; j++) { uint8_t v, byte = 0; for (bit = 0; bit < 8; bit++) { TO_START(clk); while ((v = win_serbb_get(hCom) & 0x30) == 0x30) { if (TO_ELAPSED(clk, h->timeout)) return ERR_READ_TIMEOUT; } if (v == 0x10) { byte = (byte >> 1) | 0x80; win_serbb_put(hCom, 1); TO_START(clk); while ((win_serbb_get(hCom) & 0x20) == 0x00) { if (TO_ELAPSED(clk, h->timeout)) return ERR_READ_TIMEOUT; } win_serbb_put(hCom, 3); } else { byte = (byte >> 1) & 0x7F; win_serbb_put(hCom, 2); TO_START(clk); while ((win_serbb_get(hCom) & 0x10) == 0x00) { if (TO_ELAPSED(clk, h->timeout)) return ERR_READ_TIMEOUT; } win_serbb_put(hCom, 3); } //for (i = 0; i < h->delay; i++) win_serbb_get(hCom); } data[j] = byte; } return 0; } static int ser_check(CableHandle *h, int *status) { *status = STATUS_NONE; if (!((win_serbb_get(hCom) & 0x30) == 0x30)) *status = STATUS_RX; return 0; } #define swap_bits(a) (((a&2)>>1) | ((a&1)<<1)) // swap the 2 lowest bits static int ser_set_red_wire(CableHandle *h, int b) { int v = swap_bits(win_serbb_get(hCom) >> 4); if (b) win_serbb_put(hCom, v | 0x02); else win_serbb_put(hCom, v & ~0x02); return 0; } static int ser_set_white_wire(CableHandle *h, int b) { int v = swap_bits(win_serbb_get(hCom) >> 4); if (b) win_serbb_put(hCom, v | 0x01); else win_serbb_put(hCom, v & ~0x01); return 0; } static int ser_get_red_wire(CableHandle *h) { return ((0x10 & win_serbb_get(hCom)) ? 1 : 0); } static int ser_get_white_wire(CableHandle *h) { return ((0x20 & win_serbb_get(hCom)) ? 1 : 0); } static int ser_set_raw(CableHandle *h, int state) { win_serbb_put(hCom, swap_bits(state)); return 0; } static int ser_get_raw(CableHandle *h, int *state) { *state = (win_serbb_get(hCom) >> 4) & 3; return 0; } const CableFncts cable_ser = { CABLE_BLK, "BLK", N_("BlackLink"), N_("BlackLink or home-made serial cable"), !0, &ser_prepare, &ser_open, &ser_close, &ser_reset, &ser_probe, NULL, &ser_put, &ser_get, &ser_check, &ser_set_red_wire, &ser_set_white_wire, &ser_get_red_wire, &ser_get_white_wire, &ser_set_raw, &ser_get_raw };