#include #include "lantronix.h" #define NOT_FOUND ((unsigned short)-1) int debug = 0; int lx_error = LX_ERROR_NO_ERROR; unsigned char read_queue[NQUEUE][QUEUELEN]; size_t queue_len[NQUEUE] = {0}; struct commstr { __u16 _dummy; __u16 len; __u32 acc; __u32 sid; __u8 code; __u8 d0B; __u16 datalen; __u16 d0E; __u16 d10; __u16 d12; __u16 d14; __u32 did; __u32 d1A; __u16 d1E; __u16 d20; __u8 data[]; }; struct devinfo { __u16 len; __u16 type; __u16 vid; __u16 pid; __u32 port; char client[0x40]; char name1[0x20]; __u8 ip[4]; __u16 d70; __u8 d72; __u8 d73; __u8 d74[4]; __u8 d78[4]; __u8 d7C[2]; __u16 d7E; __u8 d80[0x18]; char sn[0x20]; __u16 dB8; char name2[0x20]; __u16 dDA; }; struct cliinfo { __u16 len; __u16 type; char name[0x60]; __u8 ip[4]; __u8 d68[6]; char d6E[0x20]; }; struct udppacket { __u32 sn; __u32 firm_ver; __u32 firm_rev; __u8 code1; __u8 code2; __u16 tcp_port; __u16 d10; __u16 d12; __u16 d14; __u16 ord; __u32 d18; __u16 vid; __u16 pid; __u32 usb_port; }; int sock = 0; struct commstr *salloc = NULL; void freeall() { /* pro atexit() */ if(salloc) free(salloc); salloc = NULL; if(sock) close(sock); sock = 0; } int initsock(char *ip) { struct hostent *host; struct sockaddr_in sin; int s; if((host = gethostbyname((void*)ip)) == NULL) return -1; if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) return -1; sin.sin_family = AF_INET; sin.sin_port = htons(10010); memcpy(&(sin.sin_addr), host->h_addr, host->h_length); if((connect(s, (struct sockaddr*)&sin, sizeof(sin))) == -1) return -1; return s; } void setupstr(struct commstr *str, unsigned char code, unsigned acc, unsigned short d0E, unsigned short d10, unsigned short d12, unsigned short datalen) { memset(str, 0, sizeof(struct commstr)); str->code = code; str->acc = htonl(acc); str->d0E = htons(d0E); str->d10 = htons(d10); str->d12 = htons(d12); str->datalen = htons(datalen); str->len = htons(datalen + 32); memset(str->data, 0, datalen); } void sendstr(struct commstr *str) { unsigned char *stream = (unsigned char*)str + 2; if(debug > 1) { int i; for(i = 0; i < 34 + ntohs(str->datalen); i++) printf("%02X ", (int)(stream[i])); puts(""); } if(send(sock, (void*)stream, 34 + ntohs(str->datalen), 0) < 0) exit(RETVAL_SEND); } void sendsimple(unsigned char code, unsigned acc, unsigned short d0E, unsigned short d10, unsigned short d12) { setupstr(salloc, code, acc, d0E, d10, d12, 0); sendstr(salloc); } void sendpacket_va(unsigned char code, unsigned acc, unsigned short d0E, unsigned short d10, unsigned short d12, unsigned short datalen, va_list ap) { int i; setupstr(salloc, code, acc, d0E, d10, d12, datalen); for(i = 0; i < datalen; i++) salloc->data[i] = (unsigned char)va_arg(ap, unsigned); sendstr(salloc); } void sendpacket(unsigned char code, unsigned acc, unsigned short d0E, unsigned short d10, unsigned short d12, unsigned short datalen, ...) { va_list ap; if(datalen) { va_start(ap, datalen); sendpacket_va(code, acc, d0E, d10, d12, datalen, ap); va_end(ap); } else { sendsimple(code, acc, d0E, d10, d12); } } void sendconfig(unsigned acc, unsigned short datalen, ...) { va_list ap; va_start(ap, datalen); sendpacket_va(0x41, acc, 1,0,0, datalen, ap); va_end(ap); free(waitpacket(0x51)); } struct commstr *readpacket(int sock) { int r, len, o; struct commstr *str; unsigned char *buf; unsigned short prebuf; r = recv(sock, &prebuf, 2, 0); if(r <= 0) exit(RETVAL_RECV); len = ntohs(prebuf)+2; o = 2; str = malloc(len+2); /* Nezapomente uvolnit! */ if(!str) exit(RETVAL_MALLOC); buf = (unsigned char*)str + 2; memcpy(buf, &prebuf, 2); do { r = recv(sock, buf+o, len-o, 0); if(r <= 0) { free(str); exit(RETVAL_RECV); } else o += r; } while(o < len); if(debug > 1) { int i; for(i = 0; i < len; i++) { printf("%02X ", (int)(buf[i])); if(i == 1000) puts(""); } puts(""); } return str; } void dispatch(struct commstr *str) { struct devinfo *di; struct cliinfo *ci; struct udppacket *udp; int off, q; switch(str->code) { case 0x57: case 0x12: case 0x15: /* ignore */ break; case 0x52: if(str->d12 == 0x0) { q = ntohl(str->acc); if(queue_len[q] + ntohs(str->datalen) > QUEUELEN) exit(RETVAL_QUEUE); memcpy(read_queue[q]+queue_len[q], str->data, ntohs(str->datalen)); queue_len[q] += ntohs(str->datalen); } break; case 0x18: if(debug) { printf("\n=== 0x18 ===\nPočet zařízení: %i\nPočet klientů: %i\n", ntohs(str->d0E), ntohs(str->d10)); for(off = 0; ; off += ntohs(*(unsigned short*)(str->data+off))) { switch(str->data[off+2]) { case 0x04: di = (struct devinfo*)(str->data+off); printf("port %i: %04X/%04X %s\t%s", ntohl(di->port)-1, ntohs(di->vid), ntohs(di->pid), di->name1, di->sn); if(di->ip[0]) printf(" [%i.%i.%i.%i %s]", di->ip[0], di->ip[1], di->ip[2], di->ip[3], di->client); printf("\n"); break; case 0x05: ci = (struct cliinfo*)(str->data+off); printf("%s\t%i.%i.%i.%i\n", ci->name, ci->ip[0], ci->ip[1], ci->ip[2], ci->ip[3]); break; case 0x00: break; } if(str->data[off+2] == 0x00) { off += 4; break; } } printf("\n"); } break; case 0x61: udp = (struct udppacket*)(str->data); if(debug) { printf("\n=== 0x61: %02X%02X ===\n", udp->code1, udp->code2); switch(udp->code1) { case 0x01: if(udp->d14 == 0) sendsimple(0x05, 0,0,0,0); else puts("Zbytečnost"); break; case 0x02: case 0x03: printf("Zařízení %04X/%04X na portu %i: požadavek na %s\n", ntohs(udp->vid), ntohs(udp->pid), ntohl(udp->usb_port), udp->code1==2 ? "aktivaci":"deaktivaci"); break; case 0x06: printf("Zařízení %04X/%04X na portu %i ", ntohs(udp->vid), ntohs(udp->pid), ntohl(udp->usb_port)); switch(udp->code2) { case 0x00: if(udp->d10) puts("připojeno"); else puts("odpojeno"); break; case 0x01: puts("připraveno"); break; case 0x02: puts("aktivováno"); } break; } } break; default: if(debug) printf("\n=== 0x%02X ===\n", str->code); break; } free(str); } struct commstr *waitpacket(unsigned char code) { struct commstr *ret; time_t b = time(NULL); for(ret = readpacket(sock); ret->code != code; ret = readpacket(sock)) { dispatch(ret); if(time(NULL)-b > MAXWAIT) exit(RETVAL_WAIT); } return ret; } struct commstr *waitpacket61(unsigned short code) { struct commstr *ret; struct udppacket *udp; time_t b = time(NULL); for(;;) { for(ret = readpacket(sock); ret->code != 0x61; ret = readpacket(sock)) dispatch(ret); udp = (struct udppacket*)(ret->data); if(256 * udp->code1 + udp->code2 == code) break; dispatch(ret); if(time(NULL)-b > MAXWAIT) exit(RETVAL_WAIT); } return ret; } struct commstr *waitpacket_sid(unsigned sid) { struct commstr *ret; time_t b = time(NULL); for(ret = readpacket(sock); ntohl(ret->sid) != sid; ret = readpacket(sock)) { dispatch(ret); if(time(NULL)-b > MAXWAIT) exit(RETVAL_WAIT); } return ret; } int write_lx(unsigned acc, void *buf, size_t count) { struct commstr *ret; setupstr(salloc, 0x43, acc, 1,count,1, count); memcpy(salloc->data, buf, count); salloc->sid = htonl(1); sendstr(salloc); ret = waitpacket_sid(1); if((int)ntohl(ret->did) < 0) exit(RETVAL_WRITE); dispatch(ret); return ntohs(ret->d12); } int read_lx(unsigned acc, void *buf, size_t count) { size_t len; while(!queue_len[acc]) dispatch(waitpacket(0x52)); len = MIN(queue_len[acc], count); memcpy(buf, read_queue[acc], len); queue_len[acc] -= len; memmove(read_queue[acc], read_queue[acc]+len, queue_len[acc]); sendsimple(0x42, acc, 1,0x1000,0); return len; } unsigned short finddev_lx(int addr) { struct commstr *ret; struct devinfo *di; unsigned short ord; int off, ex = 0; sendsimple(0x08, 0, 2,3,0); ret = waitpacket(0x18); ord = 0; for(off = 0; ; off += ntohs(*(unsigned short*)(ret->data+off))) { switch(ret->data[off+2]) { case 0x04: di = (struct devinfo*)(ret->data+off); if(ntohl(di->port) == addr+1) { if(debug) { printf("finddev - port %i: %04X/%04X %s\t%s", ntohl(di->port), ntohs(di->vid), ntohs(di->pid), di->name1, di->sn); if(di->ip[0]) printf(" [%i.%i.%i.%i %s]", di->ip[0], di->ip[1], di->ip[2], di->ip[3], di->client); printf("\n"); } ex = 1; break; } ord++; break; case 0x00: if(debug) { printf("finddev: na portu %i neni pripojeno zadne zarizeni!\n", addr); } ord = NOT_FOUND; ex = 1; break; } if(ex) break; } free(ret); return ord; } int opendev_lx(int addr, int *acc) { struct commstr *ret; struct udppacket *udp; unsigned short ord, port, vid, pid; lx_error = LX_ERROR_NO_ERROR; if(!acc) { lx_error = LX_ERROR_MEMORY; return 0; } if(!salloc) { salloc = malloc(sizeof(struct commstr) + MAXDATA); if(!salloc) { lx_error = LX_ERROR_MEMORY; return 0; } } if(!sock) { sock = initsock(LX_ADDRESS/*"10.3.4.72"*/); if(sock == -1) { lx_error = LX_ERROR_NETWORK; return 0; } atexit(freeall); } setupstr(salloc, 0x01, 0, 2,1,0, 1+strlen(ID_COMPUTER)/*6*/); salloc->did = htonl(LX_SERIAL/*0xA38A13A2*/); strcpy((char*)salloc->data, ID_COMPUTER/*"VASEK"*/); sendstr(salloc); free(waitpacket(0x11)); ord = finddev_lx(addr); if(ord == NOT_FOUND) { lx_error = LX_ERROR_NOT_FOUND; return 0; } if(debug) printf("Aktivuji zařízení s pořadím %i\n", ord); sendsimple(0x09, 0, ord,0,0); for(;;) { for(ret = readpacket(sock); ret->code != 0x19 && ret->code != 0x61; ret = readpacket(sock)) dispatch(ret); if(ret->code == 0x19) break; udp = (struct udppacket*)(ret->data); if(udp->code1 == 0x02 && udp->code2 == 0x02) { vid = ntohs(udp->vid); pid = ntohs(udp->pid); port = ntohl(udp->usb_port); } dispatch(ret); } if(ret->did == 0) { if(debug) printf("Aktivace proběhla úspěšně.\n"); } else { fprintf(stderr, "Aktivace se nezdařila, chybový kód: %i.\n", (int)(ntohl(ret->did))); free(ret); lx_error = LX_ERROR_ACTIVATE; return 0; } free(ret); setupstr(salloc, 0x02, 0, vid, pid, 0, 0); salloc->did = htonl(port); sendstr(salloc); ret = waitpacket(0x12); *acc = ntohl(ret->acc); if(debug) printf(" ord = %i: acc = %i\n", ord, *acc); free(ret); sendsimple(0x08, 0, 2,3,0); dispatch(waitpacket(0x18)); if(debug) printf("Nastavuji parametry RS232\n"); sendconfig(*acc, 8, 0x41,0x11,0,0,0,0,0,0); /* Reset */ sendconfig(*acc, 8, 0x41,0,0x01,0,0,0,0,0); /* UART enable */ sendconfig(*acc, 24, 0x41,0x13,0,0,0,0,0x10,0,0x01,0,0,0,0x40,0,0,0,0,0,0,0,0,0,0,0); /* "set flow" */ sendconfig(*acc, 8, 0xC1,0x0F,0,0,0,0,0x40,0x02); /* "get props" */ sendconfig(*acc, 8, 0xC1,0x08,0,0,0,0,0x01,0); /* "get mdmsts" */ sendconfig(*acc, 8, 0x02,0x01,0,0,0x81,0,0,0); /* ??? */ sendsimple(0x47, *acc, 1,1,0); sendconfig(*acc, 8, 0x41,0x01,0x04,0,0,0,0,0); /* Baud 921600 */ sendsimple(0x42, *acc, 1,0x1000,0); sendconfig(*acc, 8, 0x41,0x07,0x02,0x02,0,0,0,0); /* RTS */ sendconfig(*acc, 8, 0x41,0x07,0x01,0x01,0,0,0,0); /* DTR */ sendconfig(*acc, 8, 0x41,0x03,0x00,0x08,0,0,0,0); /* 8 data bits, 1 stop bit, parity off */ sendconfig(*acc, 14, 0x41,0x19,0,0,0,0,0x06,0,0,0,0,0,0x11,0x13); /* "special chars" */ sendconfig(*acc, 24, 0x41,0x13,0,0,0,0,0x10,0,0x01,0,0,0,0x40,0,0,0,0,0x70,0,0,0,0x1C,0,0); /* "set flow" */ sendsimple(0x42, *acc, 1,0x1000,0); sendsimple(0x42, *acc, 1,0x1000,0); sendconfig(*acc, 8, 0x41,0x05,0x01,0,0,0,0,0); /* Break on */ sendconfig(*acc, 8, 0x41,0x05,0x01,0,0,0,0,0); /* Break on */ sendconfig(*acc, 8, 0x41,0x05,0x00,0,0,0,0,0); /* Break off */ queue_len[*acc] = 0; return 1; } int closedev_lx(int addr) { unsigned short ord; ord = finddev_lx(addr); if(ord == NOT_FOUND) return 1; usleep(500000); if(debug) printf("Deaktivuji zařízení s pořadím %i\n", ord); sendsimple(0x0C, 0, ord,0,0); free(waitpacket(0x1C)); dispatch(waitpacket61(0x0600)); dispatch(waitpacket61(0x0600)); sendsimple(0x08, 0, 2,3,0); dispatch(waitpacket(0x18)); return 1; } char *deverror_lx(int addr) { static char msg[200]; int off; off = sprintf(msg, "Nepodarilo se pripojit k zarizeni na portu c. %i.\n", addr); switch(lx_error) { case LX_ERROR_MEMORY: sprintf(msg+off, "Chyba pri inicializaci programu.\n"); break; case LX_ERROR_NETWORK: sprintf(msg+off, "Chyba sitove komunikace.\n"); break; case LX_ERROR_NOT_FOUND: sprintf(msg+off, "Zkontrolujte prosim, zda je zarizeni pripojeno na tomto portu.\n"); break; case LX_ERROR_ACTIVATE: sprintf(msg+off, "Zarizeni odmita pozadavek na aktivaci.\n"); break; } return msg; }