/* * IOTC Bridge — ARM32 process that loads the TUTK library and * communicates with the Python TUI over stdin/stdout JSON. * * Compile: arm-linux-gnueabi-gcc -o iotc_bridge iotc_bridge.c -L../lib -lIOTCAPIs_ALL -lpthread -ldl * Run: qemu-arm-static -L /usr/arm-linux-gnueabi ./iotc_bridge */ #include #include #include #include #include /* IOTC API declarations (from IOTCAPIs.h) */ extern int IOTC_Initialize2(int udp_port); extern int IOTC_DeInitialize(void); extern int IOTC_Get_SessionID(void); extern int IOTC_Connect_ByUID_Parallel(const char *UID, int SID); extern int IOTC_Session_Close(int SID); extern int IOTC_Session_Check(int SID, void *info); extern int IOTC_Lan_Search2(void *result, int max, int timeout_ms); /* AV API declarations (from AVAPIs.h) */ extern int avInitialize(int max_channels); extern int avDeInitialize(void); extern int avClientStart(int SID, const char *user, const char *pass, int timeout, unsigned int *srvtype, int channel); extern void avClientStop(int avIndex); extern int avSendIOCtrl(int avIndex, int type, const char *data, int len); extern int avRecvIOCtrl(int avIndex, int *type, char *data, int len, int timeout_ms); /* Simple JSON output helpers */ static void json_ok(const char *key, int value) { printf("{\"ok\":true,\"%s\":%d}\n", key, value); fflush(stdout); } static void json_ok_str(const char *key, const char *value) { printf("{\"ok\":true,\"%s\":\"%s\"}\n", key, value); fflush(stdout); } static void json_err(const char *msg) { printf("{\"ok\":false,\"error\":\"%s\"}\n", msg); fflush(stdout); } static void json_data(const char *cmd, const unsigned char *data, int len) { printf("{\"ok\":true,\"cmd\":\"%s\",\"len\":%d,\"hex\":\"", cmd, len); for (int i = 0; i < len && i < 4096; i++) printf("%02x", data[i]); printf("\"}\n"); fflush(stdout); } /* State */ static int g_sid = -1; static int g_av_index = -1; static int g_initialized = 0; static int do_init(void) { if (g_initialized) { json_err("already initialized"); return -1; } int ret = IOTC_Initialize2(0); if (ret < 0) { char buf[64]; snprintf(buf, sizeof(buf), "IOTC_Initialize2 failed: %d", ret); json_err(buf); return ret; } ret = avInitialize(16); if (ret < 0) { char buf[64]; snprintf(buf, sizeof(buf), "avInitialize failed: %d", ret); json_err(buf); return ret; } g_initialized = 1; json_ok("init", 0); return 0; } static int do_connect(const char *uid) { if (!g_initialized) { json_err("not initialized"); return -1; } int sid = IOTC_Get_SessionID(); if (sid < 0) { char buf[64]; snprintf(buf, sizeof(buf), "IOTC_Get_SessionID failed: %d", sid); json_err(buf); return sid; } g_sid = IOTC_Connect_ByUID_Parallel(uid, sid); if (g_sid < 0) { char buf[64]; snprintf(buf, sizeof(buf), "connect failed: %d", g_sid); json_err(buf); return g_sid; } json_ok("sid", g_sid); return g_sid; } static int do_login(const char *user, const char *pass) { if (g_sid < 0) { json_err("not connected"); return -1; } unsigned int srvtype = 0; g_av_index = avClientStart(g_sid, user, pass, 20, &srvtype, 0); if (g_av_index < 0) { char buf[64]; snprintf(buf, sizeof(buf), "avClientStart failed: %d", g_av_index); json_err(buf); return g_av_index; } json_ok("av_index", g_av_index); return g_av_index; } static int do_ioctrl(int cmd_type, const char *hex_data) { if (g_av_index < 0) { json_err("not logged in"); return -1; } /* Parse hex data */ int hex_len = strlen(hex_data); int data_len = hex_len / 2; unsigned char *data = calloc(1, data_len + 1); for (int i = 0; i < data_len; i++) { unsigned int byte; sscanf(hex_data + i * 2, "%2x", &byte); data[i] = (unsigned char)byte; } int ret = avSendIOCtrl(g_av_index, cmd_type, (const char *)data, data_len); free(data); if (ret < 0) { char buf[64]; snprintf(buf, sizeof(buf), "avSendIOCtrl failed: %d", ret); json_err(buf); return ret; } /* Try to receive response */ unsigned char resp[8192]; int resp_type = 0; int resp_len = avRecvIOCtrl(g_av_index, &resp_type, (char *)resp, sizeof(resp), 5000); if (resp_len > 0) { json_data("ioctrl_resp", resp, resp_len); } else { json_ok("sent", cmd_type); } return 0; } static int do_lan_search(void) { if (!g_initialized) { json_err("not initialized"); return -1; } /* Search result struct: 84 bytes per entry (UID[20] + IP[16] + ...)] */ unsigned char results[84 * 16]; memset(results, 0, sizeof(results)); int count = IOTC_Lan_Search2(results, 16, 3000); if (count < 0) { char buf[64]; snprintf(buf, sizeof(buf), "lan_search failed: %d", count); json_err(buf); return count; } printf("{\"ok\":true,\"count\":%d,\"devices\":[", count); for (int i = 0; i < count; i++) { unsigned char *entry = results + (i * 84); char uid[21] = {0}; memcpy(uid, entry, 20); if (i > 0) printf(","); printf("\"%s\"", uid); } printf("]}\n"); fflush(stdout); return count; } static void do_disconnect(void) { if (g_av_index >= 0) { avClientStop(g_av_index); g_av_index = -1; } if (g_sid >= 0) { IOTC_Session_Close(g_sid); g_sid = -1; } json_ok("disconnected", 1); } static void do_deinit(void) { do_disconnect(); if (g_initialized) { avDeInitialize(); IOTC_DeInitialize(); g_initialized = 0; } json_ok("deinit", 1); } int main(int argc, char *argv[]) { char line[8192]; fprintf(stderr, "IOTC Bridge started. Send JSON commands on stdin.\n"); while (fgets(line, sizeof(line), stdin)) { /* Strip newline */ line[strcspn(line, "\r\n")] = 0; if (strlen(line) == 0) continue; /* Very simple command parsing: cmd arg1 arg2 ... */ char cmd[64] = {0}; char arg1[256] = {0}; char arg2[256] = {0}; char arg3[8192] = {0}; sscanf(line, "%63s %255s %255s %8191s", cmd, arg1, arg2, arg3); if (strcmp(cmd, "init") == 0) { do_init(); } else if (strcmp(cmd, "connect") == 0) { if (strlen(arg1) == 0) { json_err("usage: connect "); } else { do_connect(arg1); } } else if (strcmp(cmd, "login") == 0) { if (strlen(arg1) == 0 || strlen(arg2) == 0) { json_err("usage: login "); } else { do_login(arg1, arg2); } } else if (strcmp(cmd, "ioctrl") == 0) { if (strlen(arg1) == 0) { json_err("usage: ioctrl [hex_data]"); } else { int cmd_id = atoi(arg1); do_ioctrl(cmd_id, strlen(arg2) > 0 ? arg2 : ""); } } else if (strcmp(cmd, "search") == 0) { do_lan_search(); } else if (strcmp(cmd, "disconnect") == 0) { do_disconnect(); } else if (strcmp(cmd, "quit") == 0 || strcmp(cmd, "exit") == 0) { do_deinit(); break; } else if (strcmp(cmd, "help") == 0) { printf("{\"commands\":[\"init\",\"connect \",\"login \",\"ioctrl [hex]\",\"search\",\"disconnect\",\"quit\"]}\n"); fflush(stdout); } else { json_err("unknown command"); } } do_deinit(); return 0; }