blob: f58c8758197d72ae0ea12bb33135bd30a2864776 [file] [log] [blame]
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <osmocom/core/msgb.h>
#include "framing.h"
#include "protocol.h"
#include "serial.h"
#include "config.h"
char *DumpBYTEs(unsigned char *p, long n, int nBytesPerRow /* = 16 */, char *szLineSep /* = "\n" */, int bRaw /* = FALSE */, const char *szIndent /* = "" */)
{
long i;
char szBuf[20];
static char szRes[4 * 1024];
szRes[0] = 0;
if(n == 0)
return szRes;
memset(szBuf, 0, sizeof(szBuf));
for(i = 0; i < n; i++)
{
if(i % nBytesPerRow == 0)
{
strcat(szRes, szIndent);
if(!bRaw)
sprintf(szRes + strlen(szRes), "%04d : ", i);
}
sprintf(szRes + strlen(szRes), "%02X ", p[i]);
szBuf[i % nBytesPerRow] = (char)((p[i] < 128 && p[i] >= ' ') ? p[i] : '.');
if((i + 1) % nBytesPerRow == 0)
{
if(bRaw)
sprintf(szRes + strlen(szRes), "%s", szLineSep);
else
sprintf(szRes + strlen(szRes), " %s%s", szBuf, szLineSep);
memset(szBuf, 0, sizeof(szBuf));
}
}
if(i % nBytesPerRow != 0)
{
if(bRaw)
sprintf(szRes + strlen(szRes), "%s", szLineSep);
else
{
n = nBytesPerRow - i % nBytesPerRow;
for(i = 0; i < n ; i++)
sprintf(szRes + strlen(szRes), " ");
sprintf(szRes + strlen(szRes), " %s%s", szBuf, szLineSep);
}
}
return szRes;
}
static int transmit_msgb(int fd, struct msgb *msg)
{
int out_len, rc;
uint8_t packet[MAX_PACKET * 2];
out_len = frame_pack(msgb_data(msg), msgb_length(msg),
packet, sizeof(packet));
if (out_len < 0) {
printf("Failed to pack packet\n");
return -1;
}
rc = write(fd, packet, out_len);
if (rc != out_len) {
printf("Short write on packet.\n");
return -1;
}
msgb_free(msg);
return 0;
}
static int transmit_packet(int fd, const uint8_t *data, size_t data_len)
{
int out_len, rc;
uint8_t packet[MAX_PACKET * 2];
out_len = frame_pack(data, data_len, packet, sizeof(packet));
if (out_len < 0) {
printf("Failed to pack packet\n");
return -1;
}
rc = write(fd, packet, out_len);
if (rc != out_len) {
printf("Short write on packet.\n");
return -1;
}
return 0;
}
static int dump_log(const uint8_t *data, const size_t len)
{
size_t i, file_len;
size_t params = 0;
const struct ext_log_msg *msg;
const char *file = NULL, *log;
struct tm *tm;
time_t now;
const size_t str_len = len - offsetof(struct ext_log_msg, data);
time(&now);
tm = localtime(&now);
if (len < sizeof(struct ext_log_msg)) {
printf("too short log message.\n");
return -1;
}
msg = (struct ext_log_msg *) data;
log = (const char *) msg->data;
/*
* Check if it is null terminated and how many parameters it
* might have. This counts all '%' but doesn't take '%%' into
* account.
*/
for (i = 0; i < str_len; ++i) {
if (log[i] == '%')
params += 1;
else if (log[i] == '\0' && i + 1 < str_len) {
file = &log[i + 1];
file_len = str_len - i - 1;
break;
}
}
if (file_len == 0 || file[file_len - 1] != '\0') {
printf("File too short or not null terminated\n");
return -2;
}
if (params > 3) {
printf("Too many parameters in the log message.\n");
return -1;
}
if (!file) {
printf("The file is not present..\n");
return -2;
}
printf("%.2d:%.2d:%.2d %-20s: ",
tm->tm_hour, tm->tm_min, tm->tm_sec,
file);
printf(log, msg->params[0], msg->params[1], msg->params[2]);
printf("\n");
return 0;
}
static int do_read(int fd, uint8_t *data)
{
uint8_t buf[MAX_PACKET];
int rc;
rc = read(fd, buf, sizeof(buf));
if (rc <= 0 ) {
printf("Short read!\n");
exit(EXIT_FAILURE);
}
rc = frame_unpack(buf, rc, data);
if (rc <= 0)
return 0;
switch (data[0]) {
case 0x79:
dump_log(data, rc);
break;
default:
printf("Got %d data of payload\n", rc);
printf("%s\n", DumpBYTEs(data, rc, 16, "\n", 0, ""));
break;
};
return rc;
}
static void do_configure(int fd)
{
static uint8_t timestamp[] = { 0x1D };
#if 0
static const uint8_t enable_evt_report[] = {
0x60, 0x01
};
#endif
static const uint8_t disable_evt_report[] = {
0x60, 0x00
};
static const uint8_t extended_report_cfg[] = {
0x7D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
};
uint8_t data[MAX_PACKET];
/* TODO: introduce a wait for response kind of method */
transmit_packet(fd, timestamp, sizeof(timestamp));
do_read(fd, data);
/* enable|disable the event report */
#if 0
transmit_packet(fd, enable_evt_report, sizeof(enable_evt_report));
do_read(fd, data);
#endif
transmit_packet(fd, disable_evt_report, sizeof(disable_evt_report));
do_read(fd, data);
transmit_packet(fd, extended_report_cfg, sizeof(extended_report_cfg));
do_read(fd, data);
struct msgb *msg = gen_log_config_set_mask(1064);
log_config_set_mask_bit(msg, 306);
log_config_set_mask_bit(msg, 544);
log_config_set_mask_bit(msg, 545);
log_config_set_mask_bit(msg, 546);
log_config_set_mask_bit(msg, 547);
log_config_set_mask_bit(msg, 553);
transmit_msgb(fd, msg);
}
int main(int argc, char **argv)
{
uint8_t data[MAX_PACKET];
int flags;
int fd, rc;
if (argc < 2) {
printf("Invoke with %s PATH_TO_SERIAL\n",
argv[0]);
return EXIT_FAILURE;
}
/* Use nonblock as the device might block otherwise */
fd = open(argv[1], O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
if (fd < 0) {
printf("Opening the serial failed: %d/%s\n",
errno, strerror(errno));
return EXIT_FAILURE;
}
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
printf("Failed to get the flags.\n");
return EXIT_FAILURE;
}
flags &= ~O_NONBLOCK;
rc = fcntl(fd, F_SETFL, flags);
if (rc != 0) {
printf("Failed to set the flags.\n");
return EXIT_FAILURE;
}
rc = serial_configure(fd);
if (rc != 0)
return EXIT_FAILURE;
do_configure(fd);
while (1)
do_read(fd, data);
}