git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1740 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
883 lines
22 KiB
C++
883 lines
22 KiB
C++
/****************************************************************
|
|
* *
|
|
* Copyright notice: *
|
|
* *
|
|
* Lauterbach Datentechnik GmbH *
|
|
* Alle Rechte vorbehalten - All rights reserved *
|
|
* *
|
|
*****************************************************************
|
|
|
|
Module: hlinknet.c
|
|
Function: Low level communication protocol for talking to TRACE32.
|
|
Is used by CAPI routined implemented in hremote.c.
|
|
Link both files with your application.
|
|
|
|
***************************************************************/
|
|
|
|
#include "t32.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifdef MS_WINDOWS
|
|
# include <winsock2.h>
|
|
# include <windows.h>
|
|
# include <fcntl.h>
|
|
typedef int socklen_t;
|
|
#endif
|
|
|
|
#ifdef DEC_VMS
|
|
# include <file.h>
|
|
# include <time.h>
|
|
# include <errno.h>
|
|
# include <socket.h>
|
|
# include <inet.h>
|
|
# include <netdb.h>
|
|
# include <in.h>
|
|
# define DONT_USE_ASYNC
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
# include <fcntl.h>
|
|
# include <unistd.h>
|
|
# include <sys/time.h>
|
|
# include <errno.h>
|
|
# include <sys/socket.h>
|
|
# include <netinet/in.h>
|
|
# include <netdb.h>
|
|
# include <sys/select.h>
|
|
#endif
|
|
|
|
|
|
#ifdef UNIX_V
|
|
# include <fcntl.h>
|
|
# include <unistd.h>
|
|
# include <sys/time.h>
|
|
# include <errno.h>
|
|
# include <sys/socket.h>
|
|
# include <netinet/in.h>
|
|
# include <netdb.h>
|
|
# ifdef HP_UX
|
|
typedef int socklen_t;
|
|
# else
|
|
# include <sys/select.h>
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef OS_9
|
|
# include <fcntl.h>
|
|
# include <sys/time.h>
|
|
# include <errno.h>
|
|
# include <inet/socket.h>
|
|
# include <inet/in.h>
|
|
# include <inet/netdb.h>
|
|
#endif
|
|
|
|
|
|
#define PCKLEN_MAX 1472 /* maximum size of UDP-packet */
|
|
#define BUFLEN_MIN 6000
|
|
|
|
#ifndef MS_WINDOWS
|
|
# ifndef UNIX_V
|
|
extern struct hostent * gethostbyaddr();
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef DEC_VMS
|
|
# define fd_set int
|
|
# define FD_ZERO(fdset) (*fdset = 0)
|
|
# define FD_SET(fd,fdset) (*fdset |= (1<<(fd)))
|
|
# define FD_ISSET(fd,fdset) (*fdset & (1<<(fd)))
|
|
#endif
|
|
|
|
#if defined(DEC_VMS) || defined(MS_WINDOWS) || defined(OS_9) || defined(LINUX)
|
|
# define RECEIVEADDR (&ReceiveSocketAddress)
|
|
static struct sockaddr ReceiveSocketAddress;
|
|
#else
|
|
# define RECEIVEADDR 0
|
|
#endif
|
|
|
|
|
|
struct LineStruct {
|
|
char NodeName[80]; /* node name of host running T32 SW */
|
|
int CommSocket; /* socket for communication */
|
|
unsigned short HostPort; /* Host side port */
|
|
unsigned short ReceivePort; /* Receiver Port */
|
|
unsigned short TransmitPort; /* Transmitter Port in T32 */
|
|
int PacketSize; /* Max. size of UDP-packet data */
|
|
int PollTimeSec;
|
|
int ReceiveToggleBit;
|
|
unsigned char MessageId;
|
|
int LineUp;
|
|
unsigned short ReceiveSeq, TransmitSeq; /* block-ids */
|
|
unsigned short LastReceiveSeq, LastTransmitSeq;
|
|
unsigned char* LastTransmitBuffer;
|
|
int LastTransmitSize;
|
|
struct sockaddr_in SocketAddress;
|
|
};
|
|
|
|
#ifdef MS_WINDOWS
|
|
extern void T32_InstallAsyncSelect(HWND hwnd, int msg);
|
|
extern void T32_UnInstallAsyncSelect(HWND hwnd);
|
|
#endif
|
|
|
|
extern void LINE_SetReceiveToggleBit(int value);
|
|
extern int LINE_GetReceiveToggleBit(void);
|
|
extern int LINE_GetNextMessageId(void);
|
|
extern int LINE_GetMessageId(void);
|
|
extern int LINE_GetLineParamsSize (void);
|
|
extern void LINE_SetDefaultLineParams (LineStruct* params);
|
|
extern LineStruct* LINE_GetLine0Params (void);
|
|
extern void LINE_SetLine (LineStruct* params);
|
|
extern int LINE_LineConfig(char * in);
|
|
extern void LINE_LineExit(void);
|
|
extern int LINE_LineInit(char * message);
|
|
extern int LINE_LineTransmit(unsigned char * in, int size);
|
|
extern int LINE_LineDriverGetSocket(void);
|
|
extern int LINE_LineReceive(unsigned char * out);
|
|
extern int LINE_ReceiveNotifyMessage(unsigned char* package);
|
|
extern int LINE_LineSync(void);
|
|
|
|
static int Connection(unsigned char *ipaddrused);
|
|
|
|
static struct timeval LongTime = { 0, 500000 };
|
|
|
|
|
|
|
|
static const LineStruct LineDefaultParams = {
|
|
"localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0};
|
|
static LineStruct Line0Params = {
|
|
"localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0};
|
|
|
|
static LineStruct* pLineParams = &Line0Params;
|
|
|
|
|
|
|
|
static int str2dec (char* in)
|
|
{
|
|
int x = 0;
|
|
while (*in) {
|
|
x *= 10;
|
|
if (*in < '0' || *in > '9')
|
|
return -1;
|
|
x += *in - '0';
|
|
in++;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
|
|
void LINE_SetReceiveToggleBit(int value)
|
|
{
|
|
pLineParams->ReceiveToggleBit = value;
|
|
}
|
|
|
|
|
|
int LINE_GetReceiveToggleBit(void)
|
|
{
|
|
return pLineParams->ReceiveToggleBit;
|
|
}
|
|
|
|
|
|
int LINE_GetNextMessageId(void)
|
|
{
|
|
return ++pLineParams->MessageId;
|
|
}
|
|
|
|
|
|
int LINE_GetMessageId(void)
|
|
{
|
|
return pLineParams->MessageId;
|
|
}
|
|
|
|
|
|
int LINE_GetLineParamsSize (void)
|
|
{
|
|
return sizeof (LineStruct);
|
|
}
|
|
|
|
void LINE_SetDefaultLineParams (LineStruct* params)
|
|
{
|
|
*params = LineDefaultParams;
|
|
return;
|
|
}
|
|
|
|
|
|
LineStruct* LINE_GetLine0Params (void)
|
|
{
|
|
return &Line0Params;
|
|
}
|
|
|
|
|
|
void LINE_SetLine (LineStruct* params)
|
|
{
|
|
pLineParams = params;
|
|
}
|
|
|
|
|
|
int LINE_LineConfig(char * in)
|
|
{
|
|
int x;
|
|
LineStruct* line = pLineParams;
|
|
|
|
if (!strncmp((char *) in, "NODE=", 5)) {
|
|
strcpy(line->NodeName, in+5);
|
|
return 1;
|
|
}
|
|
if (!strncmp((char *) in, "PORT=", 5)) {
|
|
x = str2dec (in+5);
|
|
if (x == -1)
|
|
return -1;
|
|
line->TransmitPort = x;
|
|
return 1;
|
|
}
|
|
if (!strncmp((char *) in, "HOSTPORT=", 9)) {
|
|
x = str2dec (in+9);
|
|
if (x == -1)
|
|
return -1;
|
|
line->HostPort = x;
|
|
return 1;
|
|
}
|
|
if (!strncmp((char *) in, "PACKLEN=", 8)) {
|
|
x = str2dec (in+8);
|
|
if (x == -1)
|
|
return -1;
|
|
line->PacketSize = x;
|
|
return 1;
|
|
}
|
|
if (!strncmp((char *) in, "TIMEOUT=", 8)) {
|
|
x = str2dec (in+8);
|
|
if (x == -1)
|
|
return -1;
|
|
line->PollTimeSec = x;
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void WinsockErrorMessage(char * out)
|
|
{
|
|
#ifdef MS_WINDOWS
|
|
int err;
|
|
err = WSAGetLastError();
|
|
|
|
switch (err) {
|
|
case WSAHOST_NOT_FOUND:
|
|
strcat(out, " (HOST_NOT_FOUND)");
|
|
break;
|
|
case WSATRY_AGAIN:
|
|
strcat(out, " (TRY_AGAIN)");
|
|
break;
|
|
case WSANO_RECOVERY:
|
|
strcat(out, " (NO_RECOVERY)");
|
|
break;
|
|
case WSANO_DATA:
|
|
strcat(out, " (NO_DATA)");
|
|
break;
|
|
case WSAEINTR:
|
|
strcat(out, " (INTR)");
|
|
break;
|
|
case WSANOTINITIALISED:
|
|
strcat(out, " (NOTINITIALISED)");
|
|
break;
|
|
case WSAENETDOWN:
|
|
strcat(out, " (NETDOWN)");
|
|
break;
|
|
case WSAEAFNOSUPPORT:
|
|
strcat(out, " (WSAEAFNOSUPPORT)");
|
|
break;
|
|
case WSAEINPROGRESS:
|
|
strcat(out, " (INPROGRESS)");
|
|
break;
|
|
case WSAEMFILE:
|
|
strcat(out, " (WSAEMFILE)");
|
|
break;
|
|
case WSAENOBUFS:
|
|
strcat(out, " (WSAENOBUFS)");
|
|
break;
|
|
case WSAEPROTONOSUPPORT:
|
|
strcat(out, " (WSAEPROTONOSUPPORT)");
|
|
break;
|
|
case WSAEPROTOTYPE:
|
|
strcat(out, " (WSAEPROTOTYPE)");
|
|
break;
|
|
case WSAESOCKTNOSUPPORT:
|
|
strcat(out, " (WSAESOCKTNOSUPPORT)");
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
static long GetInetAddress(char * name, char * message)
|
|
{
|
|
struct hostent *hp;
|
|
int i1, i2, i3, i4;
|
|
|
|
char ownname[256];
|
|
|
|
if (name == NULL) {
|
|
gethostname(ownname, sizeof(ownname));
|
|
name = ownname;
|
|
}
|
|
i1 = i2 = i3 = i4 = 0;
|
|
|
|
if (sscanf(name, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) == 4) {
|
|
if (i1 || i2 || i3 || i4) {
|
|
return (i1 << 24) | (i2 << 16) | (i3 << 8) | (i4);
|
|
}
|
|
}
|
|
hp = gethostbyname(name);
|
|
|
|
if (!hp) {
|
|
strcpy(message, "node name (");
|
|
strcat(message, name);
|
|
strcat(message, ") unknown");
|
|
WinsockErrorMessage(message);
|
|
return -1l;
|
|
}
|
|
return ntohl(*(long *) (hp->h_addr));
|
|
}
|
|
|
|
|
|
void LINE_LineExit(void)
|
|
{
|
|
int i;
|
|
LineStruct* line = pLineParams;
|
|
static const unsigned char discon[] = {4, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0};
|
|
|
|
if (!line->LineUp)
|
|
return;
|
|
|
|
if (line->CommSocket != -1) {
|
|
for (i = 0; i < 5; i++)
|
|
sendto(line->CommSocket, (char *) discon, 16, 0,
|
|
(struct sockaddr *) &(line->SocketAddress), sizeof(line->SocketAddress));
|
|
|
|
#ifdef MS_WINDOWS
|
|
closesocket(line->CommSocket);
|
|
#endif
|
|
#if defined(DEC_VMS) || defined(UNIX_V) || defined(OS_9)
|
|
close(line->CommSocket);
|
|
#endif
|
|
}
|
|
#ifdef MS_WINDOWS
|
|
WSACleanup();
|
|
#endif
|
|
|
|
line->CommSocket = -1;
|
|
line->LineUp = 0;
|
|
}
|
|
|
|
|
|
int LINE_LineInit(char * message)
|
|
{
|
|
int i, j;
|
|
socklen_t length;
|
|
int val;
|
|
unsigned char ipaddrused[4];
|
|
long remote_ip;
|
|
int buflen;
|
|
LineStruct* line = pLineParams;
|
|
|
|
if (line->LineUp)
|
|
return 0;
|
|
|
|
if (line->CommSocket == -1) {
|
|
#ifdef MS_WINDOWS
|
|
WSADATA wsaData;
|
|
if (WSAStartup(0x0101, &wsaData)) {
|
|
strcpy(message, "TCP/IP not ready, check configuration");
|
|
return -1;
|
|
}
|
|
#endif
|
|
}
|
|
if ((remote_ip = GetInetAddress(line->NodeName, message)) == -1l)
|
|
return -1;
|
|
|
|
if (line->CommSocket == -1) {
|
|
line->SocketAddress.sin_family = AF_INET;
|
|
line->SocketAddress.sin_addr.s_addr = INADDR_ANY;
|
|
line->SocketAddress.sin_port = line->HostPort; /* Port can be determined by
|
|
* host */
|
|
|
|
if ((line->CommSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
|
strcpy(message, "cannot create socket");
|
|
WinsockErrorMessage(message);
|
|
goto done;
|
|
}
|
|
if ((i = bind(line->CommSocket, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress))) == -1) {
|
|
strcpy(message, "cannot bind socket");
|
|
WinsockErrorMessage(message);
|
|
goto done;
|
|
}
|
|
length = sizeof(line->SocketAddress);
|
|
if (getsockname(line->CommSocket, (struct sockaddr *) & line->SocketAddress, &length) == -1) {
|
|
strcpy(message, "cannot identify port");
|
|
WinsockErrorMessage(message);
|
|
goto done;
|
|
}
|
|
line->ReceivePort = ntohs(line->SocketAddress.sin_port);
|
|
|
|
line->SocketAddress.sin_family = AF_INET;
|
|
line->SocketAddress.sin_addr.s_addr = INADDR_ANY;
|
|
line->SocketAddress.sin_port = htons(line->TransmitPort);
|
|
}
|
|
line->SocketAddress.sin_addr.s_addr = htonl(remote_ip);
|
|
|
|
buflen = 18000;
|
|
|
|
#if !defined(OS_9)
|
|
val = 0;
|
|
length = sizeof(val);
|
|
getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length);
|
|
|
|
if (val > 0 && val < line->PacketSize)
|
|
line->PacketSize = val;
|
|
|
|
if (val < buflen) {
|
|
val = buflen;
|
|
length = sizeof(val);
|
|
if (setsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, length) == -1) {
|
|
strcpy(message, "cannot alloc buffer for rcvsocket");
|
|
goto done;
|
|
}
|
|
val = 0;
|
|
length = sizeof(val);
|
|
getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length);
|
|
if (val < buflen) {
|
|
strcpy(message, "cannot alloc buffer for rcvsocket");
|
|
goto done;
|
|
}
|
|
}
|
|
val = 0;
|
|
length = sizeof(val);
|
|
getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length);
|
|
if (val < buflen) {
|
|
val = buflen;
|
|
length = sizeof(val);
|
|
if (setsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, length) == -1) {
|
|
strcpy(message, "cannot alloc buffer for sndsocket");
|
|
goto done;
|
|
}
|
|
val = 0;
|
|
length = sizeof(val);
|
|
getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length);
|
|
if (val < buflen) {
|
|
strcpy(message, "cannot alloc buffer for sndsocket");
|
|
goto done;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
j = Connection(ipaddrused);
|
|
|
|
if (j == 0)
|
|
continue;
|
|
|
|
if (j == 1) {
|
|
line->LineUp = 1;
|
|
return 1;
|
|
}
|
|
|
|
strcpy(message, "TRACE32 access refused");
|
|
goto done;
|
|
}
|
|
|
|
strcpy(message, "TRACE32 not responding");
|
|
|
|
done:
|
|
LINE_LineExit(); /* Close connection if no success */
|
|
return -1;
|
|
}
|
|
|
|
|
|
#ifdef MS_WINDOWS
|
|
|
|
void T32_InstallAsyncSelect(HWND hwnd, int msg)
|
|
{
|
|
#ifndef DONT_USE_ASYNC
|
|
WSAAsyncSelect(pLineParams->CommSocket, hwnd, msg, FD_READ);
|
|
#endif
|
|
}
|
|
|
|
void T32_UnInstallAsyncSelect(HWND hwnd)
|
|
{
|
|
#ifndef DONT_USE_ASYNC
|
|
WSAAsyncSelect(pLineParams->CommSocket, hwnd, 0, 0);
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
Sends a message to T32. Handles segmentation of _message_ into (one
|
|
or multiple) _packages_.
|
|
|
|
@param in pointer to outgoing message (already includes 5 byte message header)
|
|
@param size size of message
|
|
@note the message must be allocated such that there is space in
|
|
front of the message for adding the packet header
|
|
*/
|
|
|
|
int LINE_LineTransmit(unsigned char * in, int size)
|
|
{
|
|
int packetSize;
|
|
unsigned int tmpl;
|
|
LineStruct* line = pLineParams;
|
|
|
|
line->LastTransmitBuffer = in;
|
|
line->LastTransmitSize = size;
|
|
line->LastTransmitSeq = line->TransmitSeq;
|
|
in -= 4; /* space for packet header */
|
|
|
|
do {
|
|
packetSize = (size > line->PacketSize - 4) ? line->PacketSize - 4 : size;
|
|
|
|
/* When sending multiple packets, the packet header is written inside the
|
|
message's payload. Original contents needs to be saved/restored */
|
|
|
|
SETLONGVAR(tmpl, in[0]); /* save */
|
|
|
|
in[0] = 0x11; /* transmit data package */
|
|
in[1] = (size > packetSize) ? 1 : 0; /* more packets follow */
|
|
SETWORDVAR(in[2], line->TransmitSeq); /* packet sequence ID */
|
|
|
|
if (sendto(line->CommSocket,
|
|
(char *) in,
|
|
packetSize + 4, 0,
|
|
(struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)
|
|
) != packetSize + 4) {
|
|
|
|
SETLONGVAR(in[0], tmpl); /* restore buffer */
|
|
return 0;
|
|
}
|
|
SETLONGVAR(in[0], tmpl); /* restore buffer */
|
|
|
|
line->TransmitSeq++;
|
|
in += packetSize;
|
|
size -= packetSize;
|
|
}
|
|
while (size > 0); /* more packets required? */
|
|
|
|
return line->LastTransmitSize;
|
|
}
|
|
|
|
/** Receives a package from the socket, with timeout handling.
|
|
@return number of received bytes or error number (<0)
|
|
*/
|
|
static int ReceiveWithTimeout(struct timeval *tim, unsigned char *dest, int size)
|
|
{
|
|
int i;
|
|
fd_set readfds;
|
|
socklen_t length;
|
|
struct timeval timeout;
|
|
LineStruct* line = pLineParams;
|
|
|
|
timeout = *tim;
|
|
|
|
#ifdef POLL_NET
|
|
DWORD endpoll;
|
|
static struct timeval tival = {0};
|
|
|
|
if (tim->tv_usec || tim->tv_sec)
|
|
endpoll = GetCurrentTime() + tim->tv_usec / 1000 + tim->tv_sec * 1000;
|
|
else
|
|
endpoll = 0;
|
|
retry:
|
|
#endif
|
|
|
|
FD_ZERO(&readfds);
|
|
FD_SET( (unsigned int)line->CommSocket, &readfds);
|
|
|
|
#ifdef POLL_NET
|
|
i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tival);
|
|
|
|
if (i < 0)
|
|
return i;
|
|
|
|
if (i == 0) {
|
|
if (endpoll) {
|
|
if (GetCurrentTime() < endpoll) {
|
|
ScreenDispatcher(line->CommSocket);
|
|
goto retry;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
#else
|
|
i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timeout);
|
|
#endif
|
|
|
|
if (i <= 0) {
|
|
return i;
|
|
}
|
|
length = sizeof(struct sockaddr);
|
|
return recvfrom(line->CommSocket, dest, size, 0, (struct sockaddr *) RECEIVEADDR, &length);
|
|
}
|
|
|
|
|
|
int LINE_LineDriverGetSocket(void)
|
|
{
|
|
return pLineParams->CommSocket;
|
|
}
|
|
|
|
/* Queue pending notifications */
|
|
T32_NotificationPackage *T32_NotificationHead = NULL, *T32_NotificationTail = NULL;
|
|
|
|
/** Receives messages from the socket. Assembles multiple packets into
|
|
a single message.
|
|
|
|
@param out output buffer for storing payload. Attention: there must
|
|
be some space _before_ the output buffer (4 bytes or more)
|
|
for temporary usage.
|
|
@return number of bytes of the message or error number (<0)
|
|
*/
|
|
|
|
int LINE_LineReceive(unsigned char * out)
|
|
{
|
|
int i, flag;
|
|
int count;
|
|
unsigned short tmpw;
|
|
unsigned int tmpl;
|
|
unsigned short s;
|
|
LineStruct* line = pLineParams;
|
|
register unsigned char *dest;
|
|
static unsigned char handshake[] = {7, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0};
|
|
|
|
retry:
|
|
dest = out-4; /* adjust pointer so we place header BEFORE "out" and thus payload AT "out" */
|
|
count = 0;
|
|
s = line->ReceiveSeq;
|
|
|
|
do {
|
|
|
|
/* multiple packets are merged in-place: backup data that is
|
|
overwritten package aby header */
|
|
SETLONGVAR(tmpl, dest[0]);
|
|
|
|
do {
|
|
struct timeval PollTime = {0, 0};
|
|
PollTime.tv_sec = line->PollTimeSec;
|
|
if ((i = ReceiveWithTimeout(&PollTime, dest, line->PacketSize)) <= 0) {
|
|
if (i == -2)
|
|
goto retry;
|
|
return -1;
|
|
}
|
|
if (i <= 4) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* Detect and enqeue async notification that slipped into a request/reply pair */
|
|
if (dest[0] == T32_API_NOTIFICATION)
|
|
{
|
|
T32_NotificationPackage *newPackage, *oldHead;
|
|
|
|
newPackage = reinterpret_cast<T32_NotificationPackage*>( malloc(sizeof(T32_NotificationPackage)) );
|
|
if (newPackage==NULL)
|
|
return -1;
|
|
|
|
memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */
|
|
oldHead = T32_NotificationHead;
|
|
newPackage->prev = NULL;
|
|
newPackage->next = oldHead;
|
|
if (oldHead)
|
|
oldHead->prev = newPackage;
|
|
T32_NotificationHead = newPackage;
|
|
if (T32_NotificationTail==NULL) {
|
|
T32_NotificationTail=newPackage;
|
|
}
|
|
goto retry;
|
|
}
|
|
|
|
if (dest[0] != T32_API_RECEIVE) {
|
|
return -1;
|
|
}
|
|
SETWORDVAR(tmpw, dest[2]);
|
|
|
|
if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) {
|
|
line->TransmitSeq = line->LastTransmitSeq;
|
|
LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize);
|
|
}
|
|
}
|
|
while (tmpw != line->ReceiveSeq);
|
|
|
|
line->ReceiveSeq++;
|
|
flag = dest[1];
|
|
SETLONGVAR(dest[0], tmpl); /* restore payload overwritten by package header */
|
|
dest += i - 4;
|
|
count += i - 4;
|
|
|
|
if (count > LINE_MSIZE) {
|
|
return -1;
|
|
}
|
|
if (flag == 2) {
|
|
if (sendto(line->CommSocket, (char *) handshake, 16, 0,
|
|
(struct sockaddr *) &line->SocketAddress, sizeof(line->SocketAddress)) != 16) {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
while (flag);
|
|
|
|
line->LastReceiveSeq = s;
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
/** Receives notification messages. First checks for a queued
|
|
notification and if none is available polls the socket for new
|
|
notifications. For getting all pending notifications call the
|
|
function until it returns -1.
|
|
|
|
@param package output buffer of size T32_PCKLEN_MAX for the package
|
|
@return -1 no notification pending,
|
|
>=0 notificataion type T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG
|
|
|
|
*/
|
|
|
|
|
|
int LINE_ReceiveNotifyMessage(unsigned char* package)
|
|
{
|
|
int len;
|
|
static struct timeval LongTime = {0, 0};
|
|
|
|
/* Check for asynchronous notifications */
|
|
if (T32_NotificationTail) {
|
|
T32_NotificationPackage *prev = T32_NotificationTail->prev;
|
|
if (prev)
|
|
prev->next = NULL;
|
|
memcpy(package, T32_NotificationTail->payload, T32_PCKLEN_MAX);
|
|
free(T32_NotificationTail);
|
|
T32_NotificationTail = prev;
|
|
if (prev==NULL) /* deleted last message */
|
|
T32_NotificationHead = NULL;
|
|
} else {
|
|
len = ReceiveWithTimeout(&LongTime, package, T32_PCKLEN_MAX);
|
|
if (len < 2)
|
|
return -1;
|
|
}
|
|
|
|
if (package[0] != T32_API_NOTIFICATION)
|
|
return -1;
|
|
|
|
return package[1]; /* type of notification: T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG */
|
|
}
|
|
|
|
/** Sends sync packets */
|
|
int LINE_LineSync(void)
|
|
{
|
|
int i, j;
|
|
unsigned char packet[T32_PCKLEN_MAX];
|
|
static char magicPattern[] = "TRACE32";
|
|
LineStruct* line = pLineParams;
|
|
|
|
j = 0;
|
|
memset(packet, 0, sizeof(packet));
|
|
|
|
retry:
|
|
packet[0] = T32_API_SYNCREQUEST;
|
|
packet[1] = 0;
|
|
SETWORDVAR(packet[2], line->TransmitSeq);
|
|
SETWORDCONST(packet[4], 0);
|
|
SETWORDCONST(packet[6], 0);
|
|
strcpy((char *) (packet + 8), magicPattern);
|
|
|
|
if (sendto(line->CommSocket, (char *) packet, 16 /*size*/, 0,
|
|
(struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) {
|
|
return -1;
|
|
}
|
|
while (1) { /* empty queue */
|
|
if (++j > 20) {
|
|
return -1;
|
|
}
|
|
if ((i = ReceiveWithTimeout(&LongTime, packet, T32_PCKLEN_MAX)) <= 0) {
|
|
return -1;
|
|
}
|
|
if (i != 16 || packet[0] != T32_API_SYNCACKN || strcmp((char *) packet + 8, magicPattern)) {
|
|
if (i == 16 && packet[0] == 5)
|
|
goto retry;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
SETWORDVAR(line->ReceiveSeq, packet[2]);
|
|
line->LastReceiveSeq = line->ReceiveSeq - 100;
|
|
|
|
|
|
packet[0] = T32_API_SYNCBACK;
|
|
packet[1] = 0;
|
|
SETWORDVAR(packet[2], line->TransmitSeq);
|
|
SETWORDCONST(packet[4], 0);
|
|
SETWORDCONST(packet[6], 0);
|
|
strcpy((char *) (packet + 8), magicPattern);
|
|
|
|
if (sendto(line->CommSocket, (char *) packet, 16, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) {
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int Connection(unsigned char *ipaddrused)
|
|
{
|
|
int i;
|
|
unsigned char buffer[T32_PCKLEN_MAX];
|
|
LineStruct* line = pLineParams;
|
|
static const char magicPattern[] = "TRACE32";
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
buffer[0] = 3; /* CONNECTREQUEST */
|
|
buffer[1] = 0;
|
|
|
|
line->TransmitSeq = 1;
|
|
SETWORDVAR(buffer[2], line->TransmitSeq);
|
|
SETWORDVAR(buffer[4], line->TransmitPort);
|
|
SETWORDVAR(buffer[6], line->ReceivePort);
|
|
|
|
strcpy((char *) (buffer + 8), magicPattern);
|
|
|
|
if (sendto(line->CommSocket, (char *) buffer, line->PacketSize, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) {
|
|
return 0;
|
|
}
|
|
if ((i = ReceiveWithTimeout(&LongTime, buffer, line->PacketSize)) <= 0) {
|
|
return 0;
|
|
}
|
|
if (strcmp((char *) (buffer + 8), magicPattern)) {
|
|
return 0;
|
|
}
|
|
SETWORDVAR(line->ReceiveSeq, buffer[2]);
|
|
|
|
if (buffer[0] == 0x53) { /* POSITIVE CONNECTACKN from Debug Unit ? */
|
|
ipaddrused[0] = 1;
|
|
ipaddrused[1] = 1;
|
|
ipaddrused[2] = 1;
|
|
ipaddrused[3] = 11;
|
|
return 2;
|
|
}
|
|
|
|
if (buffer[0] != 0x13) { /* POSITIVE CONNECTACKN ? */
|
|
if (buffer[0] == 0x23) {/* NEGATIVE ? */
|
|
ipaddrused[0] = buffer[4];
|
|
ipaddrused[1] = buffer[5];
|
|
ipaddrused[2] = buffer[6];
|
|
ipaddrused[3] = buffer[7];
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
line->PacketSize = i;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|