diff --git a/chrecd/interface/chre_slpi.c b/chrecd/interface/chre_slpi.c
new file mode 100644
index 0000000..450a476
--- /dev/null
+++ b/chrecd/interface/chre_slpi.c
@@ -0,0 +1,39 @@
+/*
+ * Context Hub Runtime Environment interface - method definitions
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+const struct hrpc_method_def_interp4 chre_slpi_start_thread_def = {
+ .msg_id = 0,
+ .n_args = 0,
+ .args = NULL,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+const struct hrpc_method_def_interp4 chre_slpi_wait_on_thread_exit_def = {
+ .msg_id = 1,
+ .n_args = 0,
+ .args = NULL,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/chrecd/interface/chre_slpi.h b/chrecd/interface/chre_slpi.h
new file mode 100644
index 0000000..4c33b68
--- /dev/null
+++ b/chrecd/interface/chre_slpi.h
@@ -0,0 +1,41 @@
+/*
+ * Context Hub Runtime Environment interface - API
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INTERFACE_CHRE_SLPI_H
+#define INTERFACE_CHRE_SLPI_H
+
+#include
+#include
+
+extern struct hrpc_method_def_interp4 chre_slpi_start_thread_def;
+static inline int chre_slpi_start_thread(int fd, uint32_t hdl)
+{
+ return hexagonrpc(&chre_slpi_start_thread_def, fd, hdl);
+}
+
+extern struct hrpc_method_def_interp4 chre_slpi_wait_on_thread_exit_def;
+static inline int chre_slpi_wait_on_thread_exit(int fd, uint32_t hdl)
+{
+ return hexagonrpc(&chre_slpi_wait_on_thread_exit_def, fd, hdl);
+}
+
+
+#endif /* INTERFACE_CHRE_SLPI_H */
diff --git a/chrecd/interfaces/chre_slpi.def b/chrecd/interfaces/chre_slpi.def
deleted file mode 100644
index d9aaeff..0000000
--- a/chrecd/interfaces/chre_slpi.def
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Context Hub Runtime Environment interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_CHRE_SLPI_DEF
-#define INTERFACE_CHRE_SLPI_DEF
-
-#include
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(0, chre_slpi_start_thread, 0, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(1, chre_slpi_wait_on_thread_exit, 0, 0, 0, 0)
-
-#endif /* INTERFACE_CHRE_SLPI_DEF */
diff --git a/chrecd/main.c b/chrecd/main.c
index 3dadc40..7eed53d 100644
--- a/chrecd/main.c
+++ b/chrecd/main.c
@@ -20,105 +20,42 @@
*/
#include
-#include
-#include
+#include
#include
#include
#include
#include
-#include "interfaces/chre_slpi.def"
-
-/* TODO move these to libhexagonrpc since most clients use them */
-static int remotectl_open(int fd, char *name, struct fastrpc_context **ctx, void (*err_cb)(const char *err))
-{
- uint32_t handle;
- int32_t dlret;
- char err[256];
- int ret;
-
- ret = fastrpc2(&remotectl_open_def, fd, REMOTECTL_HANDLE,
- strlen(name) + 1, name,
- &handle,
- &dlret,
- 256, err);
-
- if (ret == -1) {
- err_cb(strerror(errno));
- return ret;
- }
-
- if (dlret == -5) {
- err_cb(err);
- return dlret;
- }
-
- *ctx = fastrpc_create_context(fd, handle);
-
- return ret;
-}
-
-static int remotectl_close(struct fastrpc_context *ctx, void (*err_cb)(const char *err))
-{
- uint32_t dlret;
- char err[256];
- int ret;
-
- ret = fastrpc2(&remotectl_close_def, ctx->fd, REMOTECTL_HANDLE,
- ctx->handle,
- &dlret,
- 256, err);
-
- if (ret == -1) {
- err_cb(strerror(errno));
- return ret;
- }
-
- fastrpc_destroy_context(ctx);
-
- return ret;
-}
-
-static void remotectl_err(const char *err)
-{
- fprintf(stderr, "Could not remotectl: %s\n", err);
-}
-
-static int chre_slpi_start_thread(struct fastrpc_context *ctx)
-{
- return fastrpc(&chre_slpi_start_thread_def, ctx);
-}
-
-static int chre_slpi_wait_on_thread_exit(struct fastrpc_context *ctx)
-{
- return fastrpc(&chre_slpi_wait_on_thread_exit_def, ctx);
-}
+#include "interface/chre_slpi.h"
int main()
{
- struct fastrpc_context *ctx;
+ uint32_t hdl;
+ char err[256];
int fd, ret;
fd = hexagonrpc_fd_from_env();
if (fd == -1)
return 1;
- ret = remotectl_open(fd, "chre_slpi", &ctx, remotectl_err);
- if (ret)
+ ret = hexagonrpc_open(fd, "chre_slpi", &hdl, 256, err);
+ if (ret) {
+ fprintf(stderr, "Could not open CHRE remote interface: %s\n", err);
return 1;
+ }
- ret = chre_slpi_start_thread(ctx);
+ ret = chre_slpi_start_thread(fd, hdl);
if (ret) {
fprintf(stderr, "Could not start CHRE\n");
goto err;
}
- ret = chre_slpi_wait_on_thread_exit(ctx);
+ ret = chre_slpi_wait_on_thread_exit(fd, hdl);
if (ret) {
fprintf(stderr, "Could not wait for CHRE thread\n");
goto err;
}
err:
- remotectl_close(ctx, remotectl_err);
+ hexagonrpc_close(fd, hdl);
}
diff --git a/chrecd/meson.build b/chrecd/meson.build
index 983d742..2108a79 100644
--- a/chrecd/meson.build
+++ b/chrecd/meson.build
@@ -1,5 +1,5 @@
executable('chrecd',
- 'interfaces.c',
+ 'interface/chre_slpi.c',
'main.c',
c_args : cflags,
include_directories : include,
diff --git a/hexagonrpcd/apps_mem.c b/hexagonrpcd/apps_mem.c
index f4d0bf9..1477f0b 100644
--- a/hexagonrpcd/apps_mem.c
+++ b/hexagonrpcd/apps_mem.c
@@ -20,15 +20,15 @@
*/
#include
+#include
#include
#include
#include
#include
#include
-#include "aee_error.h"
#include "apps_mem.h"
-#include "interfaces/apps_mem.def"
+#include "interface/apps_mem.h"
#include "listener.h"
// See fastrpc.git/src/apps_mem_imp.c
@@ -71,11 +71,9 @@ static uint32_t apps_mem_request_map64(void *data,
mmap.size = first_in->len;
ret = ioctl(ctx->fd, FASTRPC_IOCTL_MMAP, &mmap);
- if (ret == -1) {
- perror("Memory map failed");
- return AEE_EFAILED;
- } else if (ret) {
- fprintf(stderr, "Memory map failed: %s\n", aee_strerror[ret]);
+ if (ret) {
+ fprintf(stderr, "Memory map failed: %s\n",
+ hexagonrpc_strerror(ret));
return ret;
}
diff --git a/hexagonrpcd/apps_std.c b/hexagonrpcd/apps_std.c
index 06519f8..3ae0e8d 100644
--- a/hexagonrpcd/apps_std.c
+++ b/hexagonrpcd/apps_std.c
@@ -20,15 +20,15 @@
*/
#include
+#include
#include
#include
#include
#include
#include
-#include "aee_error.h"
-#include "interfaces/apps_std.def"
#include "hexagonfs.h"
+#include "interface/apps_std.h"
#include "iobuffer.h"
#include "listener.h"
diff --git a/chrecd/interfaces.c b/hexagonrpcd/interface/adsp_default_listener.c
similarity index 57%
rename from chrecd/interfaces.c
rename to hexagonrpcd/interface/adsp_default_listener.c
index 26b21ba..a632abb 100644
--- a/chrecd/interfaces.c
+++ b/hexagonrpcd/interface/adsp_default_listener.c
@@ -1,11 +1,11 @@
/*
- * FastRPC interface list for building method definitions
+ * FastRPC reverse tunnel registration interface - method definitions
*
- * Copyright (C) 2023 The Sensor Shell Contributors
+ * Copyright (C) 2025 HexagonRPC Contributors
*
- * This file is part of sensh.
+ * This file is part of HexagonRPC.
*
- * Sensh is free software: you can redistribute it and/or modify
+ * HexagonRPC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
@@ -19,6 +19,13 @@
* along with this program. If not, see .
*/
-#define HEXAGONRPC_BUILD_METHOD_DEFINITIONS 1
+#include
+#include
-#include "interfaces/chre_slpi.def"
+const struct hrpc_method_def_interp4 adsp_default_listener_register_def = {
+ .msg_id = 0,
+ .n_args = 0,
+ .args = NULL,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/hexagonrpcd/interface/adsp_default_listener.h b/hexagonrpcd/interface/adsp_default_listener.h
new file mode 100644
index 0000000..c5cea3a
--- /dev/null
+++ b/hexagonrpcd/interface/adsp_default_listener.h
@@ -0,0 +1,34 @@
+/*
+ * FastRPC reverse tunnel registration interface - API
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INTERFACE_ADSP_DEFAULT_LISTENER_H
+#define INTERFACE_ADSP_DEFAULT_LISTENER_H
+
+#include
+#include
+
+extern struct hrpc_method_def_interp4 adsp_default_listener_register_def;
+static inline int adsp_default_listener_register(int fd, uint32_t hdl)
+{
+ return hexagonrpc(&adsp_default_listener_register_def, fd, hdl);
+}
+
+#endif /* INTERFACE_ADSP_DEFAULT_LISTENER_H */
diff --git a/hexagonrpcd/interface/adsp_listener.c b/hexagonrpcd/interface/adsp_listener.c
new file mode 100644
index 0000000..d2197df
--- /dev/null
+++ b/hexagonrpcd/interface/adsp_listener.c
@@ -0,0 +1,50 @@
+/*
+ * FastRPC reverse tunnel main interface - method definitions
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+const struct hrpc_method_def_interp4 adsp_listener_init2_def = {
+ .msg_id = 3,
+ .n_args = 0,
+ .args = NULL,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+struct hrpc_arg_def_interp4 adsp_listener_next2_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
+};
+
+const struct hrpc_method_def_interp4 adsp_listener_next2_def = {
+ .msg_id = 4,
+ .n_args = HRPC_ARRAY_SIZE(adsp_listener_next2_args),
+ .args = adsp_listener_next2_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/hexagonrpcd/interface/adsp_listener.h b/hexagonrpcd/interface/adsp_listener.h
new file mode 100644
index 0000000..362d775
--- /dev/null
+++ b/hexagonrpcd/interface/adsp_listener.h
@@ -0,0 +1,54 @@
+/*
+ * FastRPC reverse tunnel main interface - API
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INTERFACE_ADSP_LISTENER_H
+#define INTERFACE_ADSP_LISTENER_H
+
+#include
+#include
+
+#define ADSP_LISTENER 3
+
+extern struct hrpc_method_def_interp4 adsp_listener_init2_def;
+static inline int adsp_listener_init2(int fd)
+{
+ return hexagonrpc(&adsp_listener_init2_def, fd, ADSP_LISTENER);
+}
+
+extern struct hrpc_method_def_interp4 adsp_listener_next2_def;
+static inline int adsp_listener_next2(int fd,
+ uint32_t ret_rctx,
+ uint32_t ret_res,
+ uint32_t ret_outbufs_len, const char *ret_outbufs,
+ uint32_t *rctx,
+ uint32_t *handle,
+ uint32_t *sc,
+ uint32_t *inbufs_len,
+ uint32_t inbufs_size, char *inbufs)
+{
+ return hexagonrpc(&adsp_listener_next2_def, fd, ADSP_LISTENER,
+ ret_rctx, ret_res,
+ ret_outbufs_len, (const void *) ret_outbufs,
+ rctx, handle, sc, inbufs_len,
+ inbufs_size, (void *) inbufs);
+}
+
+#endif /* INTERFACE_ADSP_LISTENER_H */
diff --git a/hexagonrpcd/interface/apps_mem.c b/hexagonrpcd/interface/apps_mem.c
new file mode 100644
index 0000000..018043f
--- /dev/null
+++ b/hexagonrpcd/interface/apps_mem.c
@@ -0,0 +1,42 @@
+/*
+ * FastRPC memory mapping interface - method definitions
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+static struct hrpc_arg_def_interp4 apps_mem_request_map64_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint64_t) },
+ { HRPC_ARG_WORD, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_mem_request_map64_def = {
+ .msg_id = 2,
+ .n_args = HRPC_ARRAY_SIZE(apps_mem_request_map64_args),
+ .args = apps_mem_request_map64_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/libhexagonrpc/interfaces.c b/hexagonrpcd/interface/apps_mem.h
similarity index 60%
rename from libhexagonrpc/interfaces.c
rename to hexagonrpcd/interface/apps_mem.h
index b1ce1ab..6e7da96 100644
--- a/libhexagonrpc/interfaces.c
+++ b/hexagonrpcd/interface/apps_mem.h
@@ -1,11 +1,11 @@
/*
- * FastRPC interface list for building common method definitions
+ * FastRPC memory mapping interface - API
*
- * Copyright (C) 2023 The Sensor Shell Contributors
+ * Copyright (C) 2025 HexagonRPC Contributors
*
- * This file is part of sensh.
+ * This file is part of HexagonRPC.
*
- * Sensh is free software: you can redistribute it and/or modify
+ * HexagonRPC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
@@ -19,6 +19,11 @@
* along with this program. If not, see .
*/
-#define HEXAGONRPC_BUILD_METHOD_DEFINITIONS 1
+#ifndef INTERFACE_APPS_MEM_H
+#define INTERFACE_APPS_MEM_H
-#include
+#include
+
+extern struct hrpc_method_def_interp4 apps_mem_request_map64_def;
+
+#endif /* INTERFACE_APPS_MEM_H */
diff --git a/hexagonrpcd/interface/apps_std.c b/hexagonrpcd/interface/apps_std.c
new file mode 100644
index 0000000..67b3ace
--- /dev/null
+++ b/hexagonrpcd/interface/apps_std.c
@@ -0,0 +1,184 @@
+/*
+ * FastRPC operating system interface - method definitions
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+static struct hrpc_arg_def_interp4 apps_std_freopen_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_freopen_def = {
+ .msg_id = 1,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_freopen_args),
+ .args = apps_std_freopen_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_fflush_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_fflush_def = {
+ .msg_id = 2,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_fflush_args),
+ .args = apps_std_fflush_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_fclose_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_fclose_def = {
+ .msg_id = 3,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_fclose_args),
+ .args = apps_std_fclose_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_fread_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_fread_def = {
+ .msg_id = 4,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_fread_args),
+ .args = apps_std_fread_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_fseek_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_fseek_def = {
+ .msg_id = 9,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_fseek_args),
+ .args = apps_std_fseek_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_fopen_with_env_args[] = {
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_fopen_with_env_def = {
+ .msg_id = 19,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_fopen_with_env_args),
+ .args = apps_std_fopen_with_env_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_opendir_args[] = {
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_opendir_def = {
+ .msg_id = 26,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_opendir_args),
+ .args = apps_std_opendir_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_closedir_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint64_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_closedir_def = {
+ .msg_id = 27,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_closedir_args),
+ .args = apps_std_closedir_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_readdir_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(char) * 256 },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_readdir_def = {
+ .msg_id = 28,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_readdir_args),
+ .args = apps_std_readdir_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_mkdir_args[] = {
+ { HRPC_ARG_BLOB, sizeof(char) },
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_mkdir_def = {
+ .msg_id = 29,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_mkdir_args),
+ .args = apps_std_mkdir_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static struct hrpc_arg_def_interp4 apps_std_stat_args[] = {
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint64_t) },
+};
+
+const struct hrpc_method_def_interp4 apps_std_stat_def = {
+ .msg_id = 31,
+ .n_args = HRPC_ARRAY_SIZE(apps_std_stat_args),
+ .args = apps_std_stat_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/hexagonrpcd/interface/apps_std.h b/hexagonrpcd/interface/apps_std.h
new file mode 100644
index 0000000..b80a1ca
--- /dev/null
+++ b/hexagonrpcd/interface/apps_std.h
@@ -0,0 +1,39 @@
+/*
+ * FastRPC operating system interface - API
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INTERFACE_APPS_STD_H
+#define INTERFACE_APPS_STD_H
+
+#include
+
+extern struct hrpc_method_def_interp4 apps_std_freopen_def;
+extern struct hrpc_method_def_interp4 apps_std_fflush_def;
+extern struct hrpc_method_def_interp4 apps_std_fclose_def;
+extern struct hrpc_method_def_interp4 apps_std_fread_def;
+extern struct hrpc_method_def_interp4 apps_std_fseek_def;
+extern struct hrpc_method_def_interp4 apps_std_fopen_with_env_def;
+extern struct hrpc_method_def_interp4 apps_std_opendir_def;
+extern struct hrpc_method_def_interp4 apps_std_closedir_def;
+extern struct hrpc_method_def_interp4 apps_std_readdir_def;
+extern struct hrpc_method_def_interp4 apps_std_mkdir_def;
+extern struct hrpc_method_def_interp4 apps_std_stat_def;
+
+#endif /* INTERFACE_APPS_STD_H */
diff --git a/hexagonrpcd/interfaces.c b/hexagonrpcd/interfaces.c
deleted file mode 100644
index 3e64e63..0000000
--- a/hexagonrpcd/interfaces.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * FastRPC interface list for building method definitions
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#define HEXAGONRPC_BUILD_METHOD_DEFINITIONS 1
-
-#include "interfaces/adsp_default_listener.def"
-#include "interfaces/apps_mem.def"
-#include "interfaces/apps_std.def"
-#include "interfaces/adsp_listener.def"
diff --git a/hexagonrpcd/interfaces/adsp_default_listener.def b/hexagonrpcd/interfaces/adsp_default_listener.def
deleted file mode 100644
index 0e56ed5..0000000
--- a/hexagonrpcd/interfaces/adsp_default_listener.def
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * FastRPC reverse tunnel registration interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_ADSP_DEFAULT_LISTENER_DEF
-#define INTERFACE_ADSP_DEFAULT_LISTENER_DEF
-
-#include
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(0, adsp_default_listener_register, 0, 0, 0, 0)
-
-#endif /* INTERFACE_ADSP_DEFAULT_LISTENER_DEF */
diff --git a/hexagonrpcd/interfaces/adsp_listener.def b/hexagonrpcd/interfaces/adsp_listener.def
deleted file mode 100644
index 4f521c0..0000000
--- a/hexagonrpcd/interfaces/adsp_listener.def
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * FastRPC reverse tunnel main interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_ADSP_LISTENER_DEF
-#define INTERFACE_ADSP_LISTENER_DEF
-
-#include
-
-#define ADSP_LISTENER_HANDLE 3
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(3, adsp_listener_init2, 0, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(4, adsp_listener_next2, 2, 1, 4, 1)
-
-#endif /* INTERFACE_ADSP_LISTENER_DEF */
diff --git a/hexagonrpcd/interfaces/apps_mem.def b/hexagonrpcd/interfaces/apps_mem.def
deleted file mode 100644
index 948b837..0000000
--- a/hexagonrpcd/interfaces/apps_mem.def
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * FastRPC operating system interface
- *
- * Copyright (C) 2024 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_APPS_MEM_DEF
-#define INTERFACE_APPS_MEM_DEF
-
-#include
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(2, apps_mem_request_map64, 8, 0, 4, 0)
-
-#endif /* INTERFACE_APPS_MEM_DEF */
diff --git a/hexagonrpcd/interfaces/apps_std.def b/hexagonrpcd/interfaces/apps_std.def
deleted file mode 100644
index 2fbbdb1..0000000
--- a/hexagonrpcd/interfaces/apps_std.def
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * FastRPC operating system interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_APPS_STD_DEF
-#define INTERFACE_APPS_STD_DEF
-
-#include
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(1, apps_std_freopen, 1, 0, 1, 1)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(2, apps_std_fflush, 8, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(3, apps_std_fclose, 1, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(4, apps_std_fread, 1, 0, 2, 1)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(9, apps_std_fseek, 3, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(19, apps_std_fopen_with_env, 0, 4, 1, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(26, apps_std_opendir, 0, 1, 2, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(27, apps_std_closedir, 2, 0, 0, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(28, apps_std_readdir, 2, 0, 66, 0)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(31, apps_std_stat, 1, 1, 24, 0)
-
-#endif /* INTERFACE_APPS_STD_DEF */
diff --git a/hexagonrpcd/iobuffer.c b/hexagonrpcd/iobuffer.c
index 6481651..0995f8e 100644
--- a/hexagonrpcd/iobuffer.c
+++ b/hexagonrpcd/iobuffer.c
@@ -19,7 +19,7 @@
* along with this program. If not, see .
*/
-#include
+#include
#include
#include
#include
diff --git a/hexagonrpcd/iobuffer.h b/hexagonrpcd/iobuffer.h
index 3b32cf6..de4218d 100644
--- a/hexagonrpcd/iobuffer.h
+++ b/hexagonrpcd/iobuffer.h
@@ -27,7 +27,7 @@
#include
struct fastrpc_io_buffer {
- uint32_t s;
+ size_t s;
void *p;
};
diff --git a/hexagonrpcd/listener.c b/hexagonrpcd/listener.c
index 932c54d..33cbf75 100644
--- a/hexagonrpcd/listener.c
+++ b/hexagonrpcd/listener.c
@@ -20,117 +20,400 @@
*/
#include
-#include
-#include
+#include
+#include
#include
+#include
#include
-#include "aee_error.h"
-#include "interfaces/adsp_listener.def"
+#include "interface/adsp_listener.h"
#include "iobuffer.h"
#include "listener.h"
-static int adsp_listener_init2(int fd)
+static int count_sizes_in_type4(const struct hrpc_inner_type_def_interp4 *type,
+ const struct fastrpc_io_buffer **curr_inbuf,
+ const struct fastrpc_io_buffer *inbufs_end,
+ const void **inst, const void *end)
{
- return fastrpc2(&adsp_listener_init2_def, fd, ADSP_LISTENER_HANDLE);
+ size_t size, i;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ *inst = (const char *) *inst + type->p[i].d;
+ if (*inst > end)
+ return -1;
+
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ if ((const void *) ((const uint32_t *) *inst + 1) > end)
+ return -1;
+
+ if (*curr_inbuf >= inbufs_end)
+ return -1;
+
+ size = *(const uint32_t *) *inst;
+ size *= type->p[i].d;
+ if ((*curr_inbuf)->s != size)
+ return -1;
+
+ *inst = (const uint32_t *) *inst + 1;
+ (*curr_inbuf)++;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
}
-static int adsp_listener_next2(int fd,
- uint32_t ret_rctx,
- uint32_t ret_res,
- uint32_t ret_outbuf_len, void *ret_outbuf,
- uint32_t *rctx,
- uint32_t *handle,
- uint32_t *sc,
- uint32_t *inbufs_len,
- uint32_t inbufs_size, void *inbufs)
+static int count_sizes_out_type4(const struct hrpc_inner_type_def_interp4 *type,
+ uint8_t *n_outbufs,
+ const void **inst, const void *end)
{
- return fastrpc2(&adsp_listener_next2_def, fd, ADSP_LISTENER_HANDLE,
- ret_rctx,
- ret_res,
- ret_outbuf_len, ret_outbuf,
- rctx,
- handle,
- sc,
- inbufs_len,
- inbufs_size, inbufs);
+ size_t i;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ *inst = (const uint32_t *) *inst + 1;
+ if (*inst > end)
+ return -1;
+
+ if (*n_outbufs == 0)
+ return -1;
+ (*n_outbufs)--;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
}
-static struct fastrpc_io_buffer *allocate_outbufs(const struct fastrpc_function_def_interp2 *def,
- uint32_t *first_inbuf)
+static int count_sizes4(const struct hrpc_method_def_interp4 *def,
+ uint8_t n_inbufs, uint8_t n_outbufs,
+ const struct fastrpc_io_buffer *inbufs)
{
- struct fastrpc_io_buffer *out;
- size_t out_count;
- size_t i, j;
- off_t off;
- uint32_t *sizes;
-
- out_count = def->out_bufs + (def->out_nums && 1);
- /*
- * POSIX allows malloc to return a non-NULL pointer to a zero-size area
- * in memory. Since the code below assumes non-zero size if the pointer
- * is non-NULL, exit early if we do not need to allocate anything.
- */
- if (out_count == 0)
- return NULL;
-
- out = malloc(sizeof(struct fastrpc_io_buffer) * out_count);
- if (out == NULL)
- return NULL;
+ const struct hrpc_inner_type_def_interp4 *inner_type;
+ const void *pos = inbufs[0].p;
+ const void *end = (const char *) inbufs[0].p + inbufs[0].s;
+ const struct fastrpc_io_buffer *inbufs_end = &inbufs[n_inbufs];
+ const struct fastrpc_io_buffer *curr_inbuf = &inbufs[1];
+ size_t size, i, j;
+ const void *inner_pos;
+ const void *inner_end;
+ int ret;
- out[0].s = def->out_nums * 4;
- if (out[0].s) {
- out[0].p = malloc(def->out_nums * 4);
- if (out[0].p == NULL)
- goto err_free_out;
+ if (def->msg_id > 30)
+ pos = (const uint32_t *) pos + 1;
+
+ for (i = 0; i < def->n_args; i++) {
+ switch (def->args[i].t) {
+ case HRPC_ARG_WORD:
+ if (def->args[i].d != 4 && def->args[i].d != 8)
+ return -1;
+
+ /* fall through */
+ case HRPC_ARG_BLOB:
+ pos = (const char *) pos + def->args[i].d;
+ if (pos > end)
+ return -1;
+
+ break;
+ case HRPC_ARG_TYPE:
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = count_sizes_in_type4(inner_type,
+ &curr_inbuf,
+ inbufs_end,
+ &pos, end);
+ if (ret)
+ return -1;
+
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ if ((const void *) ((const uint32_t *) pos + 1) > end)
+ return -1;
+
+ if (curr_inbuf >= inbufs_end)
+ return -1;
+
+ size = *(const uint32_t *) pos * def->args[i].d;
+ if (curr_inbuf->s != size)
+ return -1;
+
+ pos = (const uint32_t *) pos + 1;
+ curr_inbuf++;
+ break;
+ case HRPC_ARG_TYPE_SEQ:
+ if ((const void *) ((const uint32_t *) pos + 1) > end)
+ return -1;
+
+ if (curr_inbuf >= inbufs_end)
+ return -1;
+
+ size = *(const uint32_t *) pos;
+ pos = (const uint32_t *) pos + 1;
+
+ inner_type = &def->inner_types[def->args[i].d];
+ inner_pos = curr_inbuf->p;
+ inner_end = (const char *) curr_inbuf->p + curr_inbuf->s;
+ curr_inbuf++;
+ for (j = 0; j < size; j++) {
+ ret = count_sizes_in_type4(inner_type,
+ &curr_inbuf,
+ inbufs_end,
+ &inner_pos,
+ inner_end);
+ if (ret)
+ return -1;
+ }
+
+ break;
+ case HRPC_ARG_OUT_BLOB:
+ break;
+ case HRPC_ARG_OUT_TYPE:
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = count_sizes_out_type4(inner_type,
+ &n_outbufs,
+ &pos, end);
+ if (ret)
+ return -1;
+
+ break;
+ case HRPC_ARG_OUT_BLOB_SEQ:
+ if ((const void *) ((const uint32_t *) pos + 1) > end)
+ return -1;
+
+ if (n_outbufs == 0)
+ return -1;
+
+ pos = (const uint32_t *) pos + 1;
+ n_outbufs--;
+ break;
+ case HRPC_ARG_OUT_TYPE_SEQ:
+ if ((const void *) ((const uint32_t *) pos + 1) > end)
+ return -1;
+
+ if (curr_inbuf >= inbufs_end)
+ return -1;
+
+ size = *(const uint32_t *) pos;
+ pos = (const uint32_t *) pos + 1;
+
+ inner_type = &def->inner_types[def->args[i].d];
+ inner_pos = curr_inbuf->p;
+ inner_end = (const char *) curr_inbuf->p + curr_inbuf->s;
+ curr_inbuf++;
+ for (j = 0; j < size; j++) {
+ ret = count_sizes_out_type4(inner_type,
+ &n_outbufs,
+ &inner_pos,
+ inner_end);
+ if (ret)
+ return -1;
+ }
+
+ break;
+ default:
+ return -1;
+ }
}
- off = def->out_nums && 1;
- sizes = &first_inbuf[def->in_nums + def->in_bufs];
+ return 0;
+}
- for (i = 0; i < def->out_bufs; i++) {
- out[off + i].s = sizes[i];
- out[off + i].p = malloc(sizes[i]);
- if (out[off + i].p == NULL)
- goto err_free_prev;
+static int alloc_outbufs_in_type4(const struct hrpc_inner_type_def_interp4 *type,
+ const struct fastrpc_io_buffer **curr_inbuf,
+ const void **inst)
+{
+ size_t i;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ *inst = (const char *) *inst + type->p[i].d;
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ *inst = (const uint32_t *) *inst + 1;
+ (*curr_inbuf)++;
+ break;
+ default:
+ return -1;
+ }
}
- return out;
+ return 0;
+}
-err_free_prev:
- for (j = 0; j < i; j++)
- free(out[off + j].p);
+static int alloc_outbufs_out_type4(const struct hrpc_inner_type_def_interp4 *type,
+ struct fastrpc_io_buffer **curr_outbuf,
+ const void **inst_in, size_t *n_inst_out)
+{
+ size_t size, i;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ *n_inst_out += type->p[i].d;
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ size = type->p[i].d;
+ size *= *(const uint32_t *) *inst_in;
+
+ (*curr_outbuf)->s = size;
+ (*curr_outbuf)->p = malloc(size);
+ if ((*curr_outbuf)->p == NULL)
+ return -1;
+
+ *inst_in = (const uint32_t *) *inst_in + 1;
+ (*curr_outbuf)++;
+ break;
+ default:
+ return -1;
+ }
+ }
-err_free_out:
- free(out);
- return NULL;
+ return 0;
}
-static int check_inbuf_sizes(const struct fastrpc_function_def_interp2 *def,
- const struct fastrpc_io_buffer *inbufs)
+static struct fastrpc_io_buffer *alloc_outbufs4(const struct hrpc_method_def_interp4 *def,
+ const struct fastrpc_io_buffer *inbufs,
+ uint8_t n_outbufs)
{
- uint8_t i;
- const uint32_t *sizes = &((const uint32_t *) inbufs[0].p)[def->in_nums];
-
- if (inbufs[0].s != 4U * (def->in_nums
- + def->in_bufs
- + def->out_bufs)) {
- fprintf(stderr, "Invalid number of input numbers: %" PRIu32 " (expected %u)\n",
- inbufs[0].s,
- 4 * (def->in_nums
- + def->in_bufs
- + def->out_bufs));
- return -1;
+ const struct hrpc_inner_type_def_interp4 *inner_type;
+ const void *prim_in = inbufs[0].p;
+ struct fastrpc_io_buffer *out, *curr_outbuf, *inner_outbuf;
+ const struct fastrpc_io_buffer *curr_inbuf = &inbufs[1];
+ const void *inner_pos;
+ size_t i, j, size, prim_out_size = 0;
+ int ret;
+
+ curr_outbuf = out = calloc(n_outbufs, sizeof(*out));
+ if (out == NULL)
+ return NULL;
+
+ for (i = 0; i < def->n_args; i++) {
+ if (def->args[i].t == HRPC_ARG_OUT_BLOB
+ || def->args[i].t == HRPC_ARG_OUT_TYPE) {
+ curr_outbuf = &out[1];
+ break;
+ }
}
- for (i = 0; i < def->in_bufs; i++) {
- if (inbufs[i + 1].s != sizes[i]) {
- fprintf(stderr, "Invalid buffer size\n");
- return -1;
+ for (i = 0; i < def->n_args; i++) {
+ switch (def->args[i].t) {
+ case HRPC_ARG_WORD:
+ case HRPC_ARG_BLOB:
+ prim_in = (const char *) prim_in + def->args[i].d;
+ break;
+ case HRPC_ARG_TYPE:
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = alloc_outbufs_in_type4(inner_type,
+ &curr_inbuf,
+ &prim_in);
+ if (ret)
+ return NULL;
+
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ prim_in = (const uint32_t *) prim_in + 1;
+ curr_inbuf++;
+ break;
+ case HRPC_ARG_TYPE_SEQ:
+ size = *(const uint32_t *) prim_in;
+ prim_in = (const uint32_t *) prim_in + 1;
+
+ inner_type = &def->inner_types[def->args[i].d];
+ inner_pos = curr_inbuf->p;
+ curr_inbuf++;
+ for (j = 0; j < size; j++) {
+ ret = alloc_outbufs_in_type4(inner_type,
+ &curr_inbuf,
+ &inner_pos);
+ if (ret)
+ return NULL;
+ }
+
+ break;
+ case HRPC_ARG_OUT_BLOB:
+ prim_out_size += def->args[i].d;
+ break;
+ case HRPC_ARG_OUT_TYPE:
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = alloc_outbufs_out_type4(inner_type,
+ &curr_outbuf,
+ &prim_in,
+ &prim_out_size);
+ if (ret)
+ return NULL;
+
+ break;
+ case HRPC_ARG_OUT_BLOB_SEQ:
+ size = *(const uint32_t *) prim_in;
+ size *= def->args[i].d;
+
+ curr_outbuf->s = size;
+ curr_outbuf->p = malloc(size);
+ if (curr_outbuf->p == NULL)
+ goto err;
+
+ curr_outbuf++;
+
+ prim_in = (const uint32_t *) prim_in + 1;
+ break;
+ case HRPC_ARG_OUT_TYPE_SEQ:
+ size = *(const uint32_t *) prim_in;
+ prim_in = (const uint32_t *) prim_in + 1;
+
+ inner_type = &def->inner_types[def->args[i].d];
+ inner_pos = curr_inbuf->p;
+ curr_inbuf++;
+
+ inner_outbuf = curr_outbuf;
+ curr_outbuf++;
+
+ for (j = 0; j < size; j++) {
+ ret = alloc_outbufs_out_type4(inner_type,
+ &curr_outbuf,
+ &inner_pos,
+ &inner_outbuf->s);
+ if (ret)
+ return NULL;
+ }
+
+ inner_outbuf->p = malloc(inner_outbuf->s);
+ if (inner_outbuf->p == NULL)
+ return NULL;
+
+ break;
+ default:
+ goto err;
}
}
- return 0;
+ if (prim_out_size != 0) {
+ out[0].s = prim_out_size;
+ out[0].p = malloc(prim_out_size);
+ if (out[0].p == NULL)
+ goto err;
+ }
+
+ return out;
+
+err:
+ for (; curr_outbuf >= out; curr_outbuf--) {
+ if (curr_outbuf->p != NULL)
+ free(curr_outbuf->p);
+ }
+
+ free(out);
+
+ return NULL;
}
static int return_for_next_invoke(int fd,
@@ -215,11 +498,20 @@ static int invoke_requested_procedure(size_t n_ifaces,
struct fastrpc_io_buffer **returned)
{
const struct fastrpc_function_impl *impl;
- uint8_t in_count;
- uint8_t out_count;
uint32_t method = REMOTE_SCALARS_METHOD(sc);
int ret;
+ if (method < 31) {
+ method = REMOTE_SCALARS_METHOD(sc);
+ } else if (REMOTE_SCALARS_INBUFS(sc) != 0
+ && decoded[0].s >= sizeof(uint32_t)) {
+ method = *(const uint32_t *) decoded[0].p;
+ } else {
+ fprintf(stderr, "Expected extended method ID, but got none\n");
+ *result = AEE_EBADPARM;
+ return 1;
+ }
+
if (sc & 0xff) {
fprintf(stderr, "Handles are not supported, but got %u in, %u out\n",
(sc & 0xf0) >> 4, sc & 0xf);
@@ -247,26 +539,17 @@ static int invoke_requested_procedure(size_t n_ifaces,
return 1;
}
- in_count = impl->def->in_bufs + ((impl->def->in_nums
- || impl->def->in_bufs
- || impl->def->out_bufs) && 1);
- out_count = impl->def->out_bufs + (impl->def->out_nums && 1);
-
- if (REMOTE_SCALARS_INBUFS(sc) != in_count
- || REMOTE_SCALARS_OUTBUFS(sc) != out_count) {
- fprintf(stderr, "Unexpected buffer count: %08x\n", sc);
- *result = AEE_EBADPARM;
- return 1;
- }
-
- ret = check_inbuf_sizes(impl->def, decoded);
+ ret = count_sizes4(impl->def, REMOTE_SCALARS_INBUFS(sc),
+ REMOTE_SCALARS_OUTBUFS(sc), decoded);
if (ret) {
+ fprintf(stderr, "Inconsistent buffer sizes\n");
*result = AEE_EBADPARM;
return 1;
}
- *returned = allocate_outbufs(impl->def, decoded[0].p);
- if (*returned == NULL && out_count > 0) {
+ *returned = alloc_outbufs4(impl->def, decoded,
+ REMOTE_SCALARS_OUTBUFS(sc));
+ if (*returned == NULL && impl->def->n_args > 0) {
perror("Could not allocate output buffers");
*result = AEE_ENOMEMORY;
return 1;
diff --git a/hexagonrpcd/listener.h b/hexagonrpcd/listener.h
index 7c2aab3..8938b87 100644
--- a/hexagonrpcd/listener.h
+++ b/hexagonrpcd/listener.h
@@ -22,14 +22,14 @@
#ifndef LISTENER_H
#define LISTENER_H
-#include
+#include
#include
#include
#include "iobuffer.h"
struct fastrpc_function_impl {
- const struct fastrpc_function_def_interp2 *def;
+ const struct hrpc_method_def_interp4 *def;
uint32_t (*impl)(void *data,
const struct fastrpc_io_buffer *inbufs,
struct fastrpc_io_buffer *outbufs);
diff --git a/hexagonrpcd/localctl.c b/hexagonrpcd/localctl.c
index 3eaef88..f90f99e 100644
--- a/hexagonrpcd/localctl.c
+++ b/hexagonrpcd/localctl.c
@@ -19,13 +19,13 @@
* along with this program. If not, see .
*/
-#include
+#include
+#include
#include
#include
#include
#include
-#include "aee_error.h"
#include "iobuffer.h"
#include "listener.h"
#include "localctl.h"
diff --git a/hexagonrpcd/meson.build b/hexagonrpcd/meson.build
index 3d1e9d1..11244ef 100644
--- a/hexagonrpcd/meson.build
+++ b/hexagonrpcd/meson.build
@@ -1,8 +1,10 @@
executable('hexagonrpcd',
- 'aee_error.c',
'apps_mem.c',
'apps_std.c',
- 'interfaces.c',
+ 'interface/adsp_default_listener.c',
+ 'interface/adsp_listener.c',
+ 'interface/apps_mem.c',
+ 'interface/apps_std.c',
'hexagonfs.c',
'hexagonfs_mapped.c',
'hexagonfs_plat_subtype_name.c',
diff --git a/hexagonrpcd/rpcd.c b/hexagonrpcd/rpcd.c
index cc1f5cf..38d5c00 100644
--- a/hexagonrpcd/rpcd.c
+++ b/hexagonrpcd/rpcd.c
@@ -21,8 +21,10 @@
#include
#include
-#include
-#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -34,99 +36,34 @@
#include
#include
-#include "aee_error.h"
#include "apps_mem.h"
#include "apps_std.h"
#include "hexagonfs.h"
-#include "interfaces/adsp_default_listener.def"
+#include "interface/adsp_default_listener.h"
#include "listener.h"
#include "localctl.h"
#include "rpcd_builder.h"
-static int remotectl_open(int fd, char *name, struct fastrpc_context **ctx, void (*err_cb)(const char *err))
-{
- uint32_t handle;
- int32_t dlret;
- char err[256];
- int ret;
-
- ret = fastrpc2(&remotectl_open_def, fd, REMOTECTL_HANDLE,
- strlen(name) + 1, name,
- &handle,
- &dlret,
- 256, err);
-
- if (ret == -1) {
- err_cb(strerror(errno));
- return ret;
- }
-
- if (dlret == -5) {
- err_cb(err);
- return dlret;
- } else if (dlret) {
- err_cb(aee_strerror[dlret]);
- return dlret;
- }
-
- *ctx = fastrpc_create_context(fd, handle);
-
- return ret;
-}
-
-static int remotectl_close(struct fastrpc_context *ctx, void (*err_cb)(const char *err))
-{
- uint32_t dlret;
- char err[256];
- int ret;
-
- ret = fastrpc2(&remotectl_close_def, ctx->fd, REMOTECTL_HANDLE,
- ctx->handle,
- &dlret,
- 256, err);
-
- if (ret == -1) {
- err_cb(strerror(errno));
- return ret;
- }
-
- if (dlret) {
- err_cb(aee_strerror[dlret]);
- return dlret;
- }
-
- fastrpc_destroy_context(ctx);
-
- return ret;
-}
-
-static int adsp_default_listener_register(struct fastrpc_context *ctx)
-{
- return fastrpc(&adsp_default_listener_register_def, ctx);
-}
-
-static void remotectl_err(const char *err)
-{
- fprintf(stderr, "Could not remotectl: %s\n", err);
-}
-
static int register_fastrpc_listener(int fd)
{
- struct fastrpc_context *ctx;
+ uint32_t hdl;
+ char err[256];
int ret;
- ret = remotectl_open(fd, "adsp_default_listener", &ctx, remotectl_err);
- if (ret)
+ ret = hexagonrpc_open(fd, "adsp_default_listener", &hdl, 256, err);
+ if (ret) {
+ fprintf(stderr, "Could not open remote interface: %s\n", err);
return 1;
+ }
- ret = adsp_default_listener_register(ctx);
+ ret = adsp_default_listener_register(fd, hdl);
if (ret) {
fprintf(stderr, "Could not register ADSP default listener\n");
goto err;
}
err:
- remotectl_close(ctx, remotectl_err);
+ hexagonrpc_close(fd, hdl);
return ret;
}
@@ -268,7 +205,7 @@ static void *start_reverse_tunnel(int fd, const char *device_dir, const char *ds
* fully populate the ifaces array as long as it receives a pointer to
* it.
*/
- ifaces[REMOTECTL_HANDLE] = fastrpc_localctl_init(n_ifaces, ifaces);
+ ifaces[REMOTECTL] = fastrpc_localctl_init(n_ifaces, ifaces);
// Dynamic interfaces with no hardcoded handle
ifaces[1] = fastrpc_apps_std_init(root_dir);
@@ -280,7 +217,7 @@ static void *start_reverse_tunnel(int fd, const char *device_dir, const char *ds
run_fastrpc_listener(fd, n_ifaces, ifaces);
- fastrpc_localctl_deinit(ifaces[REMOTECTL_HANDLE]);
+ fastrpc_localctl_deinit(ifaces[REMOTECTL]);
free(ifaces);
diff --git a/hexagonrpcd/aee_error.h b/include/libhexagonrpc/error.h
similarity index 93%
rename from hexagonrpcd/aee_error.h
rename to include/libhexagonrpc/error.h
index 911165e..375c3f4 100644
--- a/hexagonrpcd/aee_error.h
+++ b/include/libhexagonrpc/error.h
@@ -2,6 +2,7 @@
* Imported FastRPC error numbers
*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, The Sensor Shell Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -29,8 +30,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef AEE_STRERROR_H
-#define AEE_STRERROR_H
+#ifndef LIBHEXAGONRPC_ERROR_H
+#define LIBHEXAGONRPC_ERROR_H
#define AEE_SUCCESS 0
#define AEE_EFAILED 1
@@ -83,6 +84,6 @@
#define AEE_ECPUEXCEPTION 48
#define AEE_EREADONLY 49
-extern const char *aee_strerror[];
+const char *hexagonrpc_strerror(int ret);
-#endif
+#endif /* LIBHEXAGONRPC_ERROR_H */
diff --git a/include/libhexagonrpc/fastrpc.h b/include/libhexagonrpc/fastrpc.h
deleted file mode 100644
index 69f0d17..0000000
--- a/include/libhexagonrpc/fastrpc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * FastRPC API Replacement - header files
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef FASTRPC_H
-#define FASTRPC_H
-
-#include
-#include
-#include
-
-// See fastrpc.git/inc/remote.h
-#define REMOTE_SCALARS_MAKEX(nAttr,nMethod,nIn,nOut,noIn,noOut) \
- ((((uint32_t) (nAttr) & 0x7) << 29) | \
- (((uint32_t) (nMethod) & 0x1f) << 24) | \
- (((uint32_t) (nIn) & 0xff) << 16) | \
- (((uint32_t) (nOut) & 0xff) << 8) | \
- (((uint32_t) (noIn) & 0x0f) << 4) | \
- ((uint32_t) (noOut) & 0x0f))
-
-#define REMOTE_SCALARS_MAKE(nMethod,nIn,nOut) REMOTE_SCALARS_MAKEX(0,nMethod,nIn,nOut,0,0)
-
-#define REMOTE_SCALARS_METHOD(sc) (((sc) >> 24) & 0x1f)
-#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0xff)
-#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0xff)
-
-struct fastrpc_context {
- int fd;
- uint32_t handle;
-};
-
-struct fastrpc_function_def_interp2 {
- uint32_t msg_id;
- uint8_t in_nums;
- uint8_t in_bufs;
- uint8_t out_nums;
- uint8_t out_bufs;
-};
-
-struct fastrpc_context *fastrpc_create_context(int fd, uint32_t handle);
-
-static inline void fastrpc_destroy_context(struct fastrpc_context *ctx)
-{
- free(ctx);
-}
-
-int vfastrpc2(const struct fastrpc_function_def_interp2 *def,
- int fd, uint32_t handle, va_list arg_list);
-int vfastrpc(const struct fastrpc_function_def_interp2 *def,
- const struct fastrpc_context *ctx, va_list arg_list);
-int fastrpc2(const struct fastrpc_function_def_interp2 *def,
- int fd, uint32_t handle, ...);
-int fastrpc(const struct fastrpc_function_def_interp2 *def,
- const struct fastrpc_context *ctx, ...);
-
-#endif
diff --git a/include/libhexagonrpc/handle.h b/include/libhexagonrpc/handle.h
new file mode 100644
index 0000000..15a2c4f
--- /dev/null
+++ b/include/libhexagonrpc/handle.h
@@ -0,0 +1,41 @@
+/*
+ * FastRPC handle utilities
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef LIBHEXAGONRPC_HANDLE_H
+#define LIBHEXAGONRPC_HANDLE_H
+
+#include
+#include
+
+/*
+ * Open a remote interface by name and get its handle.
+ *
+ * On success, returns 0 and sets the handle.
+ * On failure, returns -1 and sets the err string.
+ */
+int hexagonrpc_open(int fd, const char *name, uint32_t *hdl, size_t n_err, char *err);
+
+/*
+ * Close a remote interface by its handle.
+ */
+void hexagonrpc_close(int fd, uint32_t hdl);
+
+#endif /* LIBHEXAGONRPC_HANDLE_H */
diff --git a/include/libhexagonrpc/hexagonrpc.h b/include/libhexagonrpc/hexagonrpc.h
new file mode 100644
index 0000000..3bebda6
--- /dev/null
+++ b/include/libhexagonrpc/hexagonrpc.h
@@ -0,0 +1,90 @@
+/*
+ * FastRPC argument marshalling - header files
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef HEXAGONRPC_H
+#define HEXAGONRPC_H
+
+#include
+#include
+#include
+#include
+
+// See fastrpc.git/inc/remote.h
+#define REMOTE_SCALARS_MAKEX(nAttr,nMethod,nIn,nOut,noIn,noOut) \
+ ((((uint32_t) (nAttr) & 0x7) << 29) | \
+ (((uint32_t) (nMethod) & 0x1f) << 24) | \
+ (((uint32_t) (nIn) & 0xff) << 16) | \
+ (((uint32_t) (nOut) & 0xff) << 8) | \
+ (((uint32_t) (noIn) & 0x0f) << 4) | \
+ ((uint32_t) (noOut) & 0x0f))
+
+#define REMOTE_SCALARS_MAKE(nMethod,nIn,nOut) REMOTE_SCALARS_MAKEX(0,nMethod,nIn,nOut,0,0)
+
+#define REMOTE_SCALARS_METHOD(sc) (((sc) >> 24) & 0x1f)
+#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0xff)
+#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0xff)
+
+#define HRPC_ARRAY_SIZE(p) (sizeof(p) / sizeof(*(p)))
+
+// Literal uint32_t or uint64_t (top-level use only)
+#define HRPC_ARG_WORD 0
+// Pointer to data of size d (usable in inner types)
+#define HRPC_ARG_BLOB 1
+// Pointer to inner type, with d indexing the inner_types array (top-level use only)
+#define HRPC_ARG_TYPE 2
+// Number of elements and pointer to sequence, element size d (usable in inner types)
+#define HRPC_ARG_BLOB_SEQ 3
+// Number of elements and pointer to sequence of inner type, with index d
+#define HRPC_ARG_TYPE_SEQ 4
+// Type 5 is reserved for sequence of inner type containing other sequences of inner types
+
+// Corresponding argument types for output (top-level use only)
+#define HRPC_ARG_OUT_BLOB 6
+#define HRPC_ARG_OUT_TYPE 7
+#define HRPC_ARG_OUT_BLOB_SEQ 8
+#define HRPC_ARG_OUT_TYPE_SEQ 9
+
+struct hrpc_arg_def_interp4 {
+ // Type (field t) can be any HRPC_ARG_* macro
+ uint32_t t;
+ // Data depends on type
+ uint32_t d;
+};
+
+struct hrpc_inner_type_def_interp4 {
+ size_t s;
+ const struct hrpc_arg_def_interp4 *p;
+};
+
+struct hrpc_method_def_interp4 {
+ uint32_t msg_id;
+ size_t n_args;
+ const struct hrpc_arg_def_interp4 *args;
+ size_t n_inner_types;
+ const struct hrpc_inner_type_def_interp4 *inner_types;
+};
+
+int vhexagonrpc(const struct hrpc_method_def_interp4 *def,
+ int fd, uint32_t handle, va_list list);
+int hexagonrpc(const struct hrpc_method_def_interp4 *def,
+ int fd, uint32_t handle, ...);
+
+#endif
diff --git a/include/libhexagonrpc/interface.h b/include/libhexagonrpc/interface.h
deleted file mode 100644
index 0b6700f..0000000
--- a/include/libhexagonrpc/interface.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * FastRPC interface method definition macros
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef LIBHEXAGONRPC_INTERFACE_H
-#define LIBHEXAGONRPC_INTERFACE_H
-
-#include
-
-/*
- * We want to declare method definitions as external by default so we only need
- * special flags when compiling the interfaces. Otherwise, everything that uses
- * the interfaces would need to define a macro.
- */
-#if !HEXAGONRPC_BUILD_METHOD_DEFINITIONS
-
-#define HEXAGONRPC_DEFINE_REMOTE_METHOD(mid, name, \
- innums, inbufs, \
- outnums, outbufs) \
- extern const struct fastrpc_function_def_interp2 name##_def;
-
-#else /* HEXAGONRPC_BUILD_METHOD_DEFINITIONS */
-
-#define HEXAGONRPC_DEFINE_REMOTE_METHOD(mid, name, \
- innums, inbufs, \
- outnums, outbufs) \
- const struct fastrpc_function_def_interp2 name##_def = { \
- .msg_id = mid, \
- .in_nums = innums, \
- .in_bufs = inbufs, \
- .out_nums = outnums, \
- .out_bufs = outbufs, \
- };
-
-#endif /* HEXAGONRPC_BUILD_METHOD_DEFINITIONS */
-
-#endif /* LIBHEXAGONRPC_INTERFACE_H */
diff --git a/include/libhexagonrpc/interface/remotectl.h b/include/libhexagonrpc/interface/remotectl.h
new file mode 100644
index 0000000..67e46d1
--- /dev/null
+++ b/include/libhexagonrpc/interface/remotectl.h
@@ -0,0 +1,52 @@
+/*
+ * Remote processor control interface - API
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INTERFACE_REMOTECTL_H
+#define INTERFACE_REMOTECTL_H
+
+#include
+#include
+
+#define REMOTECTL 0
+
+extern struct hrpc_method_def_interp4 remotectl_open_def;
+static inline int remotectl_open(int fd,
+ uint32_t n_str, const char *str,
+ uint32_t *handle,
+ uint32_t n_err, char *err,
+ uint32_t *err_valid_len)
+{
+ return hexagonrpc(&remotectl_open_def, fd, REMOTECTL,
+ n_str, (const void *) str,
+ (void *) handle, n_err, (void *) err, (void *) err_valid_len);
+}
+
+extern struct hrpc_method_def_interp4 remotectl_close_def;
+static inline int remotectl_close(int fd,
+ uint32_t handle,
+ uint32_t n_err, char *err,
+ uint32_t *err_valid_len)
+{
+ return hexagonrpc(&remotectl_close_def, fd, REMOTECTL,
+ handle, n_err, (void *) err, (void *) err_valid_len);
+}
+
+#endif /* INTERFACE_REMOTECTL_H */
diff --git a/include/libhexagonrpc/interfaces/remotectl.def b/include/libhexagonrpc/interfaces/remotectl.def
deleted file mode 100644
index ba23c57..0000000
--- a/include/libhexagonrpc/interfaces/remotectl.def
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Remote processor control interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef INTERFACE_REMOTECTL_DEF
-#define INTERFACE_REMOTECTL_DEF
-
-#include
-
-#define REMOTECTL_HANDLE 0
-
-HEXAGONRPC_DEFINE_REMOTE_METHOD(0, remotectl_open, 0, 1, 2, 1)
-HEXAGONRPC_DEFINE_REMOTE_METHOD(1, remotectl_close, 1, 0, 1, 1)
-
-#endif /* INTERFACE_REMOTECTL_DEF */
diff --git a/libhexagonrpc/context.c b/libhexagonrpc/context.c
deleted file mode 100644
index c3fa204..0000000
--- a/libhexagonrpc/context.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * FastRPC API Replacement - context-based interface
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-
-struct fastrpc_context *fastrpc_create_context(int fd, uint32_t handle)
-{
- struct fastrpc_context *ctx;
-
- ctx = malloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
-
- ctx->fd = fd;
- ctx->handle = handle;
-
- return ctx;
-}
-
-int vfastrpc(const struct fastrpc_function_def_interp2 *def,
- const struct fastrpc_context *ctx, va_list arg_list)
-{
- return vfastrpc2(def, ctx->fd, ctx->handle, arg_list);
-}
-
-int fastrpc(const struct fastrpc_function_def_interp2 *def,
- const struct fastrpc_context *ctx, ...)
-{
- va_list arg_list;
- int ret;
-
- va_start(arg_list, ctx);
- ret = vfastrpc(def, ctx, arg_list);
- va_end(arg_list);
-
- return ret;
-}
-
diff --git a/hexagonrpcd/aee_error.c b/libhexagonrpc/error.c
similarity index 89%
rename from hexagonrpcd/aee_error.c
rename to libhexagonrpc/error.c
index f0f2930..7b2cc20 100644
--- a/hexagonrpcd/aee_error.c
+++ b/libhexagonrpc/error.c
@@ -2,6 +2,7 @@
* Imported FastRPC error messages
*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, The Sensor Shell Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -29,7 +30,10 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-const char *aee_strerror[] = {
+#include
+#include
+
+static const char *err_tab[] = {
"No error",
"General failure",
"Insufficient RAM",
@@ -81,3 +85,13 @@ const char *aee_strerror[] = {
"A CPU exception occurred",
"Cannot change read-only object or parameter",
};
+
+const char *hexagonrpc_strerror(int ret)
+{
+ if (ret == -1)
+ return strerror(errno);
+ else if (ret >= 0 && (unsigned int) ret < sizeof(err_tab) / sizeof(*err_tab))
+ return err_tab[ret];
+
+ return "Unknown error";
+}
diff --git a/libhexagonrpc/fastrpc.c b/libhexagonrpc/fastrpc.c
deleted file mode 100644
index cee9323..0000000
--- a/libhexagonrpc/fastrpc.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * FastRPC API Replacement
- *
- * Copyright (C) 2023 The Sensor Shell Contributors
- *
- * This file is part of sensh.
- *
- * Sensh is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-static void allocate_first_inbuf(const struct fastrpc_function_def_interp2 *def,
- struct fastrpc_invoke_args *arg,
- uint32_t **inbuf)
-{
- uint32_t *buf;
- size_t len;
-
- len = sizeof(uint32_t) * (def->in_nums + def->in_bufs + def->out_bufs);
-
- if (len)
- buf = malloc(len);
- else
- buf = NULL;
-
- *inbuf = buf;
-
- if (buf != NULL) {
- arg->ptr = (__u64) buf;
- arg->length = len;
- arg->fd = -1;
- }
-}
-
-static void allocate_first_outbuf(const struct fastrpc_function_def_interp2 *def,
- struct fastrpc_invoke_args *arg,
- uint32_t **outbuf)
-{
- uint32_t *buf;
- size_t len;
-
- len = sizeof(uint32_t) * def->out_nums;
-
- if (len)
- buf = malloc(len);
- else
- buf = NULL;
-
- *outbuf = buf;
-
- if (buf != NULL) {
- arg->ptr = (__u64) buf;
- arg->length = len;
- arg->fd = -1;
- }
-}
-
-/*
- * This populates relevant inputs (in general) with information necessary to
- * receive output from the remote processor.
- *
- * First, it allocates a new first output buffer to contain the returned 32-bit
- * integers. This output buffer must be freed after use.
- *
- * With a peek at the output arguments, it populates the fastrpc_invoke_args
- * struct to give information about the buffer to the kernel, and adds an entry
- * to the first input buffer to tell the remote processor how large the
- * function-level output buffer can be.
- *
- * This is the only part of the argument processing that can be split off into
- * a different function because it is operating on a copy of the va_list.
- * Calling va_arg() on a va_list after the return of a function that already
- * used it causes undefined behavior.
- */
-static void prepare_outbufs(const struct fastrpc_function_def_interp2 *def,
- struct fastrpc_invoke_args *args,
- uint8_t out_count,
- uint32_t *inbuf,
- uint32_t **outbuf,
- va_list peek)
-{
- int i;
- int off;
- int size;
-
- allocate_first_outbuf(def, args, outbuf);
-
- off = def->out_nums && 1;
-
- for (i = 0; i < def->out_nums; i++)
- va_arg(peek, uint32_t *);
-
- for (i = 0; i < def->out_bufs; i++) {
- size = va_arg(peek, uint32_t);
-
- args[off + i].ptr = (__u64) va_arg(peek, void *);
- args[off + i].length = size;
- args[off + i].fd = -1;
-
- inbuf[i] = size;
- }
-}
-
-/*
- * This is the main function to invoke a fastrpc procedure call. The first
- * parameter specifies how to populate the ioctl-level buffers. The second and
- * third parameters specify where to send the invocation to. The fourth is the
- * list of arguments that the procedure call should interact with.
- *
- * The argument list has, in order:
- * - a (uint32_t val) for each input number
- * - a (uint32_t len, void *buf) for each input buffer
- * - a (uint32_t *val) for each output number
- * - a (uint32_t max_size, void *buf) for each output buffer
- *
- * A good example for this would be the adsp_listener_next2 call:
- *
- * static inline void adsp_listener_next2(int fd, uint32_t handle,
- * uint32_t prev_ctx,
- * uint32_t prev_result,
- * uint32_t nested_outbufs_len,
- * void *nested_outbufs,
- * uint32_t *ctx,
- * uint32_t *nested_handle,
- * uint32_t *nested_sc,
- * uint32_t *nested_inbufs_len,
- * uint32_t nested_inbufs_size,
- * void *nested_inbufs)
- * {
- * struct fastrpc_function_def_interp2 def = {
- * .in_nums = 2,
- * .in_bufs = 1,
- * .out_nums = 4,
- * .out_bufs = 1,
- * .mid = 4,
- * };
- * return fastrpc(def, fd, handle,
- * prev_ctx,
- * prev_result,
- * nested_outbufs_len,
- * nested_outbufs,
- * ctx,
- * nested_handle,
- * nested_sc,
- * nested_inbufs_len,
- * nested_inbufs_size,
- * nested_inbufs);
- * }
- */
-int vfastrpc2(const struct fastrpc_function_def_interp2 *def,
- int fd, uint32_t handle, va_list arg_list)
-{
- va_list peek;
- struct fastrpc_invoke invoke;
- struct fastrpc_invoke_args *args;
- uint32_t *inbuf;
- uint32_t *outbuf;
- uint8_t in_count;
- uint8_t out_count;
- uint32_t size;
- uint8_t i;
- int ret;
-
- /*
- * Calculate the amount of needed buffers, accounting for the need for
- * the maximum size of the output buffer.
- */
- in_count = def->in_bufs + ((def->in_nums
- || def->in_bufs
- || def->out_bufs) && 1);
- out_count = def->out_bufs + (def->out_nums && 1);
-
- if (in_count || out_count)
- args = malloc(sizeof(*args) * (in_count + out_count));
- else
- args = NULL;
-
- allocate_first_inbuf(def, args, &inbuf);
-
- for (i = 0; i < def->in_nums; i++)
- inbuf[i] = va_arg(arg_list, uint32_t);
-
- for (i = 0; i < def->in_bufs; i++) {
- size = va_arg(arg_list, uint32_t);
-
- args[i + 1].ptr = (__u64) va_arg(arg_list, void *);
- args[i + 1].length = size;
- args[i + 1].fd = -1;
-
- inbuf[def->in_nums + i] = size;
- }
-
- va_copy(peek, arg_list);
- prepare_outbufs(def,
- &args[in_count],
- out_count,
- &inbuf[def->in_nums + def->in_bufs],
- &outbuf,
- peek);
- va_end(peek);
-
- invoke.handle = handle;
- invoke.sc = REMOTE_SCALARS_MAKE(def->msg_id, in_count, out_count);
- invoke.args = (__u64) args;
-
- ret = ioctl(fd, FASTRPC_IOCTL_INVOKE, (__u64) &invoke);
-
- for (i = 0; i < def->out_nums; i++)
- *va_arg(arg_list, uint32_t *) = outbuf[i];
-
- if (in_count || out_count)
- free(args);
-
- if (in_count)
- free(inbuf);
-
- if (out_count)
- free(outbuf);
-
- return ret;
-}
-
-int fastrpc2(const struct fastrpc_function_def_interp2 *def,
- int fd, uint32_t handle, ...)
-{
- va_list arg_list;
- int ret;
-
- va_start(arg_list, handle);
- ret = vfastrpc2(def, fd, handle, arg_list);
- va_end(arg_list);
-
- return ret;
-}
diff --git a/libhexagonrpc/handle.c b/libhexagonrpc/handle.c
new file mode 100644
index 0000000..7268440
--- /dev/null
+++ b/libhexagonrpc/handle.c
@@ -0,0 +1,57 @@
+/*
+ * FastRPC remote interface handle management
+ *
+ * Copyright (C) 2023 The Sensor Shell Contributors
+ *
+ * This file is part of sensh.
+ *
+ * Sensh is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+
+int hexagonrpc_open(int fd, const char *name, uint32_t *hdl, size_t n_err, char *err)
+{
+ uint32_t dlerr;
+ int ret;
+
+ ret = remotectl_open(fd, strlen(name) + 1, name, hdl,
+ n_err, err, &dlerr);
+ if (ret) {
+ strncpy(err, hexagonrpc_strerror(ret), n_err);
+ err[n_err - 1] = '\0';
+ return -1;
+ }
+
+ /*
+ * The error message is already in the buffer because the buffer was
+ * directly passed as an output buffer. Simply return at this point.
+ */
+ if (dlerr)
+ return -1;
+
+ return 0;
+}
+
+void hexagonrpc_close(int fd, uint32_t hdl)
+{
+ uint32_t dlerr;
+
+ remotectl_close(fd, hdl, 0, NULL, &dlerr);
+}
diff --git a/libhexagonrpc/hexagonrpc.c b/libhexagonrpc/hexagonrpc.c
new file mode 100644
index 0000000..b638530
--- /dev/null
+++ b/libhexagonrpc/hexagonrpc.c
@@ -0,0 +1,831 @@
+/*
+ * FastRPC argument marshalling
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+/*
+ * Operations to be done for a stage of invoking.
+ *
+ * The hexagonrpc function has 5 stages that parse the method definition:
+ * - count: count the I/O buffers in need of marshalling
+ * - alloc: populate fastrpc_invoke_args with pointers, allocating when needed
+ * - encode: marshal va_args into primary input buffer
+ * - decode: demarshal primary output buffer into va_args buffers
+ * - free: free any buffers allocated by the alloc stage
+ *
+ * These stages interpret the arguments in the exact same way and have a
+ * similar control structure. To reduce code duplication, each stage can call
+ * emit_args with their own stage_ops callbacks and state.
+ */
+struct stage_ops {
+ void (*emit_prim_in)(size_t size, const void *ptr, void *data);
+ void (*emit_prim_out)(size_t size, void *ptr, void *data);
+ void (*emit_inbuf)(size_t size, const void *ptr, void *data);
+ void (*emit_outbuf)(size_t size, void *ptr, void *data);
+
+ int (*emit_type_seq_in)(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst);
+ int (*emit_type_seq_out)(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst);
+};
+
+// Used by count_ops
+struct buf_count {
+ uint8_t n_inbufs;
+ uint8_t n_outbufs;
+ uint32_t n_prim_in;
+ uint32_t n_prim_out;
+};
+
+// Used by alloc_ops and free_ops
+struct curr_buf {
+ struct fastrpc_invoke_args *inbuf;
+ struct fastrpc_invoke_args *outbuf;
+};
+
+// Used by encode_ops and decode_ops
+struct curr_pos {
+ struct fastrpc_invoke_args *buf;
+ void *prim;
+};
+
+static const struct stage_ops count_ops;
+static const struct stage_ops alloc_ops;
+static const struct stage_ops encode_ops;
+static const struct stage_ops decode_ops;
+static const struct stage_ops free_ops;
+
+static int emit_inner_type_in(const struct hrpc_inner_type_def_interp4 *type,
+ const struct stage_ops *ops, void *data,
+ const void **inst)
+{
+ uint32_t arg32;
+ void *ptr;
+ size_t i, size;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ size = type->p[i].d;
+ ops->emit_prim_in(size, *inst, data);
+ *inst = (char *) *inst + size;
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ arg32 = *(const uint32_t *) *inst;
+ *inst = (uint32_t *) *inst + 1;
+ ptr = *(void **) *inst;
+ *inst = (void **) *inst + 1;
+
+ size = (size_t) type->p[i].d * arg32;
+
+ ops->emit_prim_in(sizeof(arg32), &arg32, data);
+ ops->emit_inbuf(size, ptr, data);
+
+ break;
+ // Not seen so far in public IDLs
+ case HRPC_ARG_TYPE_SEQ:
+ return -1;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int emit_inner_type_out(const struct hrpc_inner_type_def_interp4 *type,
+ const struct stage_ops *ops, void *data,
+ void **inst)
+{
+ uint32_t arg32;
+ void *ptr;
+ size_t i, size;
+
+ for (i = 0; i < type->s; i++) {
+ switch (type->p[i].t) {
+ case HRPC_ARG_BLOB:
+ size = type->p[i].d;
+ ops->emit_prim_out(size, *inst, data);
+ *inst = (char *) *inst + size;
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ arg32 = *(const uint32_t *) *inst;
+ *inst = (uint32_t *) *inst + 1;
+ ptr = *(void **) *inst;
+ *inst = (void **) *inst + 1;
+
+ size = (size_t) type->p[i].d * arg32;
+
+ ops->emit_prim_in(sizeof(arg32), &arg32, data);
+ ops->emit_outbuf(size, ptr, data);
+
+ break;
+ // Not seen so far in public IDLs
+ case HRPC_ARG_TYPE_SEQ:
+ return -1;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int emit_args(const struct hrpc_method_def_interp4 *def,
+ const struct stage_ops *ops, void *data,
+ va_list list)
+{
+ const struct hrpc_inner_type_def_interp4 *inner_type;
+ uint32_t arg32;
+ uint64_t arg64;
+ const void *iptr;
+ void *optr;
+ size_t i, size;
+ int ret;
+
+ for (i = 0; i < def->n_args; i++) {
+ switch (def->args[i].t) {
+ case HRPC_ARG_WORD:
+ size = def->args[i].d;
+ if (size == sizeof(uint32_t)) {
+ arg32 = va_arg(list, uint32_t);
+ ops->emit_prim_in(size, &arg32, data);
+ } else if (size == sizeof(uint64_t)) {
+ arg64 = va_arg(list, uint64_t);
+ ops->emit_prim_in(size, &arg64, data);
+ } else {
+ return -1;
+ }
+
+ break;
+ case HRPC_ARG_BLOB:
+ size = def->args[i].d;
+ iptr = va_arg(list, const void *);
+ ops->emit_prim_in(size, iptr, data);
+ break;
+ case HRPC_ARG_TYPE:
+ iptr = va_arg(list, const void *);
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = emit_inner_type_in(inner_type,
+ ops, data, &iptr);
+ if (ret)
+ return ret;
+ break;
+ case HRPC_ARG_BLOB_SEQ:
+ arg32 = va_arg(list, uint32_t);
+ iptr = va_arg(list, const void *);
+ size = (size_t) def->args[i].d * arg32;
+
+ ops->emit_prim_in(sizeof(arg32), &arg32, data);
+ ops->emit_inbuf(size, iptr, data);
+
+ break;
+ case HRPC_ARG_TYPE_SEQ:
+ arg32 = va_arg(list, uint32_t);
+ iptr = va_arg(list, const void *);
+ ret = ops->emit_type_seq_in(def, inner_type,
+ data, arg32, iptr);
+ if (ret)
+ return ret;
+ break;
+ case HRPC_ARG_OUT_BLOB:
+ optr = va_arg(list, void *);
+ ops->emit_prim_out(def->args[i].d, optr, data);
+ break;
+ case HRPC_ARG_OUT_TYPE:
+ optr = va_arg(list, void *);
+ inner_type = &def->inner_types[def->args[i].d];
+ ret = emit_inner_type_out(inner_type,
+ ops, data, &optr);
+ if (ret)
+ return ret;
+ break;
+ case HRPC_ARG_OUT_BLOB_SEQ:
+ arg32 = va_arg(list, uint32_t);
+ optr = va_arg(list, void *);
+ size = (size_t) def->args[i].d * arg32;
+
+ ops->emit_prim_in(sizeof(arg32), &arg32, data);
+ ops->emit_outbuf(size, optr, data);
+
+ break;
+ case HRPC_ARG_OUT_TYPE_SEQ:
+ arg32 = va_arg(list, uint32_t);
+ optr = va_arg(list, void *);
+ ret = ops->emit_type_seq_out(def, inner_type,
+ data, arg32, optr);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void emit_nop_in(size_t size, const void *ptr, void *data)
+{
+}
+
+static void emit_nop_out(size_t size, void *ptr, void *data)
+{
+}
+
+static void count_prim_in(size_t size, const void *ptr, void *data)
+{
+ ((struct buf_count *) data)->n_prim_in += size;
+}
+
+static void count_prim_out(size_t size, void *ptr, void *data)
+{
+ ((struct buf_count *) data)->n_prim_out += size;
+}
+
+static void count_inbuf(size_t size, const void *ptr, void *data)
+{
+ ((struct buf_count *) data)->n_inbufs++;
+}
+
+static void count_outbuf(size_t size, void *ptr, void *data)
+{
+ ((struct buf_count *) data)->n_outbufs++;
+}
+
+static int count_type_seq_in(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst)
+{
+ struct buf_count inner_count = { 0, 0, 0, 0 };
+ struct buf_count *count = data;
+ int ret = 0;
+
+ if (n_inst) {
+ ret = emit_inner_type_in(type,
+ &count_ops, &inner_count,
+ &inst);
+ count->n_inbufs++;
+ count->n_inbufs += inner_count.n_inbufs * n_inst;
+ }
+
+ return ret;
+}
+
+static int count_type_seq_out(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst)
+{
+ struct buf_count inner_count = { 0, 0, 0, 0 };
+ struct buf_count *count = data;
+ int ret = 0;
+
+ if (n_inst) {
+ ret = emit_inner_type_out(type,
+ &count_ops, &inner_count,
+ &inst);
+ count->n_inbufs++;
+ count->n_outbufs += inner_count.n_outbufs * n_inst;
+ }
+
+ return ret;
+}
+
+static const struct stage_ops count_ops = {
+ .emit_prim_in = count_prim_in,
+ .emit_prim_out = count_prim_out,
+ .emit_inbuf = count_inbuf,
+ .emit_outbuf = count_outbuf,
+ .emit_type_seq_in = count_type_seq_in,
+ .emit_type_seq_out = count_type_seq_out,
+};
+
+static void alloc_inbuf(size_t size, const void *ptr, void *data)
+{
+ struct curr_buf *curr = data;
+
+ curr->inbuf->length = size;
+ curr->inbuf->ptr = (__u64) ptr;
+ curr->inbuf++;
+}
+
+static void alloc_outbuf(size_t size, void *ptr, void *data)
+{
+ struct curr_buf *curr = data;
+
+ curr->outbuf->length = size;
+ curr->outbuf->ptr = (__u64) ptr;
+ curr->outbuf++;
+}
+
+static int alloc_type_seq_in(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst)
+{
+ struct buf_count inner_count = { 0, 0, 0, 0 };
+ struct curr_buf *curr = data;
+ int ret = 0;
+ size_t i;
+
+ if (n_inst) {
+ ret = emit_inner_type_in(type,
+ &count_ops, &inner_count,
+ &inst);
+ if (ret)
+ return ret;
+
+ curr->inbuf->length = inner_count.n_prim_in * n_inst;
+ curr->inbuf->ptr = (__u64) malloc(curr->inbuf->length);
+ if (curr->inbuf->ptr == 0)
+ return -1;
+ }
+
+ curr->inbuf++;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_in(type, &alloc_ops, data, &inst);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int alloc_type_seq_out(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst)
+{
+ struct buf_count inner_count = { 0, 0, 0, 0 };
+ struct curr_buf *curr = data;
+ int ret = 0;
+ size_t i;
+
+ if (n_inst) {
+ ret = emit_inner_type_out(type,
+ &count_ops, &inner_count,
+ &inst);
+ if (ret)
+ return ret;
+
+ curr->inbuf->length = inner_count.n_prim_in * n_inst;
+ curr->inbuf->ptr = (__u64) malloc(curr->inbuf->length);
+ if (curr->inbuf->ptr == 0)
+ return -1;
+
+ curr->outbuf->length = inner_count.n_prim_out * n_inst;
+ curr->outbuf->ptr = (__u64) malloc(curr->outbuf->length);
+ if (curr->outbuf->ptr == 0)
+ return -1;
+ }
+
+ curr->inbuf++;
+ curr->outbuf++;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_out(type, &alloc_ops, data, &inst);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct stage_ops alloc_ops = {
+ .emit_prim_in = emit_nop_in,
+ .emit_prim_out = emit_nop_out,
+ .emit_inbuf = alloc_inbuf,
+ .emit_outbuf = alloc_outbuf,
+ .emit_type_seq_in = alloc_type_seq_in,
+ .emit_type_seq_out = alloc_type_seq_out,
+};
+
+static void encode_prim_in(size_t size, const void *ptr, void *data)
+{
+ struct curr_pos *pos = data;
+
+ memcpy(pos->prim, ptr, size);
+ pos->prim = (char *) pos->prim + size;
+}
+
+static void encode_inbuf(size_t size, const void *ptr, void *data)
+{
+ ((struct curr_pos *) data)->buf++;
+}
+
+static int encode_type_seq_in(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst)
+{
+ struct curr_pos inner_pos;
+ struct curr_pos *pos = data;
+ int ret;
+ size_t i;
+
+ inner_pos.buf = pos->buf;
+ inner_pos.prim = (void *) pos->buf->ptr;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_in(type, &encode_ops, &inner_pos, &inst);
+ if (ret)
+ return ret;
+ }
+
+ pos->buf = inner_pos.buf;
+ return 0;
+}
+
+static int encode_type_seq_out(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst)
+{
+ struct curr_pos inner_pos;
+ struct curr_pos *pos = data;
+ int ret;
+ size_t i;
+
+ inner_pos.buf = pos->buf;
+ inner_pos.prim = (void *) pos->buf->ptr;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_out(type, &encode_ops, &inner_pos, &inst);
+ if (ret)
+ return ret;
+ }
+
+ pos->buf = inner_pos.buf;
+ return 0;
+}
+
+static const struct stage_ops encode_ops = {
+ .emit_prim_in = encode_prim_in,
+ .emit_prim_out = emit_nop_out,
+ .emit_inbuf = encode_inbuf,
+ .emit_outbuf = emit_nop_out,
+ .emit_type_seq_in = encode_type_seq_in,
+ .emit_type_seq_out = encode_type_seq_out,
+};
+
+static void decode_prim_out(size_t size, void *ptr, void *data)
+{
+ struct curr_pos *pos = data;
+
+ memcpy(ptr, pos->prim, size);
+ pos->prim = (char *) pos->prim + size;
+}
+
+static void decode_outbuf(size_t size, void *ptr, void *data)
+{
+ ((struct curr_pos *) data)->buf++;
+}
+
+static int decode_type_seq_in(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst)
+{
+ return 0;
+}
+
+static int decode_type_seq_out(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst)
+{
+ struct curr_pos inner_pos;
+ struct curr_pos *pos = data;
+ int ret;
+ size_t i;
+
+ inner_pos.buf = pos->buf;
+ inner_pos.prim = (void *) pos->buf->ptr;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_out(type, &decode_ops, &inner_pos, &inst);
+ if (ret)
+ return ret;
+ }
+
+ pos->buf = inner_pos.buf;
+ return 0;
+}
+
+static const struct stage_ops decode_ops = {
+ .emit_prim_in = emit_nop_in,
+ .emit_prim_out = decode_prim_out,
+ .emit_inbuf = emit_nop_in,
+ .emit_outbuf = decode_outbuf,
+ .emit_type_seq_in = decode_type_seq_in,
+ .emit_type_seq_out = decode_type_seq_out,
+};
+
+static void free_inbuf(size_t size, const void *ptr, void *data)
+{
+ ((struct curr_buf *) data)->inbuf++;
+}
+
+static void free_outbuf(size_t size, void *ptr, void *data)
+{
+ ((struct curr_buf *) data)->outbuf++;
+}
+
+static int free_type_seq_in(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, const void *inst)
+{
+ struct curr_buf *curr = data;
+ int ret = 0;
+ size_t i;
+
+ if (n_inst) {
+ free((void *) curr->inbuf->ptr);
+ }
+
+ curr->inbuf++;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_in(type, &free_ops, data, &inst);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int free_type_seq_out(const struct hrpc_method_def_interp4 *def,
+ const struct hrpc_inner_type_def_interp4 *type,
+ void *data, size_t n_inst, void *inst)
+{
+ struct curr_buf *curr = data;
+ int ret = 0;
+ size_t i;
+
+ if (n_inst) {
+ free((void *) curr->inbuf->ptr);
+ free((void *) curr->outbuf->ptr);
+ }
+
+ curr->inbuf++;
+ curr->outbuf++;
+
+ for (i = 0; i < n_inst; i++) {
+ ret = emit_inner_type_out(type, &free_ops, data, &inst);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct stage_ops free_ops = {
+ .emit_prim_in = emit_nop_in,
+ .emit_prim_out = emit_nop_out,
+ .emit_inbuf = free_inbuf,
+ .emit_outbuf = free_outbuf,
+ .emit_type_seq_in = free_type_seq_in,
+ .emit_type_seq_out = free_type_seq_out,
+};
+
+static int count_args(const struct hrpc_method_def_interp4 *def,
+ struct buf_count *count, va_list list)
+{
+ int ret;
+
+ if (def->msg_id > 30)
+ count->n_prim_in += 4;
+
+ ret = emit_args(def, &count_ops, count, list);
+ if (ret)
+ return ret;
+
+ if (count->n_prim_in)
+ count->n_inbufs++;
+ if (count->n_prim_out)
+ count->n_outbufs++;
+
+ return 0;
+}
+
+static void free_args(const struct hrpc_method_def_interp4 *def,
+ const struct buf_count *count,
+ struct fastrpc_invoke_args *args,
+ va_list list);
+
+static struct fastrpc_invoke_args *alloc_args(const struct hrpc_method_def_interp4 *def,
+ const struct buf_count *count,
+ va_list list)
+{
+ struct curr_buf curr_buf = { NULL, NULL };
+ struct fastrpc_invoke_args *args;
+ size_t i;
+ int ret = -1;
+ va_list peek;
+
+ args = malloc(sizeof(*args) * (count->n_inbufs + count->n_outbufs));
+ if (args == NULL)
+ return NULL;
+
+ for (i = 0; i < count->n_inbufs + count->n_outbufs; i++) {
+ args[i].fd = -1;
+ args[i].attr = 0;
+ args[i].ptr = 0;
+ }
+
+ curr_buf.inbuf = &args[0];
+ curr_buf.outbuf = &args[count->n_inbufs];
+
+ if (count->n_prim_in) {
+ curr_buf.inbuf->length = count->n_prim_in;
+ curr_buf.inbuf->ptr = (__u64) malloc(count->n_prim_in);
+ if (curr_buf.inbuf->ptr == 0)
+ goto err;
+ curr_buf.inbuf++;
+ }
+
+ if (count->n_prim_out) {
+ curr_buf.outbuf->length = count->n_prim_out;
+ curr_buf.outbuf->ptr = (__u64) malloc(count->n_prim_out);
+ if (curr_buf.outbuf->ptr == 0)
+ goto err;
+ curr_buf.outbuf++;
+ }
+
+ va_copy(peek, list);
+ ret = emit_args(def, &alloc_ops, &curr_buf, peek);
+ va_end(peek);
+ if (ret)
+ goto err;
+
+ return args;
+
+err:
+ va_copy(peek, list);
+ free_args(def, count, args, peek);
+ va_end(peek);
+ return NULL;
+}
+
+static int encode_args(const struct hrpc_method_def_interp4 *def,
+ const struct buf_count *count,
+ struct fastrpc_invoke_args *args,
+ va_list list)
+{
+ struct curr_pos curr_pos;
+
+ curr_pos.buf = &args[0];
+ if (count->n_prim_in) {
+ curr_pos.prim = (void *) args[0].ptr;
+ curr_pos.buf++;
+ } else {
+ curr_pos.prim = NULL;
+ }
+
+ if (def->msg_id > 30) {
+ *(uint32_t *) curr_pos.prim = def->msg_id;
+ curr_pos.prim = (uint32_t *) curr_pos.prim + 1;
+ }
+
+ return emit_args(def, &encode_ops, &curr_pos, list);
+}
+
+static void decode_args(const struct hrpc_method_def_interp4 *def,
+ const struct buf_count *count,
+ struct fastrpc_invoke_args *args,
+ va_list list)
+{
+ struct curr_pos curr_pos;
+
+ curr_pos.buf = &args[count->n_inbufs];
+ if (count->n_prim_out) {
+ curr_pos.prim = (void *) args[count->n_inbufs].ptr;
+ curr_pos.buf++;
+ } else {
+ curr_pos.prim = NULL;
+ }
+
+ emit_args(def, &decode_ops, &curr_pos, list);
+}
+
+static void free_args(const struct hrpc_method_def_interp4 *def,
+ const struct buf_count *count,
+ struct fastrpc_invoke_args *args,
+ va_list list)
+{
+ struct curr_buf curr_buf = { NULL, NULL };
+
+ curr_buf.inbuf = &args[0];
+ curr_buf.outbuf = &args[count->n_inbufs];
+
+ if (count->n_prim_in) {
+ if (curr_buf.inbuf->ptr)
+ free((void *) curr_buf.inbuf->ptr);
+ curr_buf.inbuf++;
+ }
+
+ if (count->n_prim_out) {
+ if (curr_buf.outbuf->ptr)
+ free((void *) curr_buf.outbuf->ptr);
+ curr_buf.outbuf++;
+ }
+
+ emit_args(def, &free_ops, &curr_buf, list);
+
+ free(args);
+}
+
+/*
+ * 1. validate def and count prim_in, prim_out sizes
+ * 2. construct prim_in, sequences with nestings
+ * 3. point inbufs to sequences, nested sequences
+ * 4. return prim_out
+ */
+int vhexagonrpc(const struct hrpc_method_def_interp4 *def,
+ int fd, uint32_t handle, va_list list)
+{
+ struct buf_count count = { 0, 0, 0, 0 };
+ struct fastrpc_invoke invoke;
+ struct fastrpc_invoke_args *args;
+ va_list peek;
+ int ret;
+
+ va_copy(peek, list);
+ ret = count_args(def, &count, peek);
+ va_end(peek);
+ if (ret)
+ return ret;
+
+ va_copy(peek, list);
+ args = alloc_args(def, &count, peek);
+ va_end(peek);
+ if (args == NULL)
+ return -1;
+
+ va_copy(peek, list);
+ ret = encode_args(def, &count, args, peek);
+ va_end(peek);
+ if (ret)
+ goto err;
+
+ invoke.args = (__u64) args;
+ invoke.handle = handle;
+ if (def->msg_id > 30)
+ invoke.sc = REMOTE_SCALARS_MAKE(31,
+ count.n_inbufs, count.n_outbufs);
+ else
+ invoke.sc = REMOTE_SCALARS_MAKE(def->msg_id,
+ count.n_inbufs, count.n_outbufs);
+
+ ret = ioctl(fd, FASTRPC_IOCTL_INVOKE, (__u64) &invoke);
+ if (ret)
+ goto err;
+
+ va_copy(peek, list);
+ decode_args(def, &count, args, peek);
+ va_end(peek);
+
+err:
+ va_copy(peek, list);
+ free_args(def, &count, args, peek);
+ va_end(peek);
+ return ret;
+}
+
+int hexagonrpc(const struct hrpc_method_def_interp4 *def,
+ int fd, uint32_t handle, ...)
+{
+ va_list list;
+ int ret;
+
+ va_start(list, handle);
+ ret = vhexagonrpc(def, fd, handle, list);
+ va_end(list);
+
+ return ret;
+}
diff --git a/libhexagonrpc/interface/remotectl.c b/libhexagonrpc/interface/remotectl.c
new file mode 100644
index 0000000..d1a170b
--- /dev/null
+++ b/libhexagonrpc/interface/remotectl.c
@@ -0,0 +1,52 @@
+/*
+ * Remote processor control interface - method definitions
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+struct hrpc_arg_def_interp4 remotectl_open_args[] = {
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 remotectl_open_def = {
+ .msg_id = 0,
+ .n_args = HRPC_ARRAY_SIZE(remotectl_open_args),
+ .args = remotectl_open_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+struct hrpc_arg_def_interp4 remotectl_close_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
+};
+
+const struct hrpc_method_def_interp4 remotectl_close_def = {
+ .msg_id = 1,
+ .n_args = HRPC_ARRAY_SIZE(remotectl_close_args),
+ .args = remotectl_close_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
diff --git a/libhexagonrpc/meson.build b/libhexagonrpc/meson.build
index 24efb34..6811853 100644
--- a/libhexagonrpc/meson.build
+++ b/libhexagonrpc/meson.build
@@ -1,7 +1,8 @@
libhexagonrpc = shared_library('hexagonrpc',
- 'context.c',
- 'fastrpc.c',
- 'interfaces.c',
+ 'error.c',
+ 'handle.c',
+ 'hexagonrpc.c',
+ 'interface/remotectl.c',
'session.c',
c_args : cflags,
include_directories : include,
diff --git a/tests/meson.build b/tests/meson.build
index e7303c7..70fd8ee 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -24,5 +24,13 @@ test_hexagonfs = executable('test_hexagonfs',
include_directories : include,
)
+test_hexagonrpc = executable('test_hexagonrpc',
+ 'test_hexagonrpc.c',
+ '../libhexagonrpc/hexagonrpc.c',
+ c_args : cflags,
+ include_directories : include,
+)
+
test('iobuffer', test_iobuffer)
test('hexagonfs', test_hexagonfs, args : [sample_file])
+test('hexagonrpc', test_hexagonrpc)
diff --git a/tests/test_hexagonfs.c b/tests/test_hexagonfs.c
index ae9ee7a..38e767d 100644
--- a/tests/test_hexagonfs.c
+++ b/tests/test_hexagonfs.c
@@ -20,8 +20,8 @@
*/
#include
-#include
#include
+#include
#include
#include
diff --git a/tests/test_hexagonrpc.c b/tests/test_hexagonrpc.c
new file mode 100644
index 0000000..f168ad8
--- /dev/null
+++ b/tests/test_hexagonrpc.c
@@ -0,0 +1,177 @@
+/*
+ * FastRPC reverse tunnel - tests for virtual filesystem
+ *
+ * Copyright (C) 2025 HexagonRPC Contributors
+ *
+ * This file is part of HexagonRPC.
+ *
+ * HexagonRPC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __GLIBC__
+typedef unsigned long int ioctl_operation;
+#else
+typedef int ioctl_operation;
+#endif
+
+struct expected_invoke_arg {
+ size_t len;
+ const void *ptr;
+};
+
+static const struct expected_invoke_arg *expected = NULL;
+static uint32_t expected_sc = 0;
+
+static const uint32_t no_args_sc = REMOTE_SCALARS_MAKE(0, 0, 0);
+
+static const struct hrpc_method_def_interp4 no_args_def = {
+ .msg_id = 0,
+ .n_args = 0,
+ .args = NULL,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+static const char scalar_arg_exp0[] = {
+ 0x67, 0x45, 0x23, 0x01,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+static const char scalar_arg_exp1[] = {
+ 'h', 'i',
+};
+
+static const struct expected_invoke_arg scalar_arg_exp[] = {
+ {
+ .len = sizeof(scalar_arg_exp0),
+ .ptr = scalar_arg_exp0,
+ },
+ {
+ .len = sizeof(scalar_arg_exp1),
+ .ptr = scalar_arg_exp1,
+ },
+ {
+ .len = 0,
+ .ptr = NULL,
+ },
+};
+
+static const uint32_t scalar_arg_sc = REMOTE_SCALARS_MAKE(0, 3, 0);
+
+static const struct hrpc_arg_def_interp4 scalar_arg_args[] = {
+ { HRPC_ARG_WORD, sizeof(uint32_t) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+ { HRPC_ARG_BLOB_SEQ, sizeof(char) },
+};
+
+static const struct hrpc_method_def_interp4 scalar_arg_def = {
+ .msg_id = 0,
+ .n_args = HRPC_ARRAY_SIZE(scalar_arg_args),
+ .args = scalar_arg_args,
+ .n_inner_types = 0,
+ .inner_types = NULL,
+};
+
+int ioctl(int fd, ioctl_operation op, ...)
+{
+ struct fastrpc_invoke *invoke;
+ struct fastrpc_invoke_args *args;
+ size_t i, n_inbufs, n_outbufs;
+ void *data;
+ va_list list;
+
+ va_start(list, op);
+ data = va_arg(list, void *);
+ va_end(list);
+
+ if (op != (ioctl_operation) FASTRPC_IOCTL_INVOKE) {
+ return syscall(SYS_ioctl, fd, op, data);
+ } else {
+ invoke = data;
+
+ if (fd != -1)
+ return -1;
+
+ if (invoke->handle != 0)
+ return -1;
+
+ if (invoke->sc != expected_sc)
+ return -1;
+
+ n_inbufs = REMOTE_SCALARS_INBUFS(invoke->sc);
+ n_outbufs = REMOTE_SCALARS_OUTBUFS(invoke->sc);
+ args = (struct fastrpc_invoke_args *) invoke->args;
+
+ for (i = 0; i < n_inbufs; i++) {
+ if (args[i].fd != -1 || args[i].attr != 0)
+ return -1;
+
+ if (args[i].length != expected[i].len)
+ return -1;
+
+ if (memcmp((void *) args[i].ptr,
+ expected[i].ptr,
+ args[i].length))
+ return -1;
+ }
+
+ for (i = n_inbufs; i < n_inbufs + n_outbufs; i++) {
+ if (args[i].fd != -1 || args[i].attr != 0)
+ return -1;
+
+ if (args[i].length < expected[i].len)
+ return -1;
+
+ memcpy((void *) args[i].ptr,
+ expected[i].ptr,
+ args[i].length);
+ }
+
+ return 0;
+ }
+}
+
+int main(void)
+{
+ int ret, fd = -1;
+ uint32_t hdl = 0;
+
+ expected_sc = no_args_sc;
+ expected = NULL;
+ ret = hexagonrpc(&no_args_def, fd, hdl);
+ if (ret)
+ return 1;
+
+ expected_sc = scalar_arg_sc;
+ expected = scalar_arg_exp;
+ ret = hexagonrpc(&scalar_arg_def, fd, hdl,
+ (uint32_t) 0x01234567,
+ (uint32_t) 2, (const void *) "hi",
+ (uint32_t) 0, (const void *) NULL);
+ if (ret)
+ return 1;
+
+ return 0;
+}
diff --git a/tests/test_iobuffer.c b/tests/test_iobuffer.c
index 99da73f..a252f24 100644
--- a/tests/test_iobuffer.c
+++ b/tests/test_iobuffer.c
@@ -19,7 +19,8 @@
* along with this program. If not, see .
*/
-#include
+#include
+#include
#include
#include "../hexagonrpcd/iobuffer.h"