libxtos-bci
BCI 会话、设备能力、缓冲区所有权和公开数据格式限制。
本页目录
设备前提
会话访问 XTOS 字符设备(如 /dev/xtos0),不直接访问任意 /dev/ttyUSB0。
需要 xtos_bci_core、xtos_bci_buffer 和匹配设备驱动,并完成设备注册。
公开 OpenBCI Cyton 实现是 serdev 驱动,设备树 compatible 为 openbci,cyton;加载模块不等于串口绑定或设备注册。
create 使用 open(path, O_RDWR),调用者需要读写权限。节点缺失通常 ENOENT,权限不足 EACCES。内核 core 当前只允许一个打开者,第二个为 EBUSY。QEMU 可验证模块加载,不能在没有串口板卡时证明硬件采集。
会话顺序
xtos_bci_session_t *xtos_bci_session_create(const char *device_path);
int xtos_bci_get_info(xtos_bci_session_t *session,
struct xtos_bci_device_info *info);
int xtos_bci_start(xtos_bci_session_t *session);
int xtos_bci_stop(xtos_bci_session_t *session);
void xtos_bci_session_destroy(xtos_bci_session_t *session);- create:path 非 NULL 且为 NUL 结尾字符串;NULL 为 EINVAL,分配或 open 失败返回 NULL 并保留失败 errno。
- get_info:session/info 非 NULL;返回 create 时缓存,不重新请求 GET_INFO。检查 num_channels、sampling_rate、resolution_bits。
- 配置:采集前选择驱动支持的采样率和通道;成功不证明硬件采纳每项配置。
- start→采集或 poll→stop:start/stop 执行 ioctl,成功 0、失败 -1;仅 ioctl 成功后更新 streaming 标志。
- destroy:先停工作线程;函数尝试停止活跃会话,再 munmap、close、free。destroy(NULL) 是空操作,清理失败无返回值。
GET_INFO 失败时 create 仍返回会话,缓存保持 calloc 的零值;后续 get_info 可能返回 0。因此创建成功不等于节点实现 XTOS UAPI。info.name 是固定 32 字节,未保证 NUL 结尾,输出要限长。session.c 无并发锁;不要并发读、配置或销毁同一会话。
采集配置
| 接口 | 约束与返回 | 公开 Cyton 行为 |
|---|---|---|
| set_sampling_rate | rate 为整数 Hz;库不检查支持列表;成功 0/-1,成功后更新缓存。 | 支持 250/500/1000/2000 Hz,否则 EINVAL;串口命令结果未完整检查,不重分配已有 ring buffer。 |
| set_channel | channel 从 0 开始,enabled 为 bool,gain 为 uint32;NULL session 为 EINVAL,其他返回 ioctl。 | Cyton 为 0–7;core 传 channel/enabled,不传 gain,不能声称修改硬件增益。 |
| calibrate | NULL session 为 -1/EINVAL;其他由驱动决定。 | Cyton 打印 not implemented 并返回 0,不执行校准。 |
| check_impedance | output 非 NULL,1≤channels≤32;数组至少 channels 个 uint32,单位整数 kΩ。 | Cyton 返回 EOPNOTSUPP,不填伪造结果。 |
这些接口配置采集设备,不是执行器命令接口。ioctl 可能返回 EINVAL、EOPNOTSUPP、EFAULT 或未知命令的 ENOTTY,串口错误也可能上传。区分参数非法、能力不支持和链路失败;同时记录期望配置和核验配置。
样本格式
ssize_t xtos_bci_read_samples(xtos_bci_session_t *session,
float *buffer, size_t num_samples);要求 session/buffer 非 NULL、num_samples>0,否则 -1/EINVAL。
函数一次 read 请求 num_samples×sizeof(float) 字节,再以读取字节数除以 sizeof(float) 返回;buffer 至少容纳 num_samples 个 float。
参数是标量通道值数量,不自动表示多通道帧数。
允许短读;-1 的 errno 来自 read;不检查乘法溢出或帧对齐。
该读取接口不返回时间戳、packet 序号、质量标志或可靠帧边界;读完成时间不是设备采样时间。若在核验过的驱动上通过借用 fd 读取原始整数,应用必须实现字节拼接、完整帧对齐、单位转换和时间标注,这不是 SDK 已提供的转换。公开串口解析从 packet[1] 读取通道字节,未显式提取序号,也没有完整尾部校验;源码存在不等于 Cyton 协议已验证。
fd 与 mmap
void *xtos_bci_get_mmap_buffer(xtos_bci_session_t *session, size_t *size);
int xtos_bci_get_fd(xtos_bci_session_t *session);get_fd 返回会话拥有的借用 fd;NULL 为 -1/EINVAL。可用于 poll/select,但不能 close,也不能在 destroy 后使用。open 默认不是 O_NONBLOCK;poll 后 read 仍可能受竞态、信号和短读影响。应用可用 fcntl 设置非阻塞,此时无数据可为 EAGAIN。
get_mmap_buffer 按 channels×sampling_rate×sizeof(float)×2 字节估算,用 PROT_READ、MAP_SHARED 映射;size 可 NULL。成功后缓存并返回同一借用地址;失败返回 NULL,errno 来自 mmap 或参数校验。调用方不能 free/munmap;destroy 释放映射;失败后不要读取未写入的 size。
估算不查询真实 ring buffer 字节数,采样率变更也不刷新缓存映射。mmap 按页工作,非页对齐估算或变更后的大小可能超过实际缓冲区并失败。映射没有 write_pos/read_pos、稳定快照、时间戳或消费者推进协议;单独的指针不是完整零拷贝流方案。
统计与限制
int xtos_bci_get_stats(xtos_bci_session_t *session,
struct xtos_bci_statistics *stats);
int xtos_bci_reset_stats(xtos_bci_session_t *session);get_stats 要求 session/stats 非 NULL,返回 0/-1;reset_stats 要求 session 非 NULL。字段为 samples_read、samples_dropped、errors、overruns。Cyton 在通道值写入缓冲后增加 samples_read,不是应用读出的帧数;空间不足时 ring buffer 丢弃最旧字节并增加 overruns,samples_dropped 不是所有丢失的完整计数。源码:sdk/libxtos-bci/include/xtos/bci.h、bci_uapi.h、src/session.c;内核为 xtos_bci_core.c、xtos_bci_buffer.c、devices/openbci_cyton.c。
应分别记录会话控制、缺少转换的读取路径、校准占位、gain 未传驱动、阻抗不支持和 mmap 协议不足;这些事实不能合并为“硬件 BCI 全链路已验证”。