From a915c1c944938f332e70aff8927f19b6e381eeea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 9 Nov 2015 20:01:37 +0100 Subject: initial checkin of some c-language code to parse Sierra Wireless HAPC --- Makefile | 17 ++++++++++ hapc_frame.c | 49 +++++++++++++++++++++++++++ hapc_frame.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hapc_test.c | 55 ++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 Makefile create mode 100644 hapc_frame.c create mode 100644 hapc_frame.h create mode 100644 hapc_test.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3b6153c --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +OSMO_CFLAGS:=`pkg-config --cflags libosmocore` +OSMO_LDFLAGS:=`pkg-config --libs libosmocore` + +CFLAGS=-g -Wall $(OSMO_CFLAGS) +LDFLAGS=$(OSMO_LDFLAGS) + +all: hapc_test + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + + +hapc_test: hapc_test.o hapc_frame.o + $(CC) $(LDFLAGS) -o $@ $^ + +clean: + rm -f hapc_test *.o || true diff --git a/hapc_frame.c b/hapc_frame.c new file mode 100644 index 0000000..1469b60 --- /dev/null +++ b/hapc_frame.c @@ -0,0 +1,49 @@ +#include + +#include "hapc_frame.h" + +const struct value_string hapc_flow_names[30] = { + { HAPC_FLOW_STATUS, "status" }, + { HAPC_FLOW_DEBUG, "debug" }, + { HAPC_FLOW_INIT, "init" }, + { HAPC_FLOW_WI2C, "wi2c" }, + { HAPC_FLOW_TRACE, "trace" }, + { HAPC_FLOW_RI2C, "ri2c" }, + { HAPC_FLOW_MSG, "msg" }, + { HAPC_FLOW_GDB, "gdb" }, + { HAPC_FLOW_READ, "read" }, + { HAPC_FLOW_READ_PACK, "read-pack" }, + { HAPC_FLOW_WRITE, "write" }, + { HAPC_FLOW_OBJECT, "object" }, + { HAPC_FLOW_RESET, "reset" }, + { HAPC_FLOW_PROTOCOL, "protocol" }, + { HAPC_FLOW_EEPROM, "eeprom" }, + { HAPC_FLOW_EEPROM2, "eeprom2" }, + { HAPC_FLOW_FS, "filesystem" }, + { HAPC_FLOW_MSG2, "msg2" }, + { HAPC_FLOW_KBD, "kbd" }, + { HAPC_FLOW_WATCH, "watch" }, + { HAPC_FLOW_DIAG, "diag" }, + { HAPC_FLOW_RTK, "rtk" }, + { HAPC_FLOW_RPC2, "rpc2" }, + { HAPC_FLOW_PROD, "prod" }, + { HAPC_FLOW_RADIO, "radio" }, + { HAPC_FLOW_AT, "at" }, + { HAPC_FLOW_TRACE_TSTP, "trace" }, + { HAPC_FLOW_DUMP, "dump" }, + { HAPC_FLOW_ATENCAP, "atencap" }, + { 0, NULL } +}; + +const struct value_string hapc_obj_status_names[9] = { + { HAPC_OBJ_READ_REQ, "read-req" }, + { HAPC_OBJ_READ_RESP, "read-resp" }, + { HAPC_OBJ_WRITE_REQ, "write-req" }, + { HAPC_OBJ_WRITE_RESP, "write-resp" }, + { HAPC_OBJ_ID_LIST_REQ, "id-list-req" }, + { HAPC_OBJ_ID_LIST_RESP,"id-list-resp" }, + { HAPC_OBJ_DEL_REQ, "delete-req" }, + { HAPC_OBJ_DEL_RESP, "delete-resp" }, + { 0, NULL } +}; + diff --git a/hapc_frame.h b/hapc_frame.h new file mode 100644 index 0000000..96a81b6 --- /dev/null +++ b/hapc_frame.h @@ -0,0 +1,109 @@ +#pragma once + +#include + +enum hapc_flow_id { + HAPC_FLOW_STATUS = 0x00, + HAPC_FLOW_DEBUG = 0x01, + HAPC_FLOW_INIT = 0x02, + HAPC_FLOW_WI2C = 0x03, + HAPC_FLOW_TRACE = 0x04, + HAPC_FLOW_RI2C = 0x05, + HAPC_FLOW_MSG = 0x06, + HAPC_FLOW_GDB = 0x07, + HAPC_FLOW_READ = 0x08, + HAPC_FLOW_READ_PACK = 0x09, + HAPC_FLOW_WRITE = 0x0A, + HAPC_FLOW_OBJECT = 0x0B, + HAPC_FLOW_RESET = 0x0C, + HAPC_FLOW_PROTOCOL = 0x0D, + HAPC_FLOW_EEPROM = 0x0E, + HAPC_FLOW_EEPROM2 = 0x0F, + HAPC_FLOW_FS = 0x10, + HAPC_FLOW_MSG2 = 0x11, + HAPC_FLOW_KBD = 0x12, + HAPC_FLOW_WATCH = 0x14, + HAPC_FLOW_DIAG = 0x16, + HAPC_FLOW_RTK = 0x18, + HAPC_FLOW_RPC2 = 0x19, + HAPC_FLOW_PROD = 0x1A, + HAPC_FLOW_RADIO = 0x1C, + HAPC_FLOW_AT = 0x1D, + HAPC_FLOW_TRACE_TSTP = 0x1E, + HAPC_FLOW_DUMP = 0x20, + HAPC_FLOW_ATENCAP = 0x9F, +}; + +/* HAPC frame format: + * first byte: 0xAA + * 2nd byte: LSB of length + * 3rd byte: MSB of length (3 lower bits) + flow-id (5 upper bits) + * N bytes payload + * 2 bytes of checksum + */ + +/* common HAPC header */ +struct hapc_msg_hdr { + uint8_t aa; + uint8_t lsb_len; + uint8_t msb_len:3, + flow_id:5; + uint8_t data[0]; +} __attribute__ ((packed)); + +#define hapc_payload_len(x) ((x)->msb_len << 8 | (x)->lsb_len) + +static inline uint8_t hapc_frame_csum(const struct hapc_msg_hdr *mh) +{ + unsigned int payload_len = hapc_payload_len(mh); + + return mh->data[payload_len]; +} + +enum hapc_obj_status_id { + HAPC_OBJ_READ_REQ = 0x01, + HAPC_OBJ_READ_RESP = 0x02, + HAPC_OBJ_READ_RESP2 = 0x82, + HAPC_OBJ_WRITE_REQ = 0x03, + HAPC_OBJ_WRITE_RESP = 0x04, + HAPC_OBJ_WRITE_RESP2 = 0x84, + HAPC_OBJ_ID_LIST_REQ = 0x05, + HAPC_OBJ_ID_LIST_RESP = 0x06, + HAPC_OBJ_ID_LIST_RESP2 = 0x86, + HAPC_OBJ_DEL_REQ = 0x07, + HAPC_OBJ_DEL_RESP = 0x08, + HAPC_OBJ_DEL_RESP2 = 0x88, +}; + +/* uses HAPC_FLOW_OBJECT */ +struct hapc_flash_obj_hdr { + uint32_t obj_id; + uint32_t mask; + uint16_t total_size; + uint16_t block_size; + uint16_t offset_block; + uint8_t obj_status; + uint8_t data[0]; +} __attribute__ ((packed)); + + +/* uses HAPC_FLOW_READ_PACK */ +struct hapc_ram_read { + uint32_t start_addr; + uint16_t len; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* uses HAPC_FLOW_WRITE */ +struct hapc_ram_write { + uint8_t pad0[8]; + uint32_t start_addr; + uint16_t len; + uint8_t pad1[2]; + uint8_t data[0]; +} __attribute__ ((packed)); + +#include + +extern const struct value_string hapc_flow_names[30]; +const struct value_string hapc_obj_status_names[9]; diff --git a/hapc_test.c b/hapc_test.c new file mode 100644 index 0000000..a240c14 --- /dev/null +++ b/hapc_test.c @@ -0,0 +1,55 @@ +#include + +#include "hapc_frame.h" + +const uint8_t test_frame[] = { 0xAA, 0x10, 0x58, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13 }; +const uint8_t resp_frame[] = { 0xAA, 0x20, 0x58, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x82, + 0x18, 0x81, 0x00, 0x00, 0x20, 0x03, 0x00, 0x09, 0x08, 0x91, 0x94, 0x58, 0x16, 0x89, 0x63, 0x07, 0xf2, 0x0d }; + +static void dump_frame_object(const struct hapc_flash_obj_hdr *foh, unsigned int len) +{ + unsigned int payload_len = len - sizeof(*foh); + printf("obj_id=0x%08x, mask=0x%08x, total_size=%d, block_size=%d, offset_block=%d, status=%s, data=%s\n", + foh->obj_id, foh->mask, foh->total_size, foh->block_size, foh->offset_block, + get_value_string(hapc_obj_status_names, foh->obj_status & 0x7f), osmo_hexdump(foh->data, payload_len)); +} + +static uint8_t compute_checksum(const uint8_t *data, unsigned int len) +{ + unsigned int i; + uint8_t checksum = 0; + + for (i = 0; i < len; i++) + checksum += data[i]; + + return checksum; +} + +void dump_frame(const struct hapc_msg_hdr *hdr) +{ + unsigned int len = hapc_payload_len(hdr); + + printf("len=%4u, flow_id=%s: ", len, + get_value_string(hapc_flow_names, hdr->flow_id)); + + printf("checksum=0x%02x, computed=0x%02x\n", + hapc_frame_csum(hdr), compute_checksum((const uint8_t *) hdr, sizeof(*hdr)+len)); + + switch (hdr->flow_id) { + case HAPC_FLOW_OBJECT: + dump_frame_object((const struct hapc_flash_obj_hdr *) hdr->data, len - sizeof(*hdr)); + break; + default: + printf("\n"); + break; + } +} + +int main(int argc, char **argv) +{ + const struct hapc_msg_hdr *hdr = (const struct hapc_msg_hdr *) test_frame; + dump_frame(hdr); + + hdr = (const struct hapc_msg_hdr *) resp_frame; + dump_frame(hdr); +} -- cgit v1.2.3