2024-07-05 20:07:40 -03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#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<void*>(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;
|
|
|
|
}
|
|
|
|
|
2024-07-12 21:45:16 -03:00
|
|
|
typedef void (*mavlink_data_callback_t)(const struct qurt_rpc_msg *msg, void* p);
|
2024-07-05 20:07:40 -03:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2024-07-12 21:45:16 -03:00
|
|
|
if (data_len_in_bytes < QURT_RPC_MSG_HEADER_LEN) {
|
2024-07-05 20:07:40 -03:00
|
|
|
return 0;
|
|
|
|
}
|
2024-07-12 21:45:16 -03:00
|
|
|
const auto *msg = (struct qurt_rpc_msg *)data;
|
|
|
|
if (msg->data_length + QURT_RPC_MSG_HEADER_LEN != data_len_in_bytes) {
|
2024-07-05 20:07:40 -03:00
|
|
|
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));
|
|
|
|
}
|
2024-07-12 21:45:16 -03:00
|
|
|
|
|
|
|
/*
|
|
|
|
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;
|
|
|
|
}
|