#include <asm/types.h>
#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;
}