Author SHA1 Message Date
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
14 changed files with 349 additions and 39 deletions

No files matched your search

+15 -7
View File
@@ -125,18 +125,26 @@ Interfaces are initialized in the `start_reverse_tunnel` function, in hexagonrpc
## HexagonFS
The reverse tunnel's `apps_std` interface serves files to the remote processor.
These files are 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:
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
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
+1 -1
View File
@@ -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,
+2 -2
View File
@@ -47,7 +47,7 @@ static void mapped_close(void *fd_data)
free(ctx);
}
static int mapped_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
struct mapped_ctx *ctx;
const char *name = dirent_data;
@@ -222,7 +222,7 @@ static void mapped_or_empty_close(void *fd_data)
mapped_close(fd_data);
}
static int mapped_or_empty_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_or_empty_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
int ret;
+2 -2
View File
@@ -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;
+16 -7
View File
@@ -31,10 +31,10 @@
* This function searches for the relevant path segment in the path directory.
* It is not optimized because it is dealing with small directories.
*/
static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
static const struct hexagonfs_dirent *walk_dir(const struct hexagonfs_dirent *const *dir,
const char *segment)
{
struct hexagonfs_dirent **curr = dir;
const struct hexagonfs_dirent *const *curr = dir;
while (*curr != NULL) {
if (!strcmp(segment, (*curr)->name))
@@ -46,9 +46,17 @@ static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
return *curr;
}
static int virt_dir_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int virt_dir_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
*fd_data = dirent_data;
const struct hexagonfs_dirent *const **wrapper;
wrapper = malloc(sizeof(*wrapper));
if (wrapper == NULL)
return -ENOMEM;
*wrapper = dirent_data;
*fd_data = wrapper;
return 0;
}
@@ -57,12 +65,12 @@ static int virt_dir_openat(struct hexagonfs_fd *dir,
bool expect_dir,
struct hexagonfs_fd **out)
{
const struct hexagonfs_dirent *const **dirlist = dir->data;
const struct hexagonfs_dirent *ent;
struct hexagonfs_fd *fd;
struct hexagonfs_dirent *ent;
struct hexagonfs_dirent **dirlist = dir->data;
int ret;
ent = walk_dir(dirlist, segment);
ent = walk_dir(*dirlist, segment);
if (ent == NULL)
return -ENOENT;
@@ -89,6 +97,7 @@ err:
static void virt_dir_close(void *fd_data)
{
free(fd_data);
}
static int virt_dir_stat(struct hexagonfs_fd *fd, struct stat *stats)
+64
View File
@@ -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\&.
+1
View File
@@ -17,3 +17,4 @@ executable('hexagonrpcd',
link_with : libhexagonrpc,
install_dir : get_option('bindir'),
)
install_man('hexagonrpcd.1')
+39 -18
View File
@@ -31,6 +31,7 @@
#define SENSORS_CONFIG "/sensors/config/"
#define SENSORS_REGISTRY "/sensors/registry/"
#define SNS_REG_CONFIG "/sensors/sns_reg.conf"
#define SYSFS_SOCINFO "/socinfo/"
static struct hexagonfs_dirent *hfs_mkdir(const char *name, size_t n_ents, ...)
{
@@ -110,9 +111,9 @@ static struct hexagonfs_dirent *hfs_map_or_empty(const char *name, const char *p
*/
struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
{
char *acdbdata, *dsp_libs, *sns_cfg, *sns_reg, *sns_reg_config;
char *acdbdata, *dsp_libs, *sns_cfg, *sns_reg, *sns_reg_config, *socinfo;
size_t n_prefix;
struct hexagonfs_dirent *persist_dir;
struct hexagonfs_dirent *persist_dir, *vendor_dir;
n_prefix = strlen(prefix);
@@ -120,6 +121,7 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
sns_cfg = malloc(n_prefix + strlen(SENSORS_CONFIG) + 1);
sns_reg = malloc(n_prefix + strlen(SENSORS_REGISTRY) + 1);
sns_reg_config = malloc(n_prefix + strlen(SNS_REG_CONFIG) + 1);
socinfo = malloc(n_prefix + strlen(SYSFS_SOCINFO) + 1);
dsp_libs = malloc(n_prefix + strlen(DSP_LIBS) + strlen(dsp) + 1);
@@ -143,6 +145,11 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
strcat(sns_reg_config, SNS_REG_CONFIG);
}
if (socinfo != NULL) {
strcpy(socinfo, prefix);
strcat(socinfo, SYSFS_SOCINFO);
}
if (dsp_libs != NULL) {
strcpy(dsp_libs, prefix);
strcat(dsp_libs, DSP_LIBS);
@@ -161,21 +168,11 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
)
);
return hfs_mkdir("/", 4,
hfs_mkdir("mnt", 1,
hfs_mkdir("vendor", 1,
persist_dir
)
),
persist_dir,
hfs_mkdir("usr", 1,
hfs_mkdir("lib", 1,
hfs_mkdir("qcom", 1,
hfs_map_or_empty("adsp", dsp_libs)
)
)
),
hfs_mkdir("vendor", 1,
/*
* Some platforms need vendor in / and some need it in /system. Form
* a hard link between both locations.
*/
vendor_dir = hfs_mkdir("vendor", 1,
hfs_mkdir("etc", 2,
hfs_mkdir("sensors", 2,
hfs_map_or_empty("config", sns_cfg),
@@ -183,6 +180,30 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
),
hfs_map("acdbdata", acdbdata)
)
)
);
return hfs_mkdir("/", 6,
hfs_mkdir("mnt", 1,
hfs_mkdir("vendor", 1,
persist_dir
)
),
persist_dir,
hfs_mkdir("sys", 1,
hfs_mkdir("devices", 1,
hfs_map_or_empty("soc0", socinfo)
)
),
hfs_mkdir("system", 1,
vendor_dir
),
hfs_mkdir("usr", 1,
hfs_mkdir("lib", 1,
hfs_mkdir("qcom", 1,
hfs_map_or_empty("adsp", dsp_libs)
)
)
),
vendor_dir
);
}
+1
View File
@@ -5,6 +5,7 @@ libhexagonrpc = shared_library('hexagonrpc',
'session.c',
c_args : cflags,
include_directories : include,
soversion : api_version,
install : true
)
+4 -1
View File
@@ -1,4 +1,7 @@
project('fastrpc', 'c')
project('fastrpc', 'c', version: '0.3.2')
version_array = meson.project_version().split('.')
api_version = version_array[0] + '.' + version_array[1]
include = include_directories('include')
client_target = get_option('libexecdir') / 'hexagonrpc'
+1 -1
View File
@@ -1,2 +1,2 @@
option('hexagonrpcd_verbose', type : 'boolean', value : true,
option('hexagonrpcd_verbose', type : 'boolean', value : false,
description : 'Compile hexagonrpcd with extra logging for each remote method invocation')
+14
View File
@@ -11,4 +11,18 @@ test_iobuffer = executable('test_iobuffer',
include_directories : include,
)
sample_file = custom_target('sample_file',
input : 'sample_file.txt',
output : 'sample_file.txt',
command : ['cp', '@INPUT@', '@OUTPUT@']
)
test_hexagonfs = executable('test_hexagonfs',
'test_hexagonfs.c',
'../hexagonrpcd/hexagonfs.c',
'../hexagonrpcd/hexagonfs_mapped.c',
c_args : cflags,
include_directories : include,
)
test('iobuffer', test_iobuffer)
test('hexagonfs', test_hexagonfs, args : [sample_file])
+91
View File
@@ -0,0 +1,91 @@
/*
* FastRPC reverse tunnel - sample file for HexagonFS mapped file test
*
* Copyright (C) 2024 The HexagonRPC Contributors
*
* This file is part of HexagonRPC.
*
* HexagonRPC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#![feature(io_error_more)]
use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use std::process::ExitCode;
trait HexagonFSFile {
fn seek(&self) -> Result<u64>;
fn read(&self) -> Result<usize>;
fn openat<'a>(&'a self, name: &str) -> Result<Box<dyn HexagonFSFile + 'a>>;
}
trait HexagonFSDirent {
fn open<'a>(&'a self) -> Box<dyn HexagonFSFile + 'a>;
}
struct VirtDir<'a> {
def: &'a VirtDirDirent<'a>,
}
impl<'a> HexagonFSFile for VirtDir<'a> {
fn seek(&self) -> Result<u64>
{
Err(Error::new(ErrorKind::IsADirectory, "Is a directory"))
}
fn read(&self) -> Result<usize>
{
Err(Error::new(ErrorKind::IsADirectory, "Is a directory"))
}
fn openat<'b>(&'b self, name: &str) -> Result<Box<dyn HexagonFSFile + 'b>>
{
let resolution = self.def.files.get(name);
match resolution {
Some(dirent) => Ok(dirent.open()),
None => Err(Error::new(ErrorKind::NotFound, "No such file or directory"))
}
}
}
struct VirtDirDirent<'a> {
files: HashMap<&'a str, Box<dyn HexagonFSDirent>>
}
impl<'b> HexagonFSDirent for VirtDirDirent<'b> {
fn open<'a>(&'a self) -> Box<dyn HexagonFSFile + 'a>
{
Box::new(VirtDir {
def: self
})
}
}
fn main() -> ExitCode
{
let root_dir = &VirtDirDirent { files: HashMap::from([
("sys", Box::new(VirtDirDirent { files: HashMap::from([
])}) as Box<dyn HexagonFSDirent>),
])};
let rootfd = root_dir.open();
let dirfd = rootfd.openat("");
return ExitCode::SUCCESS;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* FastRPC reverse tunnel - tests for virtual filesystem
*
* Copyright (C) 2024 The HexagonRPC Contributors
*
* This file is part of HexagonRPC.
*
* HexagonRPC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <libhexagonrpc/fastrpc.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "../hexagonrpcd/hexagonfs.h"
static int test_mapped_seq_read(const char *path)
{
struct hexagonfs_fd file = {
.is_assigned = true,
.up = NULL,
.ops = &hexagonfs_mapped_ops,
};
int ret, fd;
char *buf1, *buf2;
buf1 = malloc(256);
if (buf1 == NULL)
return 1;
buf2 = malloc(256);
if (buf2 == NULL)
return 1;
fd = open(path, O_RDONLY);
if (fd == -1)
return 1;
ret = hexagonfs_mapped_ops.from_dirent(path, false, &file.data);
if (ret)
return 1;
memset(buf1, 0, 6);
memset(buf2, 0, 6);
read(fd, buf1, 1);
read(fd, &buf1[1], 5);
hexagonfs_mapped_ops.read(&file, 1, buf2);
hexagonfs_mapped_ops.read(&file, 5, &buf2[1]);
if (memcmp(buf1, buf2, 6))
return 1;
memset(buf1, 0, 27);
memset(buf2, 0, 27);
lseek(fd, 819 - 6, SEEK_CUR);
read(fd, buf1, 27);
hexagonfs_mapped_ops.seek(&file, 819 - 6, SEEK_CUR);
hexagonfs_mapped_ops.read(&file, 27, buf2);
if (memcmp(buf1, buf2, 27))
return 1;
hexagonfs_mapped_ops.close(file.data);
close(fd);
free(buf2);
free(buf1);
return 0;
}
int main(int argc, const char **argv)
{
int ret;
if (argc < 2)
return 1;
ret = test_mapped_seq_read(argv[1]);
if (ret)
return ret;
return 0;
}