Author SHA1 Message Date
Richard Acayan 92237debf1 fastrpc: hexagonrpcd: listener: switch to interp3
For a proper transition to version 3 of the method definitions, switch
the reverse tunnel to version 3.
2024-12-30 18:11:00 -05:00
Richard Acayan 64bff607fe fastrpc: hexagonrpcd: use interface-defined inline functions
The inline functions are convenient, but shouldn't be defined in every
source file that uses them. Use the new functions defined in the
interface definitions.
2024-12-30 18:11:00 -05:00
Richard Acayan b15e721660 fastrpc: chrecd: interfaces: convert to interp3
Add the remote method definitions for the CHRE interface according to
the 3rd format version.
2024-12-30 18:11:00 -05:00
Richard Acayan eee667b6cc fastrpc: hexagonrpcd: interfaces: convert to interp3
Add the remote method definitions for interfaces used by HexagonRPCD
according to the 3rd format version.
2024-12-30 18:11:00 -05:00
Richard Acayan 13c14c1611 fastrpc: libhexagonrpc: add error API
When the kernel side of FastRPC fails, the return value is -1 and errno
is set. When the remote side of FastRPC fails, the return value is an
AEE error code. It is not specialized for the reverse tunnel. Add an
error API that can convert the return value to a string-based error.
2024-12-30 18:11:00 -05:00
Richard Acayan 916db473b4 fastrpc: libhexagonrpc: interfaces: remotectl: add interp3 definitions
Add the remote method definitions according to the 3rd format version.
2024-12-30 18:10:44 -05:00
Richard Acayan 09add3eecc fastrpc: libhexagonrpc: add interpretation three of method call format
The method call format as interpreted last time had some limitations.
First, input words could not appear after the input buffers, making it
impossible to represent the apps_std_mkdir method accurately. Second, it
was assumed that the lengths in the primary input buffer represent the
number of bytes. In reality, the lengths represent the number of
elements, which just happened to be octets in the majority of remote
methods found, and the adsp_perf_get_usecs remote method could not be
represented. Update the format for the third time to remove these
limitations.

This format allows the mixing of words and lengths of other buffers in
the primary buffer by using 0 to denote words in an array of arguments.
It also allows a greater size of elements, denoted by any non-zero
value.
2024-10-16 19:43:41 -04:00
Alex 2415d5f90d Add soversion to the library build 2024-10-16 17:53:03 -04:00
Richard Acayan 7aab0f2c42 meson.options: disable verbose logging by default
Verbose logging can be useful when something goes wrong, but HexagonRPCD
already works well on some devices. Disable verbose logging by default.

Reported by Adrian on the SDM845 Mainline Matrix channel.

Fixes: 30fa49eb20 ("build: add hexagonrpcd_verbose option")
2024-05-16 16:00:13 -04:00
Joel Selvaraj b7eff23db1 hexagonrpcd/rpcd_builder: introduce /system/vendor mapping
Needed for some Xiaomi phones such as the Poco F1.
Based on https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/1.
Thanks to the initial work of @longnoserob in the above MR!
2024-05-14 02:03:35 -05:00
Joel Selvaraj 716e1e27c7 README: add socinfo sysfs mapping to HexagonFS table
Introduced in https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/2.
2024-05-14 02:03:35 -05:00
Joel Selvaraj 54ba43fbc3 hexagonrpcd/rpcd_builder: add mapping for socinfo sysfs
Needed for some Xiaomi phones such as Poco F1.
Based on https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/1.
Thanks to the initial findings of @longnoserob in the above MR!
2024-05-14 01:49:46 -05:00
Richard Acayan f6d8a0e686 tests: add initial hexagonfs test
The virtual filesystem is important, but is only tested in the full
program. Add the initial test for it.
2024-04-26 17:50:58 -04:00
Richard Acayan 9db873f24f hexagonrpcd: hexagonfs: constify dirent data
The data in the directory entry structure is meant to be used in opening
a file. It should not change during the program.

For the virtual directory, the pointer to constant data must be wrapped
because the data for the open file is not constant.
2024-04-17 17:03:07 -04:00
Richard Acayan 3f46980dc9 hexagonrpcd: correct -d default in help text
The name of the DSP defaults to none, but the -d option is wrongly
documented as having a default of "adsp". Correct this in the help text.
2024-04-15 18:35:46 -04:00
Richard Acayan 30fa49eb20 build: add hexagonrpcd_verbose option
There is extra debug logging in the code which can be activated by
`meson configure build -Dc_args=-DHEXAGONRPC_VERBOSE`. This may be
difficult to trigger, since it requires -D twice in the same argument.
Add the hexagonrpcd_verbose option to make it easier to configure the
extra logging.

This can be activated with `-Dhexagonrpcd_verbose=true` and deactivated
with `-Dhexagonrpcd_verbose=false`.
2024-04-11 17:59:03 -04:00
Richard Acayan b7ad1021a2 build: apply default C flags to all targets
The warning flags should be applied to the entire C codebase in order to
help ensure correct code. No extra warnings are emitted by doing this.
2024-04-11 17:45:47 -04:00
Richard Acayan f23297f962 tests: set warning flags
Most subdirectories in this project have all, pedantic, and some extra
warnings enabled. Set this for tests as well, as there is no real
justification otherwise.
2024-04-09 19:18:44 -04:00
Richard Acayan c4c469bd8a tests: iobuffer: convert binary data to unsigned char arrays
Signed character arrays can overflow when specifying values greater than
127. The actual data is not affected, but this can cause compiler
warnings. Use unsigned character arrays so the compiler does not
complain about overflows.
2024-04-09 19:16:04 -04:00
Richard Acayan 6840e1dcfa tests: iobuffer: exit with code 0 on success
This file seems to implicitly return 0 when everything is successful,
but this is unclear when reading it. Explicitly return zero when all
tests are successful.
2024-04-09 19:10:30 -04:00
Richard Acayan aaef8a1e28 hexagonrpcd: use the dsp directory as the default for libraries
This variable represents the subdirectory in the dsp/ directory where
libraries should be searched. This is the argument to the optional `-d`
and is used when creating the filesystem. Initialize it to an empty
string so HexagonFS searches in /usr/share/qcom/dsp/ by default.
2024-04-09 17:05:21 -04:00
Richard Acayan 63b1711021 move fastrpc to project root
The FastRPC implementation is loosely related to the sensor shell. It is
useful to provide interfaces over FastRPC for sensor DSP firmware, and
enables the sensor shell to provide most physical sensors. However, the
FastRPC implementation has no meaningful connection with the sensor
shell in terms of code. Move the FastRPC implementation to the project
root to make it more intuitive to install and use and to separate it
from a distinct project.
2024-03-01 21:48:39 -05:00
Richard Acayan 39dd3aec6e fastrpc: separate chre client
The CHRE client is not part of the core functionality of the daemon. The
client is only meant to run on sensorspd, and should not always run,
such as on non-Android or on rootpd. It should not be stuck in the file
with the program's entry point, as it needs to do more than simply
starting CHRE, like starting any useful nanoapps. Move it into a new
directory as a client that can use the same session as the daemon that
listens for remote method calls to the Application Processor, so the
session can make calls back to fetch files.

Also modify the calling conventions for starting the reverse tunnel,
since the calling conventions are not limited to a single pointer.
2024-03-01 21:24:29 -05:00
Richard Acayan 892b9f549e fastrpc: libhexagonrpc: add session API
The HexagonRPCD daemon has support for sharing sessions with other
programs by executing them with the HEXAGONRPC_FD environment variable
set. Add a library function to obtain the file descriptor used in this
session for FastRPC communication.
2024-03-01 21:24:29 -05:00
Richard Acayan b410c74a81 fastrpc: hexagonrpcd: fork managed clients
The Linux kernel FastRPC driver creates a unique session for every
process that opens a file descriptor. Session sharing allows the sharing
of a reverse tunnel across clients that need it. Add support for
managing the session for clients.

The argument to -p is a path to any executable file, such as /bin/sh.
The file descriptor to the FastRPC device node is in the HEXAGONRPC_FD
environment variable.
2024-03-01 21:24:29 -05:00
Richard Acayan 24c3eea173 fastrpc: hexagonrpcd: reword usage text and print on missing option
Remove the brackets around the -f option which imply that it is
optional. The default value is a NULL pointer.

FastRPC is not specialized to serving files to the DSPs and can do other
things such as logging and profiling, pending discovery. Change the
description of the program accordingly.

Referring to a "FastRPC node" is a bit vague and misses the detail that
the program is expecting a path to a file (a device node). Refer to the
file as a FastRPC device node so the user can intuitively look for what
the program wants.

The letter in the -R option was seemingly chosen arbitrarily. Add the
word which it originated from ("root") to make it memorable.

The INIT_ATTACH and INIT_ATTACH_SNS terms have no meaning in the usage
text. They are terms of jargon originating in the userspace API for the
Linux kernel driver, as abbreviations of FASTRPC_IOCTL_INIT_ATTACH and
FASTRPC_IOCTL_INIT_ATTACH_SNS. It is unclear what the difference is
between the two, and SNS is ambiguous with no clear connection to
sensors (did Qualcomm design some DSP communication protocol around a
Social Networking Service?). Instead of deriving terms used to inform
the driver how to interact with the DSP, use the name of the
PD ("sensorspd") and describe the effective interaction with the DSP.

If the file name for the FastRPC device node is a NULL pointer, then the
error message always prints out a NULL pointer, made redundant by the
word "invalid". An unspecified device node is an error made by the user,
and the usage text should be given to the user instead of an internal
diagnosis of invalid usage.
2024-03-01 21:24:29 -05:00
Richard Acayan 8949140fa6 fastrpc: move remotectl interface to libhexagonrpc
This is useful for most programs using FastRPC, so it does not make
sense to copy the interface every time. Move it to libhexagonrpc, even
though it may not be strictly necessary to communicate over FastRPC,
since it is common.
2024-03-01 21:24:28 -05:00
Richard Acayan 154bd2631c fastrpc: hexagonrpcd: build: suppress unused parameter warnings
Warnings on unused variables or functions can be fixed by removing the
unnecessary variable or function. Unused parameters are a regular
occurrence, and cannot be removed. Warnings about these may be useful
for new internal APIs with long development histories, but clutter any
build logs with meaningless warnings about unused parameters when
defining functions to be used with existing APIs, such as the reverse
tunnel API. Suppress these warnings to bring any more meaningful issues
to attention.
2024-01-15 19:37:14 -05:00
64 changed files with 1510 additions and 2087 deletions

No files matched your search

-65
View File
@@ -1,65 +0,0 @@
#
# Build system
#
# Copyright (C) 2022 Richard Acayan
#
# 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 <https://www.gnu.org/licenses/>.
#
QMIC = qmic
CC = gcc
LIBS = -lprotobuf-c -lqrtr
CFLAGS = -Wall -Wextra -Wpedantic -Ibuild -I.
PROTOC_C = protoc-c
build/sensh: build/sensh.o build/qmi_sns_client.o build/sns_client_event_msg.pb-c.o build/sns_client_request_msg.pb-c.o build/sns_proximity_event.pb-c.o build/sns_std_attr_event.pb-c.o build/sns_std_attr_req.pb-c.o build/sns_std_sensor_event.pb-c.o build/sns_std_suid.pb-c.o build/sns_suid_event.pb-c.o build/sns_suid_req.pb-c.o
$(CC) -o build/sensh build/sensh.o build/qmi_sns_client.o build/sns_client_event_msg.pb-c.o build/sns_client_request_msg.pb-c.o build/sns_proximity_event.pb-c.o build/sns_std_attr_event.pb-c.o build/sns_std_attr_req.pb-c.o build/sns_std_sensor_event.pb-c.o build/sns_std_suid.pb-c.o build/sns_suid_event.pb-c.o build/sns_suid_req.pb-c.o $(LIBS)
build/qmi_%.d: build/qmi_%.c
$(CC) $(CFLAGS) -MM -MT build/$*.o -o $@ $<
build/%.pb-c.d: build/%.pb-c.c
$(CC) $(CFLAGS) -MM -MT build/$*.o -o $@ $<
build/%.d: %.c
$(CC) $(CFLAGS) -MM -MT build/$*.o -o $@ $<
build/qmi_%.o: build/qmi_%.c
$(CC) $(CFLAGS) -c -o $@ $<
build/%.pb-c.o: build/%.pb-c.c
$(CC) $(CFLAGS) -c -o $@ $<
build/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
build/qmi_%.c build/qmi_%.h: qmi/%.qmi
cd build && $(QMIC) -k < ../$<
build/%.pb-c.c build/%.pb-c.h: protobuf/%.proto
$(PROTOC_C) --c_out=build -Iprotobuf $<
include build/sensh.d
include build/qmi_sns_client.d
include build/sns_client_event_msg.pb-c.d
include build/sns_client_request_msg.pb-c.d
include build/sns_proximity_event.pb-c.d
include build/sns_std_attr_event.pb-c.d
include build/sns_std_attr_req.pb-c.d
include build/sns_std_sensor_event.pb-c.d
include build/sns_std_suid.pb-c.d
include build/sns_suid_event.pb-c.d
include build/sns_suid_req.pb-c.d
+135 -48
View File
@@ -1,64 +1,151 @@
This is a proof-of-concept for interacting with the Snapdragon Sensor Core
using the reverse-engineered protocol buffers. It was made to try to
initialize it, but the Pixel 3a is missing some sensors once the firmware is
loaded.
This directory contains a FastRPC ioctl wrapper and a reverse tunnel.
A best effort is made to prefix all log messages with `sensh: ` so it's clear
which lines were entered by the user.
FastRPC is used to communicate with the Context Hub Runtime Environment, a
program on the DSP that manages sensors, and to serve files to remote
processors.
# Requirements
# Wrapper function
- gcc
- libqrtr
- meson or make
- protobuf-c
- qmic (optional for regenerating QMI, at https://github.com/andersson/qmic)
The wrapper function is designed so that the ioctl arguments do not need to be
constructed for each remote method. Instead, it accepts an open file descriptor,
handle, method definition, and arguments to the remote method using `va_args`.
This makes it relatively easy to add remote methods without the use of the QAIC
interface compiler or a free software alternative.
# Installation
## Installation
This can be compiled using Meson:
You can build and install this project using meson:
$ meson setup build
$ ninja -C build
~/sensh/fastrpc $ meson setup build
~/sensh/fastrpc $ ninja -C build
~/sensh/fastrpc # ninja -C build install
There is also a Makefile to compile this, if you can get it to work:
## Usage
$ mkdir build
$ make -k
Making already-defined method calls is relatively straightforward, depending on
the remote method that you're calling. You just need the function definition, an
open file descriptor, the handle, and the arguments for it.
# Usage
uint32_t prev_ctx, prev_result, nested_outbufs_len;
uint32_t ctx, nested_handle, nested_sc, nested_inbufs_len;
uint32_t nested_inbufs_size;
const void *nested_outbufs;
void *nested_inbufs;
int fd;
Sensh doesn't automatically track, probe, or look up sensors; that is for a full
implementation. Instead, it expects you to look up the sensor and copy the ID
with your terminal emulator:
ret = fastrpc2(&adsp_listener_next2_def, fd, ADSP_LISTENER_HANDLE,
prev_ctx,
prev_result,
nested_outbufs_len, nested_outbufs,
&ctx,
&nested_handle,
&nested_sc,
&nested_inbufs_len,
nested_inbufs_size, nested_inbufs);
lookup accel_cal
sensh: accel_cal sensor found: A1392FDF217B7D9EI6648AED8C04DDFB9
attr A1392FDF217B7D9EI6648AED8C04DDFB9
sensh: name: ASH_CAL
sensh: vendor: GOOGLE
sensh: type: accel_cal
sensh: version: 1
sensh: api: sns_cal.proto
sensh: rates: 10.000000
sensh: stream type: 1
sensh: physical sensor: 0
sensh: available: 1
All inputs are specified before all outputs. Words in the first (called "prim",
or primary in QAIC-generated code) input and output buffers go in the form of
`uint32_t` arguments. Each buffer is accepted as a `uint32_t` length and a
pointer.
You can send 3 messages: lookup, attr, and watch. The lookup command returns
SUIDs for the passed data type. The attr command returns attributes for the
sensor. Finally, the watch command tells the sensor core to send events from a
sensor whenever the sensor's value changes.
### Creating function definitions
An EOF (normally Ctrl+D) is enough to exit the shell unless the sensor core
died.
Assuming you already have knowledge about the remote method to call, you must
first write a function definition for it. A function definition is a struct with
information on its method ID and the arguments it accepts.
# References
First, the method ID is taken from the first argument of the
`REMOTE_SCALARS_MAKE()` macro or the second argument of the
`REMOTE_SCALARS_MAKEX()` macro
(defined [here](https://android.googlesource.com/platform/external/fastrpc/+/d6d6e3bba244e40e6043bd687f4cacf090a767b5/inc/remote.h#80)).
The following sources were used as reference:
Example:
- [https://android.googlesource.com/platform/system/chre](https://android.googlesource.com/platform/system/chre)
- [https://android.googlesource.com/platform/external/fastrpc](https://android.googlesource.com/platform/external/fastrpc)
- [https://github.com/calebccff/sensordaemon-re](https://github.com/calebccff/sensordaemon-re)
- [https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/merge\_requests/346](https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/merge_requests/346)
- [https://git.linaro.org/landing-teams/working/qualcomm/fastrpc.git](https://git.linaro.org/landing-teams/working/qualcomm/fastrpc.git)
REMOTE_SCALARS_MAKE(4, 2, 2)
has the method 4.
Next, information on how many arguments it takes must be specified. There are
four types of arguments:
- 32-bit input words in the first input buffer, excluding lengths for the input
and output buffers
- 32-bit output words in the first output buffer
- input buffers, excluding the first
- output buffers, excluding the first
To get the size of the first input and output buffers, a dump must be consulted,
or the prim argument of generated C files:
invoking via fastrpc, handle 3, method 4, 2 inbufs, 2 outbufs, 0 inhandles, 0 outhandles
fastrpc argument 00000000FFFFFFFF0000000000000000 // 16 bytes, or 4 words
fastrpc argument
invoking via fastrpc, handle 5, method 4, 1 inbufs, 1 outbufs, 0 inhandles, 0 outhandles
fastrpc return 91000000000000000002020029000000 // 16 bytes, or 4 words
fastrpc return
Since there are 2 input buffers excluding the first (these can have a variable
size), 2 must be subtracted from the 4 input words. These will be provided by
the wrapper as the sizes for the variable-length input and output buffers.
Counting each of these will give the numbers needed for the function definition.
A function definition looks like:
const struct fastrpc_function_def_interp2 adsp_listener_next2_def = {
.msg_id = 4,
.in_nums = 2,
.in_bufs = 1,
.out_nums = 4,
.out_bufs = 1,
};
or:
#define DEFINE_REMOTE_PROCEDURE(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, \
};
DEFINE_REMOTE_PROCEDURE(4, adsp_listener_next2, 2, 1, 4, 1)
# Reverse tunnel
The reverse tunnel calls the `adsp_listener_next2` remote method to receive
method calls for the Application Processor.
Interfaces are initialized in the `start_reverse_tunnel` function, in hexagonrpcd/rpcd.c.
## HexagonFS
The reverse tunnel's `apps_std` interface serves files to the remote processor.
These files are searched for in:
Physical file/dir Android file/dir
/usr/share/qcom/acdb /vendor/etc/acdbdata
/usr/share/qcom/dsp /vendor/dsp
/usr/share/qcom/sensors/config /vendor/etc/sensors/config
/usr/share/qcom/sensors/registry /mnt/vendor/persist/sensors/registry/registry
/usr/share/qcom/sensors/sns_reg.conf /vendor/etc/sensors/sns_reg_config
/usr/share/qcom/socinfo /sys/devices/soc0
These files and directories should be populated with files from your device's
Android firmware.
# Future plans
Reverse tunnels are separated by the process that opens the file descriptor and
cannot service requests from other processes that do not share the same file
descriptor. There should be some daemon that opens the device and allows clients
to send requests.
FastRPC may be the way to offload work to the DSPs. When a FastRPC function call
is made, the `<name>_skel_invoke` function in a shared object named
`lib<name>_skel.so` is called on the DSP. Further investigation is needed to
make a working build system for this.
@@ -1,7 +1,7 @@
/*
* Sensor SUID
* FastRPC interface list for building method definitions
*
* Copyright (C) 2022 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -19,9 +19,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
syntax = "proto2";
#define HEXAGONRPC_BUILD_METHOD_DEFINITIONS 1
message sns_std_suid {
required fixed64 suid_low = 1;
required fixed64 suid_high = 2;
}
#include "interfaces/chre_slpi.def"
@@ -27,4 +27,18 @@
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)
HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(0, chre_slpi3_start_thread)
static inline int chre_slpi3_start_thread(const struct fastrpc_context *ctx)
{
return hexagonrpc(&chre_slpi3_start_thread_def, ctx);
}
HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(1, chre_slpi3_wait_on_thread_exit)
static inline int chre_slpi3_wait_on_thread_exit(const struct fastrpc_context *ctx)
{
return hexagonrpc(&chre_slpi3_wait_on_thread_exit_def, ctx);
}
#endif /* INTERFACE_CHRE_SLPI_DEF */
+124
View File
@@ -0,0 +1,124 @@
/*
* CHRE client daemon entry point
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <libhexagonrpc/fastrpc.h>
#include <libhexagonrpc/interfaces/remotectl.def>
#include <libhexagonrpc/session.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}
int main()
{
struct fastrpc_context *ctx;
int fd, ret;
fd = hexagonrpc_fd_from_env();
if (fd == -1)
return 1;
ret = remotectl_open(fd, "chre_slpi", &ctx, remotectl_err);
if (ret)
return 1;
ret = chre_slpi_start_thread(ctx);
if (ret) {
fprintf(stderr, "Could not start CHRE\n");
goto err;
}
ret = chre_slpi_wait_on_thread_exit(ctx);
if (ret) {
fprintf(stderr, "Could not wait for CHRE thread\n");
goto err;
}
err:
remotectl_close(ctx, remotectl_err);
}
+9
View File
@@ -0,0 +1,9 @@
executable('chrecd',
'interfaces.c',
'main.c',
c_args : cflags,
include_directories : include,
install : true,
link_with : libhexagonrpc,
install_dir : client_target,
)
-150
View File
@@ -1,150 +0,0 @@
This directory contains a FastRPC ioctl wrapper and a reverse tunnel.
FastRPC is used to communicate with the Context Hub Runtime Environment, a
program on the DSP that manages sensors, and to serve files to remote
processors.
# Wrapper function
The wrapper function is designed so that the ioctl arguments do not need to be
constructed for each remote method. Instead, it accepts an open file descriptor,
handle, method definition, and arguments to the remote method using `va_args`.
This makes it relatively easy to add remote methods without the use of the QAIC
interface compiler or a free software alternative.
## Installation
You can build and install this project using meson:
~/sensh/fastrpc $ meson setup build
~/sensh/fastrpc $ ninja -C build
~/sensh/fastrpc # ninja -C build install
## Usage
Making already-defined method calls is relatively straightforward, depending on
the remote method that you're calling. You just need the function definition, an
open file descriptor, the handle, and the arguments for it.
uint32_t prev_ctx, prev_result, nested_outbufs_len;
uint32_t ctx, nested_handle, nested_sc, nested_inbufs_len;
uint32_t nested_inbufs_size;
const void *nested_outbufs;
void *nested_inbufs;
int fd;
ret = fastrpc2(&adsp_listener_next2_def, fd, ADSP_LISTENER_HANDLE,
prev_ctx,
prev_result,
nested_outbufs_len, nested_outbufs,
&ctx,
&nested_handle,
&nested_sc,
&nested_inbufs_len,
nested_inbufs_size, nested_inbufs);
All inputs are specified before all outputs. Words in the first (called "prim",
or primary in QAIC-generated code) input and output buffers go in the form of
`uint32_t` arguments. Each buffer is accepted as a `uint32_t` length and a
pointer.
### Creating function definitions
Assuming you already have knowledge about the remote method to call, you must
first write a function definition for it. A function definition is a struct with
information on its method ID and the arguments it accepts.
First, the method ID is taken from the first argument of the
`REMOTE_SCALARS_MAKE()` macro or the second argument of the
`REMOTE_SCALARS_MAKEX()` macro
(defined [here](https://android.googlesource.com/platform/external/fastrpc/+/d6d6e3bba244e40e6043bd687f4cacf090a767b5/inc/remote.h#80)).
Example:
REMOTE_SCALARS_MAKE(4, 2, 2)
has the method 4.
Next, information on how many arguments it takes must be specified. There are
four types of arguments:
- 32-bit input words in the first input buffer, excluding lengths for the input
and output buffers
- 32-bit output words in the first output buffer
- input buffers, excluding the first
- output buffers, excluding the first
To get the size of the first input and output buffers, a dump must be consulted,
or the prim argument of generated C files:
invoking via fastrpc, handle 3, method 4, 2 inbufs, 2 outbufs, 0 inhandles, 0 outhandles
fastrpc argument 00000000FFFFFFFF0000000000000000 // 16 bytes, or 4 words
fastrpc argument
invoking via fastrpc, handle 5, method 4, 1 inbufs, 1 outbufs, 0 inhandles, 0 outhandles
fastrpc return 91000000000000000002020029000000 // 16 bytes, or 4 words
fastrpc return
Since there are 2 input buffers excluding the first (these can have a variable
size), 2 must be subtracted from the 4 input words. These will be provided by
the wrapper as the sizes for the variable-length input and output buffers.
Counting each of these will give the numbers needed for the function definition.
A function definition looks like:
const struct fastrpc_function_def_interp2 adsp_listener_next2_def = {
.msg_id = 4,
.in_nums = 2,
.in_bufs = 1,
.out_nums = 4,
.out_bufs = 1,
};
or:
#define DEFINE_REMOTE_PROCEDURE(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, \
};
DEFINE_REMOTE_PROCEDURE(4, adsp_listener_next2, 2, 1, 4, 1)
# Reverse tunnel
The reverse tunnel calls the `adsp_listener_next2` remote method to receive
method calls for the Application Processor.
Interfaces are initialized in the `start_reverse_tunnel` function, in hexagonrpcd/rpcd.c.
## HexagonFS
The reverse tunnel's `apps_std` interface serves files to the remote processor.
These files are searched for in:
Physical file/dir Android file/dir
/usr/share/qcom/acdb /vendor/etc/acdbdata
/usr/share/qcom/dsp /vendor/dsp
/usr/share/qcom/sensors/config /vendor/etc/sensors/config
/usr/share/qcom/sensors/registry /mnt/vendor/persist/sensors/registry/registry
/usr/share/qcom/sensors/sns_reg.conf /vendor/etc/sensors/sns_reg_config
These files and directories should be populated with files from your device's
Android firmware.
# Future plans
Reverse tunnels are separated by the process that opens the file descriptor and
cannot service requests from other processes that do not share the same file
descriptor. There should be some daemon that opens the device and allows clients
to send requests.
FastRPC may be the way to offload work to the DSPs. When a FastRPC function call
is made, the `<name>_skel_invoke` function in a shared object named
`lib<name>_skel.so` is called on the DSP. Further investigation is needed to
make a working build system for this.
@@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef INTERFACE_APPS_STD_DEF
#define INTERFACE_APPS_STD_DEF
#include <libhexagonrpc/interface.h>
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 */
-9
View File
@@ -1,9 +0,0 @@
project('fastrpc', 'c')
include = include_directories('include')
subdir('libhexagonrpc')
subdir('hexagonrpcd')
subdir('tests')
-13
View File
@@ -1,13 +0,0 @@
valgrind = find_program('valgrind', required : false)
if valgrind.found()
add_test_setup('valgrind', exe_wrapper : valgrind)
endif
test_iobuffer = executable('test_iobuffer',
'test_iobuffer.c',
'../hexagonrpcd/iobuffer.c',
include_directories : include,
)
test('iobuffer', test_iobuffer)
@@ -20,13 +20,13 @@
*/
#include <errno.h>
#include <libhexagonrpc/error.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "aee_error.h"
#include "interfaces/apps_std.def"
#include "hexagonfs.h"
#include "iobuffer.h"
@@ -408,15 +408,15 @@ static const struct fastrpc_function_impl apps_std_procs[] = {
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{
.def = &apps_std_fflush_def,
.def = &apps_std3_fflush_def,
.impl = apps_std_fflush,
},
{
.def = &apps_std_fclose_def,
.def = &apps_std3_fclose_def,
.impl = apps_std_fclose,
},
{
.def = &apps_std_fread_def,
.def = &apps_std3_fread_def,
.impl = apps_std_fread,
},
{ .def = NULL, .impl = NULL, },
@@ -424,7 +424,7 @@ static const struct fastrpc_function_impl apps_std_procs[] = {
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{
.def = &apps_std_fseek_def,
.def = &apps_std3_fseek_def,
.impl = apps_std_fseek,
},
{ .def = NULL, .impl = NULL, },
@@ -437,7 +437,7 @@ static const struct fastrpc_function_impl apps_std_procs[] = {
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{
.def = &apps_std_fopen_with_env_def,
.def = &apps_std3_fopen_with_env_def,
.impl = apps_std_fopen_with_env,
},
{ .def = NULL, .impl = NULL, },
@@ -447,21 +447,21 @@ static const struct fastrpc_function_impl apps_std_procs[] = {
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{
.def = &apps_std_opendir_def,
.def = &apps_std3_opendir_def,
.impl = apps_std_opendir,
},
{
.def = &apps_std_closedir_def,
.def = &apps_std3_closedir_def,
.impl = apps_std_closedir,
},
{
.def = &apps_std_readdir_def,
.def = &apps_std3_readdir_def,
.impl = apps_std_readdir,
},
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{
.def = &apps_std_stat_def,
.def = &apps_std3_stat_def,
.impl = apps_std_stat,
},
};
File renamed without changes.
File renamed without changes.
@@ -33,7 +33,7 @@ struct hexagonfs_fd;
struct hexagonfs_file_ops {
void (*close)(void *fd_data);
int (*from_dirent)(void *dirent_data, bool dir, void **fd_data);
int (*from_dirent)(const void *dirent_data, bool dir, void **fd_data);
int (*openat)(struct hexagonfs_fd *dir,
const char *segment,
bool expect_dir,
@@ -47,7 +47,7 @@ static void mapped_close(void *fd_data)
free(ctx);
}
static int mapped_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
struct mapped_ctx *ctx;
const char *name = dirent_data;
@@ -222,7 +222,7 @@ static void mapped_or_empty_close(void *fd_data)
mapped_close(fd_data);
}
static int mapped_or_empty_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_or_empty_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
int ret;
@@ -41,7 +41,7 @@ static void plat_subtype_name_close(void *fd_data)
free(ctx->name);
}
static int plat_subtype_name_from_dirent(void *dirent_data,
static int plat_subtype_name_from_dirent(const void *dirent_data,
bool dir,
void **fd_data)
{
@@ -54,7 +54,7 @@ static int plat_subtype_name_from_dirent(void *dirent_data,
if (ctx == NULL)
return -ENOMEM;
ctx->fd = open((const char *) dirent_data, O_RDONLY);
ctx->fd = open(dirent_data, O_RDONLY);
if (ctx->fd == -1)
return -errno;
@@ -31,10 +31,10 @@
* This function searches for the relevant path segment in the path directory.
* It is not optimized because it is dealing with small directories.
*/
static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
static const struct hexagonfs_dirent *walk_dir(const struct hexagonfs_dirent *const *dir,
const char *segment)
{
struct hexagonfs_dirent **curr = dir;
const struct hexagonfs_dirent *const *curr = dir;
while (*curr != NULL) {
if (!strcmp(segment, (*curr)->name))
@@ -46,9 +46,17 @@ static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
return *curr;
}
static int virt_dir_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int virt_dir_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
*fd_data = dirent_data;
const struct hexagonfs_dirent *const **wrapper;
wrapper = malloc(sizeof(*wrapper));
if (wrapper == NULL)
return -ENOMEM;
*wrapper = dirent_data;
*fd_data = wrapper;
return 0;
}
@@ -57,12 +65,12 @@ static int virt_dir_openat(struct hexagonfs_fd *dir,
bool expect_dir,
struct hexagonfs_fd **out)
{
const struct hexagonfs_dirent *const **dirlist = dir->data;
const struct hexagonfs_dirent *ent;
struct hexagonfs_fd *fd;
struct hexagonfs_dirent *ent;
struct hexagonfs_dirent **dirlist = dir->data;
int ret;
ent = walk_dir(dirlist, segment);
ent = walk_dir(*dirlist, segment);
if (ent == NULL)
return -ENOENT;
@@ -89,6 +97,7 @@ err:
static void virt_dir_close(void *fd_data)
{
free(fd_data);
}
static int virt_dir_stat(struct hexagonfs_fd *fd, struct stat *stats)
@@ -24,5 +24,3 @@
#include "interfaces/adsp_default_listener.def"
#include "interfaces/apps_std.def"
#include "interfaces/adsp_listener.def"
#include "interfaces/chre_slpi.def"
#include "interfaces/remotectl.def"
@@ -26,4 +26,11 @@
HEXAGONRPC_DEFINE_REMOTE_METHOD(0, adsp_default_listener_register, 0, 0, 0, 0)
HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(0, adsp_default_listener3_register)
static inline int adsp_default_listener3_register(const struct fastrpc_context *ctx)
{
return hexagonrpc(&adsp_default_listener3_register_def, ctx);
}
#endif /* INTERFACE_ADSP_DEFAULT_LISTENER_DEF */
+57
View File
@@ -0,0 +1,57 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef INTERFACE_ADSP_LISTENER_DEF
#define INTERFACE_ADSP_LISTENER_DEF
#include <libhexagonrpc/interface.h>
#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)
HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(3, adsp_listener3_init2)
static inline int adsp_listener3_init2(int fd)
{
return hexagonrpc2(&adsp_listener3_init2_def, fd, ADSP_LISTENER_HANDLE);
}
HEXAGONRPC_DEFINE_REMOTE_METHOD3(4, adsp_listener3_next2, true,
0, 0, 1, HEXAGONRPC_DELIMITER, 0, 0, 0, 0, 1)
static inline int adsp_listener3_next2(int fd,
uint32_t ret_rctx,
uint32_t ret_res,
uint32_t ret_outbufs_len, const void *ret_outbufs,
uint32_t *rctx,
uint32_t *handle,
uint32_t *sc,
uint32_t *inbufs_len,
uint32_t inbufs_size, void *inbufs)
{
return hexagonrpc2(&adsp_listener3_next2_def, fd, ADSP_LISTENER_HANDLE,
ret_rctx, ret_res, ret_outbufs_len, ret_outbufs,
rctx, handle, sc, inbufs_len, inbufs_size, inbufs);
}
#endif /* INTERFACE_ADSP_LISTENER_DEF */
Loaded 20 of 64 files, more files were not shown because too many files have changed in this diff. Show more