191 lines
4.3 KiB
C
191 lines
4.3 KiB
C
|
#include <stdbool.h>
|
||
|
#include "msg.h"
|
||
|
|
||
|
/*
|
||
|
* send async [1]
|
||
|
* [10: bus][6: node][48 : address][8: tcode][8 : tlabel][16 : len][data ...]
|
||
|
*/
|
||
|
#define SEND_ASYNC_LEN (10 + 6 + 48 + 8 + 8 + 16)/8
|
||
|
|
||
|
/*
|
||
|
* send iso [2]
|
||
|
* [8 : channel][8 : tag][8 : synch][16 : len][data ...]
|
||
|
*/
|
||
|
#define SEND_ISO_LEN (8 + 8 + 8 + 16)/8
|
||
|
|
||
|
/*
|
||
|
* allocate [3]
|
||
|
* [48: start] [48: len]
|
||
|
*/
|
||
|
#define ALLOCATE_LEN (48 + 48)/8
|
||
|
|
||
|
static bool parse_send_async(struct msg_state *st) {
|
||
|
const char *p = st->buf + 1;
|
||
|
const size_t l = sdslen(st->buf) - 1;
|
||
|
|
||
|
if (l < SEND_ASYNC_LEN)
|
||
|
return false;
|
||
|
st->msg.send_async.len = p[10] << 8 | p[11];
|
||
|
if (l < SEND_ASYNC_LEN + len)
|
||
|
return false;
|
||
|
|
||
|
st->msg.send_async.bus = p[0] << 8 | p[1];
|
||
|
st->msg.send_async.node = bus & 0x3F;
|
||
|
st->msg.send_async.bus >>= 6;
|
||
|
|
||
|
st->msg.send_async.addr = p[2] << 40 | p[3] << 32 | p[4] << 24 | p[5] << 16
|
||
|
| p[6] << 8 | p[7];
|
||
|
st->msg.send_async.tcode = p[8];
|
||
|
st->msg.send_async.tlabel = p[9];
|
||
|
st->msg.send_async.buf = p + SEND_ASYNC_LEN;
|
||
|
|
||
|
(*st->on_read[MSG_SEND_ASYNC])(&st->msg);
|
||
|
|
||
|
sdsrange(st->buf, SEND_ASYNC_LEN + len, sdslen(st->buf));
|
||
|
st->state = PARSE_VERSION_MESSAGE;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool parse_version_message(struct msg_state *st) {
|
||
|
if (sdslen(st->buf) == 0)
|
||
|
return false;
|
||
|
|
||
|
/* Unknown version: ignore byte and continue */
|
||
|
if (st->buf[0] >> 6 != 0)
|
||
|
return true;
|
||
|
|
||
|
st->msgtype = st->buf[0] & 0x3F;
|
||
|
switch (st->msgtype) {
|
||
|
case MSG_SEND_ASYNC:
|
||
|
st->state = PARSE_SEND_ASYNC;
|
||
|
break;
|
||
|
case MSG_SEND_ISO:
|
||
|
st->state = PARSE_SEND_ISO;
|
||
|
break;
|
||
|
case MSG_ALLOCATE:
|
||
|
st->state = PARSE_ALLOCATE;
|
||
|
/* Error or noop */
|
||
|
default:
|
||
|
st->state = PARSE_VERSION_MESSAGE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool parse_allocate(struct msg_state *st) {
|
||
|
if (l < ALLOCATE_LEN)
|
||
|
return false;
|
||
|
st->msg.allocate.start = p[0] << 40 | p[1] << 32 | p[2] << 24 | p[3] << 16
|
||
|
| p[4] << 8 | p[5];
|
||
|
st->msg.allocate.len = p[6] << 40 | p[7] << 32 | p[8] << 24 | p[9] << 16
|
||
|
| p[10] << 8 | p[11];
|
||
|
|
||
|
(*st->on_read[MSG_SEND_ALLOCATE])(&st->msg);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool parse_send_iso(struct msg_state *st) {
|
||
|
const char *p = st->buf + 1;
|
||
|
const size_t l = sdslen(st->buf) - 1;
|
||
|
|
||
|
if (l < SEND_ISO_LEN)
|
||
|
return false;
|
||
|
st->msg.send_iso.len = p[3] << 8 | p[4];
|
||
|
if (l < SEND_ISO_LEN + len)
|
||
|
return false;
|
||
|
|
||
|
st->msg.send_iso.ch = p[0];
|
||
|
st->msg.send_iso.tag = p[1];
|
||
|
st->msg.send_iso.synch = p[2];
|
||
|
st->msg.send_iso.buf = p + SEND_ISO_LEN;
|
||
|
|
||
|
(*st->on_read[MSG_SEND_ASYNC])(&st->msg);
|
||
|
|
||
|
sdsrange(st->buf, SEND_ISO_LEN + len, sdslen(st->buf));
|
||
|
st->state = PARSE_VERSION_MESSAGE;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool parse_packet(struct msg_state *st) {
|
||
|
switch(st->state) {
|
||
|
case PARSE_VERSION_MESSAGE:
|
||
|
return parse_version_message(st);
|
||
|
case PARSE_SEND_ASYNC:
|
||
|
return parse_send_async(st);
|
||
|
case PARSE_ALLOCATE:
|
||
|
return parse_allocate(st);
|
||
|
case PARSE_SEND_ISO:
|
||
|
return parse_send_iso(st);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int sendall(SOCKET sck, unsigned char *msg, size_t msglen) {
|
||
|
int bytes_sent = 0;
|
||
|
do {
|
||
|
int n = send(sck, msg + bytes_sent, msglen - bytes_sent, 0);
|
||
|
if (n == SOCKET_ERROR) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bytes_sent += n;
|
||
|
} while (bytes_sent < msglen);
|
||
|
return 1;
|
||
|
}
|
||
|
int msg_send_alloc(SOCKET sck, uint64_t start, uint64_t len) {
|
||
|
unsigned char *msg;
|
||
|
int r;
|
||
|
|
||
|
msg = malloc(ALLOCATE_LEN);
|
||
|
msg[0] = MSG_ALLOCATE;
|
||
|
msg[1] = start >> 40 & 0xFF;
|
||
|
msg[2] = start >> 32 & 0xFF;
|
||
|
msg[3] = start >> 24 & 0xFF;
|
||
|
msg[4] = start >> 16 & 0xFF;
|
||
|
msg[5] = start >> 8 & 0xFF;
|
||
|
msg[6] = start & 0xFF;
|
||
|
|
||
|
msg[7] = len >> 40 & 0xFF;
|
||
|
msg[8] = len >> 32 & 0xFF;
|
||
|
msg[9] = len >> 24 & 0xFF;
|
||
|
msg[10] = len >> 16 & 0xFF;
|
||
|
msg[11] = len >> 8 & 0xFF;
|
||
|
msg[12] = len & 0xFF;
|
||
|
|
||
|
r = sendall(sck, msg, ALLOCATE_LEN);
|
||
|
free(msg);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int msg_send_async(SOCKET sck, uint16_t bus, uint8_t node, uint64_t addr,
|
||
|
uint8_t tcode, uint8_t tag, uint16_t len, void *data) {
|
||
|
unsigned char *msg;
|
||
|
size_t msglen = SEND_ASYNC_LEN + 1 + len;
|
||
|
int r;
|
||
|
|
||
|
msg = malloc(msglen);
|
||
|
msg[0] = MSG_SEND_ASYNC;
|
||
|
|
||
|
msg[1] = buf >> 8;
|
||
|
msg[2] = (bus & 0x3F << 6) | node;
|
||
|
msg[3] = (addr >> 40) & 0xFF;
|
||
|
msg[4] = (addr >> 32) & 0xFF;
|
||
|
msg[5] = (addr >> 24) & 0xFF;
|
||
|
msg[6] = (addr >> 16) & 0xFF;
|
||
|
msg[7] = (addr >> 8) & 0xFF;
|
||
|
msg[8] = addr & 0xFF;
|
||
|
|
||
|
msg[9] = tcode;
|
||
|
msg[10] = tag;
|
||
|
msg[11] = len >> 8;
|
||
|
msg[12] = len & 0xFF;
|
||
|
|
||
|
if (data)
|
||
|
memcpy(msg + 13, data, len);
|
||
|
|
||
|
r = sendall(sck, msg, msglen);
|
||
|
free(msg);
|
||
|
return r;
|
||
|
}
|