blob: 0b157d0f24cd47306fb1aa6f2292980e5bb2f8d5 [file] [log] [blame]
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "RAS_lib.h"
#define RAS_CMD_MASK 0x07
#define RAS_START_CMD 0x04
#define RAS_DATA_TIC1_CMD 0x01
#define RAS_STOP_CMD 0x02
#define RAS_DATA_RAW_CMD 0x03
#define FRAME_TYPE(data) (data[3] & RAS_CMD_MASK)
#define PDU_LENGTH 20 + 20 + 20 + 20
// read_with_length reads a byte from the provided fd, then reads that many
// bytes into buf, unless more bytes are to be read than size. The number of
// bytes actually read is returned. On error, a value less than 0 is returned.
int read_with_length(int fd, char *buf, int size) {
char to_read;
int len = read(fd, &to_read, 1);
if (len != 1) {
printf("read_with_length: read %d bytes, expecting 1\n", len);
return 0;
}
if (size < to_read) {
printf(
"read_with_length: file wants to read in %d bytes, but there is only "
"space for %d\n",
to_read, size);
// This puts the file in a bad state (the next byte is no longer a length
// byte), but good enough for now.
return -1;
}
len = read(fd, buf, to_read);
if (len < to_read) {
printf("read_with_length: got %d bytes, but wanted %d bytes\n", len, to_read);
return -1;
}
return len;
}
int parse_pdu(char *pdu, int len) {
if (len < 4) {
return 0;
}
int sequence = (pdu[3] >> 3) & 0x1f;
printf("pdu received: sequence %d\n", sequence);
switch(FRAME_TYPE(pdu)) {
case RAS_START_CMD:
printf(" audio start\n");
break;
case RAS_DATA_TIC1_CMD:
printf(" actual audio frame\n");
break;
case RAS_STOP_CMD:
printf(" audio stop\n");
break;
default:
printf(" unhandled pdu frame_type=%d\n", FRAME_TYPE(pdu));
break;
}
return 1;
}
struct pdu_accumulator {
int seen_first_packet;
int cur_idx;
char pdu[PDU_LENGTH];
};
void reset_pdu_accumulator(struct pdu_accumulator *a) {
a->seen_first_packet = 0;
a->cur_idx = 0;
memset(&(a->pdu), 0, PDU_LENGTH);
}
// accumulate_pdu accepts one 23 byte packet from the device, and returns true
// if a complete PDU has been assembled.
int accumulate_pdu(struct pdu_accumulator *a, char data[23]) {
// printf("seen_first=%d cur_idx=%d\n", a->seen_first_packet, a->cur_idx);
if(!a->seen_first_packet) {
if(FRAME_TYPE(data) == RAS_DATA_TIC1_CMD) {
a->seen_first_packet = 1;
a->cur_idx++;
memcpy(a->pdu, data, 23);
} else {
printf(" ignoring unexpected packet (type %d)\n", FRAME_TYPE(data));
}
return 0;
}
if(a->seen_first_packet) {
// if(FRAME_TYPE(data) != RAS_DATA_RAW_CMD) {
// printf("expecting raw data, but got frame type %d\n", FRAME_TYPE(data));
// reset_pdu_accumulator(a);
// return 0;
// }
// copy everything but the first 3 bytes into the result packet 0, read
// above, is 23 bytes. the next 3 are 20 bytes (with the first 3 bytes
// ignored). those 4 packets make a complete PDU.
if(a->cur_idx > 0 && a->cur_idx < 4) {
memcpy(&(a->pdu[a->cur_idx*20]), &data[3], 20);
a->cur_idx++;
} else {
printf(" cur_idx %d out of range\n", a->cur_idx);
}
}
return a->cur_idx > 3;
}
int main(int argc, char **argv) {
// TI ignores the error code from RAS_Init. I will too, I guess.
RAS_Init(1);
int input = open("out", O_RDONLY);
if (input < 0) {
perror("open ./out");
return 1;
}
struct pdu_accumulator a;
reset_pdu_accumulator(&a);
char data[64];
chunk:
while (1) {
int read = read_with_length(input, data, sizeof(data));
if (read < 1) {
return 1;
}
// printf("read %d bytes\n", read);
switch (read) {
case 4:
parse_pdu(data, read);
reset_pdu_accumulator(&a);
break;
case 23:
if(accumulate_pdu(&a, data)) {
parse_pdu(a.pdu, PDU_LENGTH);
reset_pdu_accumulator(&a);
}
break;
}
}
return 0;
}