You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1032 lines
20 KiB

/*
* $Id: syspkt.c,v 1.41 2006/10/12 14:21:23 desrod Exp $
*
* syspkt.c: Pilot SysPkt manager
*
* (c) 1996, Kenneth Albanowski.
* Derived from padp.c.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This library 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 Library
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "pi-source.h"
#include "pi-syspkt.h"
#include "pi-slp.h"
#include "pi-serial.h"
#include "pi-error.h"
/* Declare prototypes */
static int sys_PackRegisters(void *data, struct Pilot_registers *r);
/***********************************************************************
*
* Function: sys_UnpackState
*
* Summary: Get the state command
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_UnpackState(void *buffer, struct Pilot_state *s)
{
int idx;
unsigned char *data = buffer;
s->reset = get_short(data);
s->exception = get_short(data + 2);
memcpy(s->func_name, data + 152, 32);
memcpy(s->instructions, data + 78, 30);
s->func_name[32 - 1] = 0;
s->func_start = get_long(data + 144);
s->func_end = get_long(data + 148);
sys_UnpackRegisters(data + 4, &s->regs);
for (idx = 0; idx < 6; idx++) {
s->breakpoint[idx].address = get_long(data + 108 + idx * 6);
s->breakpoint[idx].enabled = get_byte(data + 112 + idx * 6);
}
s->trap_rev = get_short(data + 184);
return 0;
}
/***********************************************************************
*
* Function: sys_UnpackRegisters
*
* Summary: Read the register commands
*
* Parameters: None
*
* Returns: 0
*
***********************************************************************/
int
sys_UnpackRegisters(void *data, struct Pilot_registers *r)
{
unsigned char *buffer = data;
r->D[0] = get_long(buffer + 0);
r->D[1] = get_long(buffer + 4);
r->D[2] = get_long(buffer + 8);
r->D[3] = get_long(buffer + 12);
r->D[4] = get_long(buffer + 16);
r->D[5] = get_long(buffer + 20);
r->D[6] = get_long(buffer + 24);
r->D[7] = get_long(buffer + 28);
r->A[0] = get_long(buffer + 32);
r->A[1] = get_long(buffer + 36);
r->A[2] = get_long(buffer + 40);
r->A[3] = get_long(buffer + 44);
r->A[4] = get_long(buffer + 48);
r->A[5] = get_long(buffer + 52);
r->A[6] = get_long(buffer + 56);
r->USP = get_long(buffer + 60);
r->SSP = get_long(buffer + 64);
r->PC = get_long(buffer + 68);
r->SR = get_short(buffer + 72);
return 0;
}
/***********************************************************************
*
* Function: sys_PackRegisters
*
* Summary: Pack the register commands
*
* Parameters: None
*
* Returns: 0
*
***********************************************************************/
static int
sys_PackRegisters(void *data, struct Pilot_registers *r)
{
int idx;
unsigned char *buffer = data;
for (idx = 0; idx < 8; idx++)
set_long(buffer + idx * 4, r->D[idx]);
for (idx = 0; idx < 7; idx++)
set_long(buffer + 32 + idx * 4, r->A[idx]);
set_long(buffer + 60, r->USP);
set_long(buffer + 64, r->SSP);
set_long(buffer + 68, r->PC);
set_short(buffer + 72, r->SR);
return 0;
}
/***********************************************************************
*
* Function: sys_Continue
*
* Summary: Define the Continue command
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_Continue(int sd, struct Pilot_registers *r, struct Pilot_watch *w)
{
char buf[94];
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0x07;
buf[5] = 0; /* gapfill */
if (!r)
return pi_write(sd, buf, 6);
sys_PackRegisters(buf + 6, r);
set_byte(buf + 80, (w != 0) ? 1 : 0);
set_byte(buf + 81, 0);
set_long(buf + 82, w ? w->address : 0);
set_long(buf + 86, w ? w->length : 0);
set_long(buf + 90, w ? w->checksum : 0);
return pi_write(sd, buf, 94);
}
/***********************************************************************
*
* Function: sys_Step
*
* Summary: Single-step command
*
* Parameters: None
*
* Returns: Socket, command, 6 bytes
*
***********************************************************************/
int
sys_Step(int sd)
{
char buf[94];
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0x03;
buf[5] = 0; /* gapfill */
return pi_write(sd, buf, 6);
}
/***********************************************************************
*
* Function: sys_SetBreakpoints
*
* Summary: Set the breakpoints (0x0C, 0x8C)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_SetBreakpoints(int sd, struct Pilot_breakpoint *b)
{
int idx;
pi_buffer_t *buf;
buf = pi_buffer_new (94);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x0c;
buf->data[5] = 0; /* gapfill */
for (idx = 0; idx < 6; idx++) {
set_long(buf->data + 6 + idx * 6, b[idx].address);
set_byte(buf->data + 10 + idx * 6, b[idx].enabled);
set_byte(buf->data + 11 + idx * 6, 0);
}
pi_write(sd, buf->data, 42);
idx = pi_read(sd, buf, 6);
if (idx <= 0 || buf->data[4] != (unsigned char) 0x8c) {
pi_buffer_free (buf);
return 0;
}
pi_buffer_free (buf);
return 1;
}
/***********************************************************************
*
* Function: sys_SetTrapBreaks
*
* Summary: Set the Trap Breaks (0x11, 0x91)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_SetTrapBreaks(int sd, int *traps)
{
int idx;
pi_buffer_t *buf;
buf = pi_buffer_new (32);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x11;
buf->data[5] = 0; /* gapfill */
for (idx = 0; idx < 5; idx++) {
set_short(buf->data + 6 + idx * 2, traps[idx]);
}
pi_write(sd, buf->data, 16);
idx = pi_read(sd, buf, 6);
if ((idx <= 0) || (buf->data[4] != (unsigned char) 0x91)) {
pi_buffer_free (buf);
return 0;
}
pi_buffer_free (buf);
return 1;
}
/***********************************************************************
*
* Function: sys_GetTrapBreaks
*
* Summary: Get the Trap Breaks (0x10, 0x90)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_GetTrapBreaks(int sd, int *traps)
{
int idx;
pi_buffer_t *buf;
buf = pi_buffer_new (32);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x10;
buf->data[5] = 0; /* gapfill */
pi_write(sd, buf->data, 6);
idx = pi_read(sd, buf, 16);
if ((idx < 16) || (buf->data[4] != (unsigned char) 0x90)) {
pi_buffer_free (buf);
return 0;
}
for (idx = 0; idx < 5; idx++) {
traps[idx] = get_short(buf->data + 6 + idx * 2);
}
pi_buffer_free (buf);
return 1;
}
/***********************************************************************
*
* Function: sys_ToggleDbgBreaks
*
* Summary: Enable the DbgBreaks command (0x0D, 0x8D)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_ToggleDbgBreaks(int sd)
{
int idx;
pi_buffer_t *buf;
unsigned char byte;
buf = pi_buffer_new (32);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x0d;
buf->data[5] = 0; /* gapfill */
pi_write(sd, buf->data, 6);
idx = pi_read(sd, buf, 7);
if ((idx < 7) || (buf->data[4] != (unsigned char) 0x8d)) {
pi_buffer_free (buf);
return 0;
}
byte = get_byte(buf->data + 6);
pi_buffer_free (buf);
return byte;
}
/***********************************************************************
*
* Function: sys_QueryState
*
* Summary: Query the state (uh)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_QueryState(int sd)
{
char buf[6];
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0; /* gapfill */
return pi_write(sd, buf, 2);
}
/***********************************************************************
*
* Function: sys_ReadMemory
*
* Summary: Read memory (0x01, 0x81)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_ReadMemory(int sd, unsigned long addr, unsigned long len, void *dest)
{
int result;
unsigned long todo, done;
pi_buffer_t *buf;
buf = pi_buffer_new (0xFFFF);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
done = 0;
do {
todo = len;
if (todo > 256)
todo = 256;
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x01;
buf->data[5] = 0; /* gapfill */
set_long(buf->data + 6, addr + done);
set_short(buf->data + 10, todo);
pi_write(sd, buf->data, 12);
result = pi_read(sd, buf, todo + 6);
if (result < 0) {
pi_buffer_free (buf);
return done;
}
if ((buf->data[4] == 0x81)
&& ((unsigned int) result == todo + 6)) {
memcpy(((char *) dest) + done, buf->data + 6, todo);
done += todo;
} else {
pi_buffer_free (buf);
return done;
}
} while (done < len);
pi_buffer_free (buf);
return done;
}
/***********************************************************************
*
* Function: sys_WriteMemory
*
* Summary: Write memory (0x02, 0x82)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_WriteMemory(int sd, unsigned long addr, unsigned long len, void *src)
{
int result;
unsigned long todo, done;
pi_buffer_t *buf;
buf = pi_buffer_new (0xFFFF);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
done = 0;
do {
todo = len;
if (todo > 256)
todo = 256;
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x02;
buf->data[5] = 0; /* gapfill */
set_long(buf->data + 6, addr);
set_short(buf->data + 10, len);
memcpy(buf->data + 12, (char *)src + done, todo);
pi_write(sd, buf->data, len + 12);
result = pi_read(sd, buf, 6);
if (result < 0) {
pi_buffer_free (buf);
return done;
}
if ((buf->data[4] == (unsigned char)0x82)
&& ((unsigned long) result == todo + 6)) {
;
} else {
pi_buffer_free (buf);
return done;
}
} while (done < len);
pi_buffer_free (buf);
return done;
}
/***********************************************************************
*
* Function: sys_Find
*
* Summary: Searches a range of addresses for data (0x13, 0x80)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_Find(int sd, unsigned long startaddr, unsigned long stopaddr, size_t len,
int caseinsensitive, void *data, unsigned long *found)
{
int result;
unsigned char byte;
pi_buffer_t *buf;
buf = pi_buffer_new (len + 17);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = 0;
buf->data[1] = 0;
buf->data[2] = 0;
buf->data[3] = 0;
buf->data[4] = 0x11;
buf->data[5] = 0; /* gapfill */
set_long(buf->data + 6, startaddr);
set_long(buf->data + 10, stopaddr);
set_short(buf->data + 14, len);
set_byte(buf->data + 16, caseinsensitive);
memcpy(buf->data + 17, data, len);
pi_write(sd, buf->data, len + 17);
result = pi_read(sd, buf, 12);
if (result < 0) {
pi_buffer_free (buf);
return result;
}
if (found)
*found = get_long(buf->data + 6);
byte = get_byte(buf->data + 10);
pi_buffer_free (buf);
return byte;
}
/***********************************************************************
*
* Function: sys_RemoteEvent
*
* Summary: Parameters sent from host to target to feed pen and
* keyboard events. They do not require a response.
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_RemoteEvent(int sd, int penDown, int x, int y, int keypressed,
int keymod, int keyasc, int keycode)
{
char buf[16];
/* Offset 1, 3 and 9 are padding */
set_byte(&buf[0], 0x0D); /* RemoteEvtCommand */
set_byte(&buf[1], 0);
set_byte(&buf[2], penDown);
set_byte(&buf[3], 0);
set_short(&buf[4], x);
set_short(&buf[6], y);
set_byte(&buf[8], keypressed);
set_byte(&buf[9], 0);
set_short(&buf[10], keymod);
set_short(&buf[12], keyasc);
set_short(&buf[14], keycode);
return pi_write(sd, buf, 16);
}
/***********************************************************************
*
* Function: sys_RPC
*
* Summary: Remote Procedure calls (0x0A, 0x8A)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
sys_RPC(int sd, int sockaddr, int trap, long *D0, long *A0, int params,
struct RPC_param *param, int reply)
{
int idx;
unsigned char *c;
pi_buffer_t *buf;
buf = pi_buffer_new (4096);
if (buf == NULL) {
errno = ENOMEM;
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
}
buf->data[0] = sockaddr; /* 0 for debug, 1 for console */
buf->data[1] = sockaddr;
buf->data[2] = 0;
buf->data[4] = 0x0a;
buf->data[5] = 0;
set_short(buf->data + 6, trap);
set_long(buf->data + 8, *D0);
set_long(buf->data + 12, *A0);
set_short(buf->data + 16, params);
c = buf->data + 18;
for (idx = params - 1; idx >= 0; idx--) {
set_byte(c, param[idx].byRef);
c++;
set_byte(c, param[idx].size);
c++;
if (param[idx].data)
memcpy(c, param[idx].data, param[idx].size);
c += param[idx].size;
if (param[idx].size & 1)
*c++ = 0;
}
if (sockaddr == 3)
set_short(buf->data + 4, c - buf->data - 6);
pi_write(sd, buf->data + 4,(size_t)(c - buf->data - 4));
if (reply) {
int l = pi_read(sd, buf, 4096);
if (l < 0) {
pi_buffer_free (buf);
return l;
}
if (buf->data[0] != (unsigned char)0x8a) {
pi_buffer_free (buf);
return pi_set_error(sd, -2);
}
*D0 = get_long(buf->data + 4);
*A0 = get_long(buf->data + 8);
c = buf->data + 14;
for (idx = params - 1; idx >= 0; idx--) {
if (param[idx].byRef && param[idx].data)
memcpy(param[idx].data, c + 2,
param[idx].size);
c += 2 + ((get_byte(c + 1) + 1) & ~1);
}
}
pi_buffer_free (buf);
return 0;
}
/***********************************************************************
*
* Function: RPC
*
* Summary: Deprecated
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
RPC(int sd, int sockaddr, int trap, int reply, ...)
{
int idx = 0,
j,
RPC_arg[20];
va_list ap;
struct RPC_param p[20];
long D0 = 0,
A0 = 0;
va_start(ap, reply);
for (;;) {
int type = va_arg(ap, int);
if (type == 0)
break;
if (type < 0) {
p[idx].byRef = 0;
p[idx].size = -type;
RPC_arg[idx] = va_arg(ap, int);
p[idx].data = &RPC_arg[idx];
p[idx].invert = 0;
} else {
void *c = va_arg(ap, void *);
p[idx].byRef = 1;
p[idx].size = type;
p[idx].data = c;
p[idx].invert = va_arg(ap, int);
if (p[idx].invert) {
if (p[idx].size == 2) {
int *s = c;
*s = htons(*s);
} else {
int *l = c;
*l = htonl(*l);
}
}
}
idx++;
}
va_end(ap);
if (sys_RPC(sd, sockaddr, trap, &D0, &A0, idx, p, reply != 2) < 0)
return pi_error(sd);
for (j = 0; j < idx; j++) {
if (p[j].invert) {
void *c = p[j].data;
if (p[j].size == 2) {
int *s = c;
*s = htons(*s);
} else {
int *l = c;
*l = htonl(*l);
}
}
}
if (reply)
return A0;
return D0;
}
/***********************************************************************
*
* Function: PackRPC
*
* Summary: Pack the RPC structure for transmission
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
PackRPC(struct RPC_params *p, int trap, int reply, ...)
{
int idx = 0;
va_list ap;
p->trap = trap;
p->reply = reply;
va_start(ap, reply);
for (;;) {
int type = (int) va_arg(ap, int);
if (type == 0)
break;
if (type < 0) {
p->param[idx].byRef = 0;
p->param[idx].size = -type;
p->param[idx].arg = (int) va_arg(ap, int);
p->param[idx].data = &p->param[idx].arg;
p->param[idx].invert = 0;
} else {
void *c = (void *) va_arg(ap, void *);
p->param[idx].byRef = 1;
p->param[idx].size = type;
p->param[idx].data = c;
p->param[idx].invert = (int) va_arg(ap, int);
}
idx++;
}
p->args = idx;
va_end(ap);
return 0;
}
/***********************************************************************
*
* Function: UninvertRPC
*
* Summary:
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
void
UninvertRPC(struct RPC_params *p)
{
int j;
for (j = 0; j < p->args; j++) {
if (p->param[j].invert) {
void *c = p->param[j].data;
if ((p->param[j].invert == 2)
&& (p->param[j].size == 2)) {
int *s = c;
*s = htons(*s) >> 8;
} else if (p->param[j].size == 2) {
int *s = c;
*s = htons(*s);
} else {
long *l = c;
*l = htonl(*l);
}
}
}
}
/***********************************************************************
*
* Function: InvertRPC
*
* Summary:
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
void
InvertRPC(struct RPC_params *p)
{
int j;
for (j = 0; j < p->args; j++) {
if (p->param[j].invert) {
void *c = p->param[j].data;
if ((p->param[j].invert == 2)
&& (p->param[j].size == 2)) {
int *s = c;
*s = ntohs(*s) >> 8;
} else if (p->param[j].size == 2) {
int *s = c;
*s = ntohs(*s);
} else {
long *l = c;
*l = ntohl((unsigned) *l);
}
}
}
}
/***********************************************************************
*
* Function: DoRPC
*
* Summary: Actually execute the RPC query/response
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
unsigned long
DoRPC(int sd, int sockaddr, struct RPC_params *p, int *error)
{
int err;
long D0 = 0,
A0 = 0;
InvertRPC(p);
err =
sys_RPC(sd, sockaddr, p->trap, &D0, &A0, p->args, &p->param[0],
p->reply);
UninvertRPC(p);
if (error)
*error = err;
if (p->reply == RPC_PtrReply)
return A0;
else if (p->reply == RPC_IntReply)
return D0;
else
return err;
}
/***********************************************************************
*
* Function: RPC_Int_Void
*
* Summary:
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
RPC_Int_Void(int sd, int trap)
{
return RPC(sd, 1, trap, 0, RPC_End);
}
/***********************************************************************
*
* Function: RPC_Ptr_Void
*
* Summary:
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int
RPC_Ptr_Void(int sd, int trap)
{
return RPC(sd, 1, trap, 1, RPC_End);
}
/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
/* ex: set tabstop=4 expandtab: */
/* Local Variables: */
/* indent-tabs-mode: t */
/* c-basic-offset: 8 */
/* End: */