| |
| #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); |
| } |