#include #include #include #include #include #include #include #include #include #include "replace.h" #include "interface.h" #include "ap_host/src/protocol.h" extern "C" { // this is not declared in qurt headers void HAP_debug(const char *msg, int level, const char *filename, int line); void HAP_printf(const char *file, int line, const char *format, ...) { va_list ap; char buf[300]; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); HAP_debug(buf, 0, file, line); //usleep(20000); } /** QURT doesn't have strnlen() **/ size_t strnlen(const char *s, size_t max) { size_t len; for (len = 0; len < max; len++) { if (s[len] == '\0') { break; } } return len; } int vasprintf(char **ptr, const char *format, va_list ap) { int ret; va_list ap2; va_copy(ap2, ap); ret = vsnprintf(nullptr, 0, format, ap2); va_end(ap2); if (ret < 0) { return ret; } (*ptr) = (char *)malloc(ret+1); if (!*ptr) { return -1; } va_copy(ap2, ap); ret = vsnprintf(*ptr, ret+1, format, ap2); va_end(ap2); return ret; } int asprintf(char **ptr, const char *format, ...) { va_list ap; int ret; *ptr = nullptr; va_start(ap, format); ret = vasprintf(ptr, format, ap); va_end(ap); return ret; } void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { if (needlelen == 0) { return const_cast(haystack); } while (haystacklen >= needlelen) { char *p = (char *)memchr(haystack, *(const char *)needle, haystacklen-(needlelen-1)); if (!p) { return NULL; } if (memcmp(p, needle, needlelen) == 0) { return p; } haystack = p+1; haystacklen -= (p - (const char *)haystack) + 1; } return NULL; } char *strndup(const char *s, size_t n) { char *ret; n = strnlen(s, n); ret = (char*)malloc(n+1); if (!ret) { return NULL; } memcpy(ret, s, n); ret[n] = 0; return ret; } int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr) { return 0; } // INVESTIGATE: What is this needed on QURT? int apfs_rename(const char *oldpath, const char *newpath) { return 0; } // INVESTIGATE: Seems important :-) int ArduPilot_main(int argc, const char *argv[]) { return 0; } char *__wrap_strdup(const char *s); } extern "C" int qurt_ardupilot_main(int argc, char* const argv[]); int slpi_link_client_init(void) { HAP_PRINTF("About to call qurt_ardupilot_main %p", &qurt_ardupilot_main); qurt_ardupilot_main(0, NULL); return 0; } typedef void (*mavlink_data_callback_t)(const struct qurt_rpc_msg *msg, void* p); static mavlink_data_callback_t mav_cb; static void *mav_cb_ptr; static uint32_t expected_seq; void register_mavlink_data_callback(mavlink_data_callback_t func, void *p) { mav_cb = func; mav_cb_ptr = p; } int slpi_link_client_receive(const uint8_t *data, int data_len_in_bytes) { if (data_len_in_bytes < QURT_RPC_MSG_HEADER_LEN) { return 0; } const auto *msg = (struct qurt_rpc_msg *)data; if (msg->data_length + QURT_RPC_MSG_HEADER_LEN != data_len_in_bytes) { return 0; } if (msg->seq != expected_seq) { HAP_PRINTF("Bad sequence %u %u", msg->seq, expected_seq); } expected_seq = msg->seq + 1; switch (msg->msg_id) { case QURT_MSG_ID_MAVLINK_MSG: { if (mav_cb) { mav_cb(msg, mav_cb_ptr); } break; } default: HAP_PRINTF("Got unknown message id %d", msg->msg_id); break; } return 0; } int __wrap_printf(const char *fmt, ...) { va_list ap; char buf[300]; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); HAP_PRINTF(buf); return 0; } /* free() on strdup return on QURT causes a memory fault */ char *__wrap_strdup(const char *s) { return strndup(s, strlen(s)); } /* send a RPC message to the host */ bool qurt_rpc_send(struct qurt_rpc_msg &msg) { if (msg.data_length > sizeof(msg.data)) { return false; } return sl_client_send_data((const uint8_t*)&msg, msg.data_length + QURT_RPC_MSG_HEADER_LEN) >= 0; }