90 Commits
Author SHA1 Message Date
Richard Acayan 23a69640bf tools: make json-c optional
This shouldn't be a requirement to compile anything else. Stop requiring
it for building anything, and assume the user just wants to compile the
main project.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-19 22:30:25 -04:00
Richard Acayan 18e2ca3178 CI: depend on libjson-c-dev
This is a dependency of the newly imported sscregistrygen.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-19 22:27:14 -04:00
Richard Acayan ffca60917c meson.build: bump to 0.4.0
No breaking changes

New features:
- man page for hexagonrpcd
- support for FASTRPC_IOCTL_INIT_CREATE with fastrpc_shell_X
- apps_mem interface (mostly allocating memory for now)
- logic for hexagonfs root directory
- sscregistrygen tool to generate sensor registry
- Github CI (successful compilation only)

Fixes:
- Disabled verbose logging by default
- Documented the paths relative to the root directory
- Made apps_std_stat relative to ADSP libs directory
- Fixed unsigned/signed comparison in reverse tunnel
- Declared minimum meson version for meson.options
- Added soversion to the library build

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-19 22:15:27 -04:00
Richard Acayan 6e1281dc8d tools: add sscregistrygen from sensh
From the sensor shell repository, sscregistrygen is a tool for
generating the sensor registry from the sensor config. It is useful when
the sensor registry is not included in device firmware. Add
sscregistrygen here since it is more directly used by hexagonrpc rather
than sensh.

Link: https://gitlab.com/flamingradian/sensh/-/blob/23b7681f3faad422fa5751886f901bf03775243d/tools/sscregistrygen.c
Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-19 22:13:32 -04:00
Jens Reidel 948c5d0d37 hexagonrpcd: Guess directory for hexagonfs from compatible
Signed-off-by: Jens Reidel <adrian@travitia.xyz>
Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-18 22:49:26 -04:00
Dmitry Baryshkov e52da43a63 apps_mem: specify int argument to fastrpc_apps_mem_init()
Without this building fails with:

../git/hexagonrpcd/rpcd.c: In function 'start_reverse_tunnel':
../git/hexagonrpcd/rpcd.c:275:21: error: too many arguments to function 'fastrpc_apps_mem_init'; expected 0, have 1
  275 |         ifaces[2] = fastrpc_apps_mem_init(fd);
      |                     ^~~~~~~~~~~~~~~~~~~~~ ~~
In file included from ../git/hexagonrpcd/rpcd.c:38:
../git/hexagonrpcd/apps_mem.h:27:27: note: declared here
   27 | struct fastrpc_interface *fastrpc_apps_mem_init();
      |                           ^~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-05-13 04:59:23 +03:00
Dmitry Baryshkov 6e5f7d9d54 CI: add simple workflow
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-05-12 13:32:42 +03:00
Dmitry Baryshkov 9a68ca3abf meson.build: declare minimum meson version
The project uses meson.options rather than meson_options.txt. Document
the minimum meson version that can be used to build the project.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-05-12 13:32:42 +03:00
Dmitry Baryshkov 146d0e1dab listener: fix Wsign-compare error
Fix warning / error reported by gcc:

../git/hexagonrpcd/listener.c:115:25: warning: comparison of integer expressions of different signedness: 'uint32_t' {aka 'unsigned int'} and 'int' [-Wsign-compare]
         if (inbufs[0].s != 4 * (def->in_nums
                         ^~

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-05-12 13:32:42 +03:00
Richard Acayan 2377fd46f0 hexagonrpcd: add apps_mem interface implementation
The apps_mem interface enables the FastRPC shell to load skel ELFs,
such as libhexagon_nn_skel.so.
2025-05-09 19:36:50 -04:00
Richard Acayan 372ca67d7a hexagonrpcd: interfaces: add apps_mem interface
The apps_mem interface is the interface that allows the DSP to map
memory and to allocate more memory. Add a method definition for it.
2025-05-09 19:36:50 -04:00
Richard Acayan 4b1ecd8505 hexagonrpcd: apps_std: perform stat relative to ADSP libs directory
When loading a new skel file, the DSP may access a testsig.so file. This
calls apps_std_fopen_with_env which is relative to a specified
directory, but also apps_std_stat. Since the same "testsig.so"
path is accessed relative to ADSP_LIBRARY_PATH and to the current
working directory, infer that the current working directory should be
ADSP_LIBRARY_PATH.
2025-05-09 19:36:50 -04:00
Richard Acayan 53e347f39d hexagonrpcd.1: add -c option 2025-05-09 19:36:50 -04:00
Richard Acayan 75150d4860 hexagonrpcd: add -c option to start with pd 2025-05-09 19:36:49 -04:00
Richard Acayan 5620db43a7 hexagonrpcd.1: document the paths relative to the root directory
The files shouldn't be installed right in /usr/share/qcom except for
testing. Rather, they should be installed in some device-specific
directory to make packaging easier on some distros. Document the paths
relative to the root directory for served files.
2024-11-05 21:41:35 -05:00
Richard Acayan 0e9e03b37b README: document the paths relative to the root directory
The absolute paths shouldn't be installed right in /usr/share/qcom
except for testing. Document the modifiable directory where served files
are retrieved from and the convention of where this directory should be
located.

Link: https://gitlab.com/flamingradian/sensh/-/issues/1
2024-11-05 21:41:26 -05:00
Alexandre Viard 61bb51bbc9 Use Major.Minor for the lib soversion derived from project version
[richard: rebase and squash; remove leading whitespace in commit message]
2024-11-01 19:15:29 -04:00
Alexandre Viard ffbc4da830 Add man page for hexagonrpcd
[richard: remove trailing whitespace under -s; squash]
2024-10-21 19:06:54 -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
Richard Acayan b4db2118cb fastrpc: add iobuffer unit test
Despite the modularity of the FastRPC implementation, there are no unit
tests. This makes it unpredictable when the implementation encounters an
unlikely scenario, such as when reading uninitialized memory that is
non-zero, or when allocating zero bytes of memory. Add a unit test for
the I/O buffer encoder and decoder so there can be more confidence in
its expected operation.

This does not test edge cases in the malloc() function, such as
allocating zero bytes or failures.
2023-12-27 18:23:41 -05:00
Richard Acayan ecd901bc48 fastrpc: hexagonrpcd: hexagonfs: only close popped dir if not assigned
When a pathname navigates to the parent directory via the special "../"
name, the current directory may be assigned a numeric file descriptor.
With a numeric file descriptor, the current directory can still be
referenced, and should not be closed. Only close the directory if it is
not assigned.
2023-12-26 19:47:25 -05:00
Richard Acayan a31ec9caf9 fastrpc: hexagonrpcd: apps_std: do not initialize without root dir
The file descriptor for the root directory is required for file
operations. Without the root directory open, opening or getting stats of
a file always fails. Currently, the apps_std methods check if the root
directory is open every time they are called. Fail to initialize if the
root directory cannot be opened to allow the simplification of remote
methods accepting a path name.
2023-12-26 19:47:04 -05:00
Richard Acayan 0156911ba4 fastrpc: hexagonrpcd: apps_std: do not copy path name in stat()
The path name is already NULL-terminated by the caller and does not need
to be copied to a larger buffer to add more NULL termination. Allocating
an extra buffer can cause an unnecessary crash or failure when out of
memory. Do not copy the path name. Instead, check that the path name is
NULL-terminated by the caller.
2023-12-26 19:39:09 -05:00
Richard Acayan c82b2da4eb fastrpc: hexagonrpcd: listener: remove fastrpc_listener_interfaces
This is a variable which was superseded by dynamically initialized
interfaces. Remove it.
2023-12-18 20:07:17 -05:00
Richard Acayan cd314096a3 README: remove statement that watch command is invalid for stream type 0
Normally, the CHRE performs a full configuration on streaming sensors
with a stream type of zero. This made it seem like a simple enable would
not properly activate sensors with this stream type, but it is possible
to use the watch command on streaming sensors. Remove this statement
which may be misleading.
2023-12-18 19:48:40 -05:00
Richard Acayan 1162ccd84c fastrpc: hexagonrpcd: listener: propagate decoding error
The decoding error was added in the previous commit with the -1 return
value. Propagate it as a fatal error (-1).

Also remove a newline in an existing perror statement, where the error
message would be split between lines.
2023-12-12 19:10:25 -05:00
Richard Acayan a56406c928 fastrpc: hexagonrpcd: iobuffer: propagate decoding allocation failure
The decoder dynamically allocates memory while decoding so the decoded
buffers have the correct size. This can fail, often when the memory runs
out. Propagate any errors from malloc() and do not attempt to decode the
buffer.
2023-12-12 19:08:12 -05:00
Richard Acayan 4054893648 fastrpc: hexagonrpcd: iobuffer: change types in decoder context
There is no real reason for the position attributes to be signed. It
does not make sense to have a negative offset in the current input
buffer, negative alignment, or negative offset in the size of the
current input buffer. A negative number of input buffers also makes no
sense. Reorganize the decoder context struct and the I/O buffer struct
so offsets and maximums are together, nothing has the unnecessary
capability of being negative, and the sizes are not wider than possible
in the format.

Also include the definition for uint32_t.

Also update the error message format in listener.c to read a 32-bit
integer.
2023-12-11 21:24:54 -05:00
Richard Acayan d6c458bd17 fastrpc: hexagonrpcd: iobuffer: only align at beginning of inbuf
When the decoding continues from a misaligned part of the buffer, the
decoder attempts to skip some of the buffer to realign itself, even if
it is not the beginning of the buffer. To allow the decoding of an input
with a size indivisible by 8, only consume the alignment at the
beginning of an input buffer.

The bug outlined here does not happen in practice because the size of
the encoded input is hardcoded to 256 in listener.c.

Fixes: 77f855ec84 ("fastrpc: decode input buffers")
2023-12-11 21:24:46 -05:00
Richard Acayan 753ebda39b fastrpc: hexagonrpcd: iobuffer: allow null pointer for zero inbufs
According to malloc(3p), a call to malloc with a size of zero can result
in a NULL pointer. If this occurs, the initialized decoding context is
still valid and the program may proceed without failing. Allow a NULL
pointer when there are zero input buffers to be processed.

Fixes: 77f855ec84 ("fastrpc: decode input buffers")
2023-12-11 21:24:01 -05:00
Richard Acayan 1dc590d638 fastrpc: hexagonrpcd: listener: compute out_count before zero check
The amount of output buffers needed should be computed before the check,
otherwise it checks an uninitialized value. Initialize it first so that
the zero check works as intended.

Fixes: 9ea9bed77b ("fastrpc: hexagonrpcd: listener: do not attempt to allocate zero outbufs")
2023-12-07 19:55:18 -05:00
Richard Acayan f085f578e3 fastrpc: hexagonrpcd: do not close un-opened file
The device node has not been opened yet at this point. Directly return
without closing it.
2023-12-04 21:57:51 -05:00
Richard Acayan 0b4c7bffaf fastrpc: hexagonrpcd: hexagonfs: mapped: return NULL for empty dirs
The mapped_or_empty file implementation uses NULL to denote when an
empty directory should be in place of a non-existent file. Changing the
pointer to the output has no effect. Change the implementation data to a
NULL pointer so empty directories function properly.
2023-12-04 19:50:34 -05:00
Richard Acayan 00b5f80608 fastrpc: hexagonrpcd: hexagonfs: initialize is_assigned in from_dirent
The is_assigned attribute should only be true when it is assigned a
numeric ID, otherwise it will not be closed. The from_dirent operations
in the implementations of a file type do not use the calloc() function,
so the is_assigned attribute is uninitialized. Initialize it to zero so
the open file can be closed when requested.
2023-12-04 19:50:24 -05:00
Richard Acayan 9ea9bed77b fastrpc: hexagonrpcd: listener: do not attempt to allocate zero outbufs
The malloc(3p) manual page states that an implementation may choose to
return a non-NULL pointer when the size is zero. This function assumes
that there is an element in the array if the pointer is not NULL. When
the size is zero, skip the allocation and return NULL.
2023-12-04 19:50:11 -05:00
Richard Acayan 23585daf67 qmi: add generated substitute
The qmic utility is rarely packaged in mainstream distributions, making
it inconvenient to set up a working build environment. Add generated
source files to enable compilation without qmic installed.
2023-12-04 19:49:59 -05:00
Richard Acayan e0d6c2a7ac fastrpc: hexagonrpcd: hexagonfs: remove static root filesystem
The root filesystem is now dynamically constructed in rpcd_builder.c.
Remove this macro-generated filesystem as it is unused and generates a
warning.
2023-11-27 18:53:31 -05:00
Richard Acayan 329f1ae841 fastrpc: hexagonrpcd: apps_std: remove unused variables
These variables went unused since the input buffer lengths were switched
to the sizes parsed by iobuffer.c, instead of the sizes in the primary
input argument. This makes it unnecessary at times to unpack the primary
input buffer, although the variables were being kept around to document
calling conventions. Remove the variables since they add unnecessary
warnings.

The calling conventions can still be found in the Android implementation
of FastRPC.
2023-11-27 18:53:31 -05:00
Richard Acayan 2358946095 fastrpc: hexagonrpcd: apps_std: include correct headers
This interface implementation no longer opens files directly, but sends
requests to hexagonfs. Hence, fcntl.h and dirent.h are no longer needed.
Also, it uses 32-bit integers from stdint.h.
2023-11-27 18:53:31 -05:00
Richard Acayan 06ef0b17a4 fastrpc: README: remove note about source code directory structure
This has been completed a long time ago.
2023-11-27 18:53:31 -05:00
Richard Acayan d87d8ffc47 fastrpc: README: mention correct interface listings
The interfaces being created on the reverse tunnel are now dynamically
generated.
2023-11-27 18:53:31 -05:00
Richard Acayan 947f52d779 fastrpc: README: clarify REMOTE_SCALARS_MAKE
This macro is used to generate the 32-bit remote "scalars"/"sc"
argument. Correct the name and link to the definition.
2023-11-27 18:53:31 -05:00
Richard Acayan 4983830139 fastrpc: README: add more usage documentation
The data types for the ioctl wrapper are important, as it has variable
arguments. Document them.

Also mention terminology used in QAIC output to aid in understanding
this project in relation to existing FastRPC implementations.
2023-11-27 18:53:31 -05:00
Richard Acayan 5e04177155 fastrpc: README: document meson build system
The meson.build was added a while ago.
2023-11-27 18:52:44 -05:00
Richard Acayan ee439dd6cb fastrpc: change copyright line
There are multiple contributors already, and copyright assignment is not
an intended requirement for contributing.
2023-11-27 18:52:18 -05:00
Richard Acayan b686df88d7 fastrpc: hexagonrpcd: builder: default required directories to empty
The sensor configuration is not required and is normally used just to
generate the sensor registry, but the sensors do not appear unless the
directory is present. The ADSP_LIBRARY_PATH virtual environment variable
may be used when opening absolute paths as a firmware quirk, even if
nothing is read from it. To remove the requirement of empty directories
in the physical filesystem, use the new hexagonfs_mapped_or_empty_ops.
2023-11-27 18:28:06 -05:00
Richard Acayan ccaa9728d9 fastrpc: hexagonrpcd: hexagonfs: add optionally mapped directories
Some directories are not required for the normal operation of the sensor
firmware, such as the sensor configuration directory. Add support for
directories that are empty if they are not present in the physical
filesystem.
2023-11-27 17:21:03 -05:00
Richard Acayan f5e05d0e7d fastrpc: README: correct the sensors registry path
The sensors registry path is in /persist/sensors/registry/registry and
not /persist/sensors/registry. Correct this in the README.
2023-08-01 19:09:04 -04:00
Richard Acayan b6d1f60ae9 fastrpc: hexagonrpcd: document added options in help text
The -R option specifies the root of the files served to the remote
processor (before mapping them to the virtual filesystem). The -d option
specifies the DSP variant, used to select the subdirectory storing the
libraries for the remote processor.
2023-07-27 21:04:15 -04:00
Richard Acayan ac6b6d61d0 fastrpc: hexagonrpcd: print most help text at once
There are multiple printf statements for each line of the help text.
Each line can be concatenated to one string at compile-time without
impacting readability of the intended output, with the exception of the
first line, with special formatting. Join the rest of the help text into
one printf statement.
2023-07-27 21:00:45 -04:00
Richard Acayan 44d4a818aa fastrpc: README: document new paths 2023-07-27 21:00:37 -04:00
Richard Acayan 2b8875d185 fastrpc: hexagonrpcd: accept path information from command line
Accept the path to files for the remote processor and the subdirectory
with the DSP shared object files on the command line.
2023-07-25 19:05:33 -04:00
Richard Acayan 4fb42aaa79 fastrpc: hexagonrpcd: specify device root path as absolute
The directory that stores the files for the remote processor is
specified relative to /usr/share/qcom. This is arbitrary and confuses
the user into thinking that the path is relative to the current working
directory. Specify it as absolute.
2023-07-25 19:05:28 -04:00
Richard Acayan d791bb48a0 fastrpc: hexagonrpcd: rework virtual filesystem sources
The virtual filesystem maps to physical files and directories. Move the
location of these physical files and directories according to #1.
2023-07-05 21:59:58 -04:00
Richard Acayan 9d97f21f4a fastrpc: hexagonrpcd: localctl: use inbuf size instead of provided len
The output of the adsp_listener interface provides the size of each
buffer in addition to the length provided to the remote method in the
primary buffer. Use the size of the buffer, which always corresponds to
the size allocated to it, regardless of whether there are consistency
checks.
2023-07-03 19:34:21 -04:00
Richard Acayan 1874e7a109 fastrpc: hexagonrpcd: apps_std: use inbuf size instead of provided len
The output of the adsp_listener interface provides the size of each
buffer in addition to the length provided to the remote method in the
primary buffer. Use the size of the buffer, which always corresponds to
the size allocated to it, regardless of whether there are consistency
checks.
2023-07-03 19:30:08 -04:00
Richard Acayan aa1cfca7b4 fastrpc: hexagonrpcd: apps_std: make fseek primary input buffer constant
The input buffers are not modified by the implementation of this remote
method. Make the primary input buffer constant.
2023-06-30 21:42:40 -04:00
Richard Acayan 4e2d1d46c6 fastrpc: hexagonrpcd: apps_std: make seek table constant
This is a read-only lookup table and is not modified during runtime.
Make it constant.

Also remove excessive empty lines.
2023-06-30 21:42:40 -04:00
Richard Acayan 3becf15c7a fastrpc: hexagonrpcd: apps_std: move fread method primary parameters
The only named structs for parameters in the primary input and output
buffers are for the fread remote method. Move them to the the place
where they are used, consistent with the other remote method
implementations.
2023-06-30 21:42:40 -04:00
Richard Acayan 3bf791122f fastrpc: hexagonrpcd: hexagonfs: do not store file descriptor array
The file descriptor array maps file descriptors to their corresponding
file descriptions, and is in static storage. Since there is range
checking for file descriptors, there is still a benefit to having access
to the file descriptor array. Accept the array as a parameter.

In the future, this parameter can be removed in secondary functions if
needed.
2023-06-30 21:42:40 -04:00
Richard Acayan ea226ef7b9 fastrpc: hexagonrpcd: apps_std: open directories on initialization
The apps_std interface stores file descriptors in static variables,
opening them when needed, and configures HexagonFS with a hardcoded root
directory. Configure HexagonFS and open the file descriptors in
initialization instead.
2023-06-30 21:42:40 -04:00
Richard Acayan 77ff6338be fastrpc: hexagonrpcd: hexagonfs: receive root directory argument
The root directory should not be hardcoded by hexagonfs, but the user of
it. Receive the root directory entry as an argument to the function that
opens the root directory.
2023-06-30 21:42:40 -04:00
Richard Acayan 1e83c7316e fastrpc: hexagonrpcd: localctl: use interface list from context
Now that the context is being initialized, use the interface list stored
in it.
2023-06-30 21:42:40 -04:00
Richard Acayan 3af581489d fastprc: hexagonrpcd: dynamically initialize interfaces
Some interfaces need to be configured before they can function.
Dynamically initialize the interfaces so there can be code to configure
them.
2023-06-30 21:42:40 -04:00
Richard Acayan 36bff0f541 fastrpc: hexagonrpcd: localctl: add context initialization
This interface depends on static variables to function properly. Add
code to initialize a context with the required data.

Do not use the context yet because it is not always initialized.
2023-06-30 21:42:40 -04:00
Richard Acayan 0ed58012fa fastrpc: hexagonrpcd: listener: move interfaces to listener user
The reverse tunnel finds interfaces in a static variable. As a
consequence, the interfaces cannot be customized by the user of the
reverse tunnel. Move the interfaces to the user of the listener.
2023-06-30 21:42:40 -04:00
Richard Acayan cd8a751732 fastrpc: hexagonrpcd: listener: declare procedure array as pointer
As an variable-length array within a struct, the procedure array is not
included in the sizeof() macro and cannot be trivially copied. Declare
it as a pointer to an array of procedures so the local fastrpc interface
definitions have a predictable size.
2023-06-30 21:42:40 -04:00
Richard Acayan 9946564fe9 fastrpc: hexagonrpcd: add interface contexts
Some interfaces preserve their states between invocations in static
storage. This is not ideal, as interfaces cannot be initialized with
information from the user of the reverse tunnel. Add support for
interface-defined contexts.
2023-06-30 21:42:40 -04:00
Richard Acayan 4a5f23e5d9 fastrpc: hexgaonrpcd: hexagonfs: remove offset property
This property should only be defined for file operations that need it.
Remove it from the common hexagonfs_fd struct and expect each file
operations to add it in the data pointer if necessary.
2023-06-05 18:07:46 -04:00
Richard Acayan 7dfd7d778c fastrpc: hexagonrpcd: hexagonfs: mapped: set functions to static
These functions are only referenced in the same compilation unit to
define file operations. Set these functions to static so they don't get
exported directly for no reason.
2023-06-05 18:07:40 -04:00
62 changed files with 2360 additions and 1849 deletions

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
name: Buildtest
on:
pull_request:
push:
jobs:
build-linux:
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
# 22.04 has old meson
# - runner: ubuntu-22.04
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependencies
run: |
sudo apt update
sudo apt install -y meson ninja-build libjson-c-dev
- name: build
run: |
meson setup build
ninja -C build
-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
+142 -49
View File
@@ -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"
@@ -1,7 +1,7 @@
/*
* Context Hub Runtime Environment interface
*
* Copyright (C) 2023 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
+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,
)
-143
View File
@@ -1,143 +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
There is currently no build system.
$ gcc -o libhexagonrpc.so -shared fastrpc.c context.c
## 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.
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 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_METHOD_MAKE()` macro or the second argument of the
`REMOTE_METHOD_MAKEX()` macro.
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 listed in the `fastrpc_listener_interfaces` variable.
## 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
/etc/qcom/sns_reg.conf /vendor/etc/sensors/sns_reg_config
/etc/qcom/sensors.d /vendor/etc/sensors/config
/var/lib/qcom/sensors /mnt/vendor/persist/sensors/registry
/usr/lib/qcom/adsp /vendor/dsp/adsp
/usr/lib/qcom/adsp/avs /vendor/etc/acdbdata
These files and directories should be populated with files from your device's
Android firmware.
# Future plans
This directory is a bit messy. It should be organized into different
subdirectories and have a build system. This should also be renamed to
HexagonRPC to avoid a name collision.
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.
-236
View File
@@ -1,236 +0,0 @@
/*
* FastRPC Example
*
* Copyright (C) 2023 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/>.
*/
#include <errno.h>
#include <fcntl.h>
#include <libhexagonrpc/fastrpc.h>
#include <misc/fastrpc.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include "aee_error.h"
#include "interfaces/adsp_default_listener.def"
#include "interfaces/chre_slpi.def"
#include "interfaces/remotectl.def"
#include "listener.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 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);
}
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;
int ret;
ret = remotectl_open(fd, "adsp_default_listener", &ctx, remotectl_err);
if (ret)
return 1;
ret = adsp_default_listener_register(ctx);
if (ret) {
fprintf(stderr, "Could not register ADSP default listener\n");
goto err;
}
err:
remotectl_close(ctx, remotectl_err);
return ret;
}
static void *start_reverse_tunnel(void *data)
{
int *fd = data;
int ret;
ret = register_fastrpc_listener(*fd);
if (ret)
return NULL;
run_fastrpc_listener(*fd);
return NULL;
}
static void *start_chre_client(void *data)
{
struct fastrpc_context *ctx;
int *fd = data;
int ret;
ret = remotectl_open(*fd, "chre_slpi", &ctx, remotectl_err);
if (ret)
return NULL;
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);
return NULL;
}
int main(int argc, char* argv[])
{
pthread_t chre_thread, listener_thread;
char *fastrpc_node = NULL;
int fd, ret, opt;
bool attach_sns = false;
while ((opt = getopt(argc, argv, "sf:")) != -1) {
switch (opt) {
case 'f':
fastrpc_node = optarg;
break;
case 's':
attach_sns = true;
break;
default:
printf("Usage: %s [-s] [-f FastRPC node]\n\n", argv[0]);
printf("Qualcomm Hexagon filesystem daemon\n\n");
printf("\t-f\tFastRPC node to attach to\n");
printf("\t-s\tUse INIT_ATTACH_SNS instead of INIT_ATTACH ioctl\n");
return 1;
}
}
if (!fastrpc_node) {
fprintf(stderr, "Invalid FastRPC node: %s\n", fastrpc_node);
return 2;
}
printf("Starting %s (%s) on %s\n", argv[0], attach_sns? "INIT_ATTACH_SNS": "INIT_ATTACH", fastrpc_node);
fd = open(fastrpc_node, O_RDWR);
if (fd < 0) {
fprintf(stderr, "Could not open FastRPC node (%s): %s\n", fastrpc_node, strerror(errno));
return 3;
}
if (attach_sns)
ret = ioctl(fd, FASTRPC_IOCTL_INIT_ATTACH_SNS, NULL);
else
ret = ioctl(fd, FASTRPC_IOCTL_INIT_ATTACH, NULL);
if (ret) {
fprintf(stderr, "Could not attach to FastRPC node: %s\n", strerror(errno));
goto err_close_dev;
}
pthread_create(&listener_thread, NULL, start_reverse_tunnel, &fd);
pthread_create(&chre_thread, NULL, start_chre_client, &fd);
pthread_join(listener_thread, NULL);
pthread_join(chre_thread, NULL);
close(fd);
return 0;
err_close_dev:
close(fd);
return 4;
}
-7
View File
@@ -1,7 +0,0 @@
project('fastrpc', 'c')
include = include_directories('include')
subdir('libhexagonrpc')
subdir('hexagonrpcd')
File renamed without changes.
File renamed without changes.
+143
View File
@@ -0,0 +1,143 @@
/*
* FastRPC memory mapping interface implementation
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <misc/fastrpc.h>
#include <sys/ioctl.h>
#include "aee_error.h"
#include "apps_mem.h"
#include "interfaces/apps_mem.def"
#include "listener.h"
// See fastrpc.git/src/apps_mem_imp.c
#define ADSP_MMAP_HEAP_ADDR 4
#define ADSP_MMAP_REMOTE_HEAP_ADDR 8
#define ADSP_MMAP_ADD_PAGES 0x1000
struct apps_mem_ctx {
int fd;
};
static uint32_t apps_mem_request_map64(void *data,
const struct fastrpc_io_buffer *inbufs,
struct fastrpc_io_buffer *outbufs)
{
struct apps_mem_ctx *ctx = data;
const struct {
uint32_t heap_id;
uint32_t lflags;
uint32_t rflags;
uint32_t padding;
uint64_t vin;
uint64_t len;
} *first_in = inbufs[0].p;
struct {
uint64_t vapps;
uint64_t vadsp;
} *first_out = outbufs[0].p;
struct fastrpc_req_mmap mmap;
int ret;
if (!(first_in->rflags & ADSP_MMAP_ADD_PAGES)) {
fprintf(stderr, "Unsupported mmap operation: DMA buffer request\n");
return AEE_EUNSUPPORTED;
}
mmap.fd = -1;
mmap.flags = first_in->rflags;
mmap.vaddrin = 0;
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]);
return ret;
}
#if HEXAGONRPC_VERBOSE
printf("mmap(%d, %x, %x, %lu, %lu) -> %" PRIx64 "\n",
first_in->heap_id,
first_in->lflags,
first_in->rflags,
first_in->vin,
first_in->len,
mmap.vaddrout);
#endif
first_out->vapps = 0;
first_out->vadsp = mmap.vaddrout & 0xFFFFFFFF;
return 0;
}
struct fastrpc_interface *fastrpc_apps_mem_init(int fd)
{
struct fastrpc_interface *iface;
struct apps_mem_ctx *ctx;
iface = malloc(sizeof(*iface));
if (iface == NULL)
return NULL;
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL)
goto err_free_iface;
memcpy(iface, &apps_mem_interface, sizeof(*iface));
ctx->fd = fd;
iface->data = ctx;
return iface;
err_free_iface:
free(iface);
return NULL;
}
void fastrpc_apps_mem_deinit(struct fastrpc_interface *iface)
{
free(iface->data);
free(iface);
}
static const struct fastrpc_function_impl apps_mem_procs[] = {
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{ .def = &apps_mem_request_map64_def, .impl = apps_mem_request_map64, },
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
{ .def = NULL, .impl = NULL, },
};
const struct fastrpc_interface apps_mem_interface = {
.name = "apps_mem",
.n_procs = 6,
.procs = apps_mem_procs,
};
+30
View File
@@ -0,0 +1,30 @@
/*
* FastRPC operating system interface - context initialization
*
* Copyright (C) 2024 The Sensor Shell 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 <https://www.gnu.org/licenses/>.
*/
#ifndef APPS_MEM_H
#define APPS_MEM_H
#include "listener.h"
struct fastrpc_interface *fastrpc_apps_mem_init(int fd);
void fastrpc_apps_mem_deinit(struct fastrpc_interface *iface);
#endif
File diff suppressed because it is too large. Load diff
@@ -1,7 +1,7 @@
/*
* Protocol Buffer for Sensor Attribute Requests
* FastRPC operating system interface - context initialization
*
* Copyright (C) 2022 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -19,8 +19,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
syntax = "proto2";
#ifndef APPS_STD_H
#define APPS_STD_H
message sns_std_attr_req {
required int32 unkfield_4 = 2;
}
#include "hexagonfs.h"
#include "listener.h"
struct fastrpc_interface *fastrpc_apps_std_init(struct hexagonfs_dirent *root);
void fastrpc_apps_std_deinit(struct fastrpc_interface *iface);
#endif
@@ -1,7 +1,7 @@
/*
* Virtual read-only filesystem for Hexagon processors
*
* Copyright (C) 2023 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -29,111 +29,6 @@
#include "hexagonfs.h"
#define HEXAGONFS_MAX_FD 256
#define DEFINE_VIRT_DIR(dirname, files...) \
(struct hexagonfs_dirent) { \
.name = dirname, \
.ops = &hexagonfs_virt_dir_ops, \
.u.dir = (struct hexagonfs_dirent *[]) { files }, \
}
#define DEFINE_MAPPED(dirname, path) \
(struct hexagonfs_dirent) { \
.name = dirname, \
.ops = &hexagonfs_mapped_ops, \
.u.phys = path, \
}
#define DEFINE_SYSFILE(dirname, path) \
(struct hexagonfs_dirent) { \
.name = dirname, \
.ops = &hexagonfs_mapped_sysfs_ops, \
.u.phys = path, \
}
static struct hexagonfs_dirent root_dir = DEFINE_VIRT_DIR("/",
&DEFINE_VIRT_DIR("mnt",
&DEFINE_VIRT_DIR("vendor",
&DEFINE_VIRT_DIR("persist",
&DEFINE_VIRT_DIR("sensors",
&DEFINE_VIRT_DIR("registry",
&DEFINE_MAPPED("registry",
"/var/lib/qcom/sensors"),
NULL,
),
NULL,
),
NULL,
),
NULL,
),
NULL,
),
&DEFINE_VIRT_DIR("persist",
&DEFINE_VIRT_DIR("sensors",
&DEFINE_VIRT_DIR("registry",
&DEFINE_MAPPED("registry",
"/var/lib/qcom/sensors"),
NULL,
),
NULL,
),
NULL,
),
&DEFINE_VIRT_DIR("sys",
&DEFINE_VIRT_DIR("devices",
&DEFINE_VIRT_DIR("soc0",
&DEFINE_SYSFILE("hw_platform",
"/sys/kernel/debug/qcom_socinfo/hardware_platform"),
&(struct hexagonfs_dirent) {
.name = "platform_subtype",
.ops = &hexagonfs_plat_subtype_name_ops,
.u.phys = "/sys/kernel/debug/qcom_socinfo/hardware_platform_subtype",
},
&DEFINE_SYSFILE("platform_subtype_id",
"/sys/kernel/debug/qcom_socinfo/hardware_platform_subtype"),
&DEFINE_SYSFILE("platform_version",
"/sys/kernel/debug/qcom_socinfo/platform_version"),
&DEFINE_SYSFILE("revision",
"/sys/devices/soc0/revision"),
&DEFINE_SYSFILE("soc_id",
"/sys/devices/soc0/soc_id"),
NULL,
),
NULL,
),
NULL,
),
&DEFINE_VIRT_DIR("usr",
&DEFINE_VIRT_DIR("lib",
&DEFINE_VIRT_DIR("qcom",
&DEFINE_MAPPED("adsp",
"/usr/lib/qcom/adsp/"),
NULL,
),
NULL,
),
NULL,
),
&DEFINE_VIRT_DIR("vendor",
&DEFINE_VIRT_DIR("etc",
&DEFINE_VIRT_DIR("sensors",
&DEFINE_MAPPED("config",
"/etc/qcom/sensors.d/"),
&DEFINE_MAPPED("sns_reg_config",
"/etc/qcom/sns_reg.conf"),
NULL,
),
NULL,
),
NULL,
),
NULL,
);
static struct hexagonfs_fd *fds[HEXAGONFS_MAX_FD];
static char *copy_segment_and_advance(const char *path,
bool *trailing_slash,
const char **next)
@@ -174,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;
}
@@ -183,7 +81,8 @@ static struct hexagonfs_fd *pop_dir(struct hexagonfs_fd *dir,
return up;
}
static int allocate_file_number(struct hexagonfs_fd *fd)
static int allocate_file_number(struct hexagonfs_fd **fds,
struct hexagonfs_fd *fd)
{
size_t i;
@@ -212,7 +111,7 @@ static void destroy_file_descriptor(struct hexagonfs_fd *fd)
}
}
int hexagonfs_open_root()
int hexagonfs_open_root(struct hexagonfs_fd **fds, struct hexagonfs_dirent *root)
{
struct hexagonfs_fd *fd;
int ret;
@@ -221,16 +120,15 @@ int hexagonfs_open_root()
if (fd == NULL)
return -ENOMEM;
fd->off = 0;
fd->is_assigned = false;
fd->up = NULL;
fd->ops = root_dir.ops;
fd->ops = root->ops;
ret = root_dir.ops->from_dirent(root_dir.u.ptr, true, &fd->data);
ret = root->ops->from_dirent(root->u.ptr, true, &fd->data);
if (ret)
goto err;
ret = allocate_file_number(fd);
ret = allocate_file_number(fds, fd);
if (ret < 0)
goto err;
@@ -241,7 +139,7 @@ err:
return ret;
}
int hexagonfs_openat(int rootfd, int dirfd, const char *name)
int hexagonfs_openat(struct hexagonfs_fd **fds, int rootfd, int dirfd, const char *name)
{
struct hexagonfs_fd *fd;
const char *curr = name;
@@ -281,7 +179,7 @@ int hexagonfs_openat(int rootfd, int dirfd, const char *name)
if (ret)
goto err;
ret = allocate_file_number(fd);
ret = allocate_file_number(fds, fd);
if (ret)
goto err;
@@ -293,7 +191,7 @@ err:
return ret;
}
int hexagonfs_close(int fileno)
int hexagonfs_close(struct hexagonfs_fd **fds, int fileno)
{
struct hexagonfs_fd *fd;
@@ -312,7 +210,7 @@ int hexagonfs_close(int fileno)
return 0;
}
int hexagonfs_lseek(int fileno, off_t off, int whence)
int hexagonfs_lseek(struct hexagonfs_fd **fds, int fileno, off_t off, int whence)
{
struct hexagonfs_fd *fd;
@@ -329,7 +227,7 @@ int hexagonfs_lseek(int fileno, off_t off, int whence)
return fd->ops->seek(fd, off, whence);
}
ssize_t hexagonfs_read(int fileno, size_t size, void *ptr)
ssize_t hexagonfs_read(struct hexagonfs_fd **fds, int fileno, size_t size, void *ptr)
{
struct hexagonfs_fd *fd;
@@ -346,7 +244,7 @@ ssize_t hexagonfs_read(int fileno, size_t size, void *ptr)
return fd->ops->read(fd, size, ptr);
}
int hexagonfs_readdir(int fileno, size_t ent_size, char *ent)
int hexagonfs_readdir(struct hexagonfs_fd **fds, int fileno, size_t ent_size, char *ent)
{
struct hexagonfs_fd *fd;
@@ -363,7 +261,7 @@ int hexagonfs_readdir(int fileno, size_t ent_size, char *ent)
return fd->ops->readdir(fd, ent_size, ent);
}
int hexagonfs_fstat(int fileno, struct stat *stats)
int hexagonfs_fstat(struct hexagonfs_fd **fds, int fileno, struct stat *stats)
{
struct hexagonfs_fd *fd;
@@ -1,7 +1,7 @@
/*
* Virtual read-only filesystem for Hexagon processors
*
* Copyright (C) 2023 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -27,11 +27,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#define HEXAGONFS_MAX_FD 256
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,
@@ -54,7 +56,6 @@ struct hexagonfs_dirent {
};
struct hexagonfs_fd {
off_t off;
bool is_assigned;
struct hexagonfs_fd *up;
void *data;
@@ -63,17 +64,18 @@ struct hexagonfs_fd {
};
extern struct hexagonfs_file_ops hexagonfs_mapped_ops;
extern struct hexagonfs_file_ops hexagonfs_mapped_or_empty_ops;
extern struct hexagonfs_file_ops hexagonfs_mapped_sysfs_ops;
extern struct hexagonfs_file_ops hexagonfs_plat_subtype_name_ops;
extern struct hexagonfs_file_ops hexagonfs_virt_dir_ops;
int hexagonfs_open_root();
int hexagonfs_openat(int rootfd, int dirfd, const char *name);
int hexagonfs_close(int fileno);
int hexagonfs_open_root(struct hexagonfs_fd **fds, struct hexagonfs_dirent *root);
int hexagonfs_openat(struct hexagonfs_fd **fds, int rootfd, int dirfd, const char *name);
int hexagonfs_close(struct hexagonfs_fd **fds, int fileno);
int hexagonfs_fstat(int fileno, struct stat *stats);
int hexagonfs_lseek(int fileno, off_t pos, int whence);
int hexagonfs_readdir(int fileno, size_t size, char *name);
ssize_t hexagonfs_read(int fileno, size_t size, void *ptr);
int hexagonfs_fstat(struct hexagonfs_fd **fds, int fileno, struct stat *stats);
int hexagonfs_lseek(struct hexagonfs_fd **fds, int fileno, off_t pos, int whence);
int hexagonfs_readdir(struct hexagonfs_fd **fds, int fileno, size_t size, char *name);
ssize_t hexagonfs_read(struct hexagonfs_fd **fds, int fileno, size_t size, void *ptr);
#endif
@@ -1,7 +1,7 @@
/*
* HexagonFS mapped file/directory operations
*
* Copyright (C) 2023 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -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,7 +110,7 @@ static int mapped_openat(struct hexagonfs_fd *dir,
ctx->dir = NULL;
fd->off = 0;
fd->is_assigned = false;
fd->up = dir;
fd->ops = &hexagonfs_mapped_ops;
fd->data = ctx;
@@ -126,7 +126,7 @@ err:
return ret;
}
ssize_t mapped_read(struct hexagonfs_fd *fd, size_t size, void *out)
static ssize_t mapped_read(struct hexagonfs_fd *fd, size_t size, void *out)
{
struct mapped_ctx *ctx = fd->data;
ssize_t ret;
@@ -138,7 +138,7 @@ ssize_t mapped_read(struct hexagonfs_fd *fd, size_t size, void *out)
return ret;
}
int mapped_readdir(struct hexagonfs_fd *fd, size_t size, char *out)
static int mapped_readdir(struct hexagonfs_fd *fd, size_t size, char *out)
{
struct mapped_ctx *ctx = fd->data;
struct dirent *ent;
@@ -216,6 +216,89 @@ static int mapped_stat(struct hexagonfs_fd *fd, struct stat *stats)
return 0;
}
static void mapped_or_empty_close(void *fd_data)
{
if (fd_data)
mapped_close(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;
return 0;
}
static int mapped_or_empty_openat(struct hexagonfs_fd *dir,
const char *segment,
bool expect_dir,
struct hexagonfs_fd **out)
{
if (dir->data)
return mapped_openat(dir, segment, expect_dir, out);
else
return -ENOENT;
}
static ssize_t mapped_or_empty_read(struct hexagonfs_fd *fd,
size_t size, void *out)
{
if (fd->data)
return mapped_read(fd, size, out);
return 0;
}
static int mapped_or_empty_readdir(struct hexagonfs_fd *fd,
size_t size, char *out)
{
if (fd->data) {
return mapped_readdir(fd, size, out);
} else {
out[0] = '\0';
return 0;
}
}
static int mapped_or_empty_seek(struct hexagonfs_fd *fd, off_t off, int whence)
{
if (fd->data)
return mapped_seek(fd, off, whence);
else
return 0;
}
static int mapped_or_empty_stat(struct hexagonfs_fd *fd, struct stat *stats)
{
if (fd->data) {
return mapped_stat(fd, stats);
} else {
stats->st_size = 0;
stats->st_dev = 0;
stats->st_rdev = 0;
stats->st_ino = 0;
stats->st_nlink = 0;
stats->st_mode = S_IFDIR
| S_IRUSR | S_IXUSR
| S_IRGRP | S_IXGRP
| S_IROTH | S_IXOTH;
stats->st_atim.tv_sec = 0;
stats->st_atim.tv_nsec = 0;
stats->st_ctim.tv_sec = 0;
stats->st_ctim.tv_nsec = 0;
stats->st_mtim.tv_sec = 0;
stats->st_mtim.tv_nsec = 0;
return 0;
}
}
/*
* This is the sysfs variant of the stat function.
*
@@ -249,6 +332,16 @@ struct hexagonfs_file_ops hexagonfs_mapped_ops = {
.stat = mapped_stat,
};
struct hexagonfs_file_ops hexagonfs_mapped_or_empty_ops = {
.close = mapped_or_empty_close,
.from_dirent = mapped_or_empty_from_dirent,
.openat = mapped_or_empty_openat,
.read = mapped_or_empty_read,
.readdir = mapped_or_empty_readdir,
.seek = mapped_or_empty_seek,
.stat = mapped_or_empty_stat,
};
struct hexagonfs_file_ops hexagonfs_mapped_sysfs_ops = {
.close = mapped_close,
.from_dirent = mapped_from_dirent,
@@ -1,7 +1,7 @@
/*
* HexagonFS operations for a missing sysfs file
*
* Copyright (C) 2023 Richard Acayan
* Copyright (C) 2023 The Sensor Shell Contributors
*
* This file is part of sensh.
*
@@ -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;
Loaded 20 of 62 files, more files were not shown because too many files have changed in this diff. Show more