mirror of
https://github.com/linux-msm/hexagonrpc.git
synced 2026-10-07 15:29:50 -07:00
Compare commits
42
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5620db43a7 | ||
|
|
0e9e03b37b | ||
|
|
61bb51bbc9 | ||
|
|
ffbc4da830 | ||
|
|
2415d5f90d | ||
|
|
7aab0f2c42 | ||
|
|
b7eff23db1 | ||
|
|
716e1e27c7 | ||
|
|
54ba43fbc3 | ||
|
|
f6d8a0e686 | ||
|
|
9db873f24f | ||
|
|
3f46980dc9 | ||
|
|
30fa49eb20 | ||
|
|
b7ad1021a2 | ||
|
|
f23297f962 | ||
|
|
c4c469bd8a | ||
|
|
6840e1dcfa | ||
|
|
aaef8a1e28 | ||
|
|
63b1711021 | ||
|
|
39dd3aec6e | ||
|
|
892b9f549e | ||
|
|
b410c74a81 | ||
|
|
24c3eea173 | ||
|
|
8949140fa6 | ||
|
|
154bd2631c | ||
|
|
b4db2118cb | ||
|
|
ecd901bc48 | ||
|
|
a31ec9caf9 | ||
|
|
0156911ba4 | ||
|
|
c82b2da4eb | ||
|
|
cd314096a3 | ||
|
|
1162ccd84c | ||
|
|
a56406c928 | ||
|
|
4054893648 | ||
|
|
d6c458bd17 | ||
|
|
753ebda39b | ||
|
|
1dc590d638 | ||
|
|
f085f578e3 | ||
|
|
0b4c7bffaf | ||
|
|
00b5f80608 | ||
|
|
9ea9bed77b | ||
|
|
23585daf67 |
No files matched your search
@@ -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
|
||||
@@ -1,65 +1,158 @@
|
||||
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 (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. The watch command is only valid if
|
||||
the stream type is 1 or 2.
|
||||
### 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 a directory tree, starting at the location
|
||||
defined by the `-R` option, or in `/usr/share/qcom` by default:
|
||||
|
||||
HexagonRPCD file/dir Android file/dir
|
||||
acdb /vendor/etc/acdbdata
|
||||
dsp /vendor/dsp
|
||||
sensors/config /vendor/etc/sensors/config
|
||||
sensors/registry /mnt/vendor/persist/sensors/registry/registry
|
||||
sensors/sns_reg.conf /vendor/etc/sensors/sns_reg_config
|
||||
socinfo /sys/devices/soc0
|
||||
|
||||
These files and directories should be populated with files from your device's
|
||||
Android firmware.
|
||||
|
||||
If you can pass the `-R` option, the convention is to pass `-R
|
||||
/usr/share/qcom/SOC/VENDOR/DEVICE`, where SOC is the SoC name in lowercase,
|
||||
VENDOR is the capitalized name of the device vendor, and DEVICE is the device
|
||||
name (e.g. `-R /usr/share/qcom/sdm845/SHIFT/axolotl` or `-R
|
||||
/usr/share/qcom/sdm845/Thundercomm/db845c`).
|
||||
|
||||
# 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"
|
||||
File renamed without changes.
+124
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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,7 +0,0 @@
|
||||
project('fastrpc', 'c')
|
||||
|
||||
include = include_directories('include')
|
||||
|
||||
subdir('libhexagonrpc')
|
||||
|
||||
subdir('hexagonrpcd')
|
||||
File renamed without changes.
File renamed without changes.
@@ -172,12 +172,6 @@ static uint32_t apps_std_fopen_with_env(void *data,
|
||||
return AEE_EUNSUPPORTED;
|
||||
}
|
||||
|
||||
if (ctx->rootfd < 0) {
|
||||
fprintf(stderr, "Could not open virtual root directory: %s\n",
|
||||
strerror(-ctx->rootfd));
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
|
||||
if (!strcmp(inbufs[1].p, "ADSP_LIBRARY_PATH")) {
|
||||
dirfd = ctx->adsp_library_dirfd;
|
||||
} else if (!strcmp(inbufs[1].p, "ADSP_AVS_CFG_PATH")) {
|
||||
@@ -225,12 +219,6 @@ static uint32_t apps_std_opendir(void *data,
|
||||
if (((const char *) inbufs[1].p)[inbufs[1].s - 1] != 0)
|
||||
return AEE_EBADPARM;
|
||||
|
||||
if (ctx->rootfd < 0) {
|
||||
fprintf(stderr, "Could not open virtual root directory: %s\n",
|
||||
strerror(-ctx->rootfd));
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
|
||||
ret = hexagonfs_openat(ctx->fds, ctx->rootfd, ctx->rootfd, inbufs[1].p);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not open %s: %s\n",
|
||||
@@ -302,7 +290,6 @@ static uint32_t apps_std_stat(void *data,
|
||||
struct fastrpc_io_buffer *outbufs)
|
||||
{
|
||||
struct apps_std_ctx *ctx = data;
|
||||
char *pathname;
|
||||
struct {
|
||||
uint64_t tsz; // Unknown purpose
|
||||
uint64_t dev;
|
||||
@@ -318,31 +305,25 @@ static uint32_t apps_std_stat(void *data,
|
||||
int64_t ctime;
|
||||
int64_t ctimensec;
|
||||
} *first_out = outbufs[0].p;
|
||||
const char *pathname = inbufs[1].p;
|
||||
struct stat stats;
|
||||
int fd, ret;
|
||||
|
||||
pathname = malloc(inbufs[1].s + 1);
|
||||
memcpy(pathname, inbufs[1].p, inbufs[1].s);
|
||||
pathname[inbufs[1].s] = 0;
|
||||
|
||||
if (ctx->rootfd < 0) {
|
||||
fprintf(stderr, "Could not open virtual root directory: %s\n",
|
||||
strerror(-ctx->rootfd));
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
if (((const char *) inbufs[1].p)[inbufs[1].s - 1] != 0)
|
||||
return AEE_EBADPARM;
|
||||
|
||||
fd = hexagonfs_openat(ctx->fds, ctx->rootfd, ctx->rootfd, pathname);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Could not open %s: %s\n",
|
||||
pathname, strerror(-fd));
|
||||
goto err_free_pathname;
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
|
||||
ret = hexagonfs_fstat(ctx->fds, fd, &stats);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Could not stat %s: %s\n",
|
||||
pathname, strerror(-fd));
|
||||
goto err_free_pathname;
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
|
||||
hexagonfs_close(ctx->fds, fd);
|
||||
@@ -366,13 +347,7 @@ static uint32_t apps_std_stat(void *data,
|
||||
first_out->ctime = (int64_t) stats.st_ctim.tv_nsec;
|
||||
first_out->ctimensec = (int64_t) stats.st_ctim.tv_nsec;
|
||||
|
||||
free(pathname);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_pathname:
|
||||
free(pathname);
|
||||
return AEE_EFAILED;
|
||||
}
|
||||
|
||||
struct fastrpc_interface *fastrpc_apps_std_init(struct hexagonfs_dirent *root)
|
||||
@@ -386,28 +361,30 @@ struct fastrpc_interface *fastrpc_apps_std_init(struct hexagonfs_dirent *root)
|
||||
|
||||
ctx = calloc(1, sizeof(struct apps_std_ctx));
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
goto err_free_iface;
|
||||
|
||||
memcpy(iface, &apps_std_interface, sizeof(struct fastrpc_interface));
|
||||
|
||||
ctx->rootfd = hexagonfs_open_root(ctx->fds, root);
|
||||
if (ctx->rootfd < 0)
|
||||
goto err_free_ctx;
|
||||
|
||||
if (ctx->rootfd >= 0) {
|
||||
ctx->adsp_avs_cfg_dirfd = hexagonfs_openat(ctx->fds,
|
||||
ctx->rootfd,
|
||||
ctx->rootfd,
|
||||
"/vendor/etc/acdbdata/");
|
||||
ctx->adsp_library_dirfd = hexagonfs_openat(ctx->fds,
|
||||
ctx->rootfd,
|
||||
ctx->rootfd,
|
||||
"/usr/lib/qcom/adsp/");
|
||||
}
|
||||
ctx->adsp_avs_cfg_dirfd = hexagonfs_openat(ctx->fds,
|
||||
ctx->rootfd,
|
||||
ctx->rootfd,
|
||||
"/vendor/etc/acdbdata/");
|
||||
ctx->adsp_library_dirfd = hexagonfs_openat(ctx->fds,
|
||||
ctx->rootfd,
|
||||
ctx->rootfd,
|
||||
"/usr/lib/qcom/adsp/");
|
||||
|
||||
iface->data = ctx;
|
||||
|
||||
return iface;
|
||||
|
||||
err:
|
||||
err_free_ctx:
|
||||
free(ctx);
|
||||
err_free_iface:
|
||||
free(iface);
|
||||
|
||||
return NULL;
|
||||
File renamed without changes.
@@ -69,8 +69,11 @@ static struct hexagonfs_fd *pop_dir(struct hexagonfs_fd *dir,
|
||||
|
||||
if (dir != root && dir->up != NULL) {
|
||||
up = dir->up;
|
||||
dir->ops->close(dir->data);
|
||||
free(dir);
|
||||
|
||||
if (!dir->is_assigned) {
|
||||
dir->ops->close(dir->data);
|
||||
free(dir);
|
||||
}
|
||||
} else {
|
||||
up = dir;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -110,6 +110,7 @@ static int mapped_openat(struct hexagonfs_fd *dir,
|
||||
|
||||
ctx->dir = NULL;
|
||||
|
||||
fd->is_assigned = false;
|
||||
fd->up = dir;
|
||||
fd->ops = &hexagonfs_mapped_ops;
|
||||
fd->data = ctx;
|
||||
@@ -221,13 +222,13 @@ 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;
|
||||
|
||||
ret = mapped_from_dirent(dirent_data, dir, fd_data);
|
||||
if (ret)
|
||||
fd_data = NULL;
|
||||
*fd_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -30,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))
|
||||
@@ -45,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;
|
||||
}
|
||||
|
||||
@@ -56,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;
|
||||
|
||||
@@ -69,6 +78,7 @@ static int virt_dir_openat(struct hexagonfs_fd *dir,
|
||||
if (fd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
fd->is_assigned = false;
|
||||
fd->up = dir;
|
||||
fd->ops = ent->ops;
|
||||
|
||||
@@ -87,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)
|
||||
@@ -0,0 +1,64 @@
|
||||
'\" t
|
||||
.TH HEXAGONRPCD 1 "2024-09-28" "hexagonrpcd" "Server for FastRPC remote procedure calls from Qualcomm DSPs"
|
||||
.SH NAME
|
||||
hexagonrpcd - Server for FastRPC remote procedure calls from Qualcomm DSPs
|
||||
.SH SYNOPSIS
|
||||
\fBhexagonrpcd\fP [\fIoptions\&.\&.\&.\fP] -f \fIDEVICE
|
||||
.SH DESCRIPTION
|
||||
Server for FastRPC remote procedure calls from Qualcomm DSPs\&.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-d \fIDSP\fP
|
||||
DSP name (default: )
|
||||
.TP
|
||||
\fB\-f \fIDEVICE\fP
|
||||
FastRPC device node to attach to
|
||||
.TP
|
||||
\fB\-p \fIPROGRAM\fP
|
||||
Run client program with shared file descriptor
|
||||
.TP
|
||||
\fB\-R \fIDIR\fP
|
||||
Root directory of served files (default: /usr/share/qcom/)
|
||||
.TP
|
||||
\fB\-s\fP
|
||||
Attach to sensorspd
|
||||
.PP
|
||||
.SH NOTES
|
||||
|
||||
Hexagonrpcd serves files to the remote processor via a reverse tunnel interface
|
||||
to the remote processor. These files are by default searched for in:
|
||||
|
||||
These files are searched for in a directory tree, starting at the location
|
||||
defined by the -R option, or in /usr/share/qcom by default:
|
||||
|
||||
.TS
|
||||
l l
|
||||
---
|
||||
l l.
|
||||
HexagonRPCD file/dir Android file/dir
|
||||
acdb /vendor/etc/acdbdata
|
||||
dsp /vendor/dsp
|
||||
sensors/config /vendor/etc/sensors/config
|
||||
sensors/registry /mnt/vendor/persist/sensors/registry/registry
|
||||
sensors/sns_reg.conf /vendor/etc/sensors/sns_reg_config
|
||||
socinfo /sys/devices/soc0
|
||||
.TE
|
||||
|
||||
These files and directories should be populated with files from your device's
|
||||
Android firmware.
|
||||
|
||||
If you can pass the -R option, the convention is to pass -R
|
||||
/usr/share/qcom/SOC/VENDOR/DEVICE, where SOC is the SoC name in lowercase,
|
||||
VENDOR is the capitalized name of the device vendor, and DEVICE is the device
|
||||
name (e.g. -R /usr/share/qcom/sdm845/SHIFT/axolotl or -R
|
||||
/usr/share/qcom/sdm845/Thundercomm/db845c).
|
||||
|
||||
.SH AUTHORS
|
||||
hexagonrpcd was written by The HexagonRPC Contributors <https://github.com/linux-msm/hexagonrpc>
|
||||
.SH COPYRIGHT
|
||||
Copyright (C) 2024 The HexagonRPC Contributors <https://github.com/linux-msm/hexagonrpc>
|
||||
Copyright (C) 2023 The Sensor Shell Contributors <https://github.com/linux-msm/hexagonrpc>
|
||||
.PP
|
||||
Released under GPL-3+ license\&.
|
||||
|
||||
@@ -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"
|
||||
File renamed without changes.
Loaded 20 of 59 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user