用户空间 EC 接口 (cdev)¶
surface_aggregator_cdev
模块为 SSAM 控制器提供了一个 misc 设备,允许用户空间(或多或少)直接连接到 SAM EC。 它旨在用于开发和调试,因此不应以任何其他方式使用或依赖。 请注意,此模块不会自动加载,而是必须手动加载。
提供的接口可以通过 /dev/surface/aggregator
设备文件访问。 此接口的所有功能都通过 IOCTL 提供。 这些 IOCTL 及其各自的输入/输出参数结构在 include/uapi/linux/surface_aggregator/cdev.h
中定义。
可以在 https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam 找到一个小型 python 库和用于访问此接口的脚本。
接收事件¶
可以通过从设备文件读取来接收事件。 它们由 struct ssam_cdev_event
数据类型表示。
但是,在事件可以被读取之前,必须通过 SSAM_CDEV_NOTIF_REGISTER
IOCTL 注册所需的通知器。 从本质上讲,通知器是回调函数,当 EC 发送事件时调用。 在此接口中,它们与特定的目标类别和设备文件实例相关联。 它们将此类别的任何事件转发到相应实例的缓冲区,然后可以从中读取该事件。
通知器本身不会在 EC 上启用事件。 因此,可能还需要通过 SSAM_CDEV_EVENT_ENABLE
IOCTL 启用事件。 虽然通知器按客户端工作(即每个设备文件实例),但事件是全局启用的,适用于 EC 及其所有客户端(无论用户空间还是非用户空间)。 SSAM_CDEV_EVENT_ENABLE
和 SSAM_CDEV_EVENT_DISABLE
IOCTL 负责事件的引用计数,以便只要有客户端请求该事件,该事件就会被启用。
请注意,一旦客户端实例关闭,已启用的事件不会自动禁用。 因此,任何客户端进程(或进程组)都应平衡其事件启用调用与相应的事件禁用调用。 但是,在不同的客户端实例上启用和禁用事件是完全有效的。 例如,可以在客户端实例 A
上设置通知器并读取事件,在实例 B
上启用这些事件(请注意,由于事件是全局启用/禁用的,因此 A 也会收到这些事件),并且在不再需要任何事件后,通过实例 C
禁用先前启用的事件,这是有效的。
控制器 IOCTL¶
提供以下 IOCTL
类型 |
编号 |
方向 |
名称 |
描述 |
---|---|---|---|---|
|
|
|
|
执行同步 SAM 请求。 |
|
|
|
|
注册事件通知器。 |
|
|
|
|
取消注册事件通知器。 |
|
|
|
|
启用事件源。 |
|
|
|
|
禁用事件源。 |
SSAM_CDEV_REQUEST
¶
定义为 _IOWR(0xA5, 1, struct ssam_cdev_request)
。
执行同步 SAM 请求。 请求规范作为 struct ssam_cdev_request
类型的参数传入,然后由 IOCTL 写入/修改以返回请求的状态和结果。
请求有效负载数据必须单独分配,并通过 payload.data
和 payload.length
成员传入。 如果需要响应,则响应缓冲区必须由调用者分配,并通过 response.data
成员传入。 response.length
成员必须设置为此缓冲区的容量,如果不需要响应,则设置为零。 请求完成后,调用会将响应写入响应缓冲区(如果其容量允许),并用响应的实际大小(以字节为单位)覆盖长度字段。
此外,如果请求有响应,则必须通过请求标志来指示,就像在内核请求中一样。 可以通过 flags
成员设置请求标志,并且这些值对应于在 enum ssam_cdev_request_flags
中找到的值。
最后,请求本身的状态在 status
成员中返回(负 errno 值表示失败)。 请注意,IOCTL 的失败指示与请求的失败指示是分开的:如果在请求设置过程中出现任何故障(-EFAULT
)或者如果提供的参数或其任何字段无效(-EINVAL
),则 IOCTL 返回负状态码。 在这种情况下,可以设置请求参数的状态值,从而提供有关出现问题的更多详细信息(例如,内存不足的 -ENOMEM
),但此值也可能为零。 如果请求已成功地从 IOCTL 内部设置、提交和完成(即交回用户空间),则 IOCTL 将返回零状态码,但如果请求在提交后实际执行失败,则请求 status
成员可能仍然为负。
下面提供了参数结构的完整定义。
SSAM_CDEV_NOTIF_REGISTER
¶
定义为 _IOW(0xA5, 2, struct ssam_cdev_notifier_desc)
。
使用指定的优先级为给定通知器描述中指定的事件目标类别注册通知器。 注册通知器是接收事件所必需的,但本身不会启用事件。 在为特定目标类别注册通知器后,该类别的所有事件都将转发到用户空间客户端,然后可以从设备文件实例中读取。 请注意,在 EC 发送事件之前,可能必须启用事件,例如通过 SSAM_CDEV_EVENT_ENABLE
IOCTL。
每个目标类别和客户端实例只能注册一个通知器。 如果已注册通知器,则此 IOCTL 将失败并显示 -EEXIST
。
当设备文件实例关闭时,通知器将自动删除。
SSAM_CDEV_NOTIF_UNREGISTER
¶
定义为 _IOW(0xA5, 3, struct ssam_cdev_notifier_desc)
。
取消注册与指定目标类别关联的通知器。 此 IOCTL 将忽略优先级字段。 如果没有为此客户端实例和给定类别注册通知器,则此 IOCTL 将失败并显示 -ENOENT
。
SSAM_CDEV_EVENT_ENABLE
¶
定义为 _IOW(0xA5, 4, struct ssam_cdev_event_desc)
。
启用与给定事件描述符关联的事件。
请注意,此调用本身不会注册通知器,它只会启用控制器上的事件。 如果您想通过从设备文件读取来接收事件,则需要在该实例上注册相应的通知器。
关闭设备文件时,事件不会自动禁用。 这必须手动完成,通过调用 SSAM_CDEV_EVENT_DISABLE
IOCTL。
SSAM_CDEV_EVENT_DISABLE
¶
定义为 _IOW(0xA5, 5, struct ssam_cdev_event_desc)
。
禁用与给定事件描述符关联的事件。
请注意,这不会取消注册任何通知器。 在此调用之后,可能仍会收到事件并将其转发到用户空间。 停止接收事件的唯一安全方法是取消注册所有先前注册的通知器。
结构体和枚举¶
-
enum ssam_cdev_request_flags¶
SSAM cdev 请求 IOCTL 的请求标志。
常量
SSAM_CDEV_REQUEST_HAS_RESPONSE
指定请求需要响应。 如果未设置,则请求将在其底层数据包传输后直接完成。 如果设置,则请求传输系统会等待请求的响应。
SSAM_CDEV_REQUEST_UNSEQUENCED
指定应通过未排序的数据包传输请求。 如果设置,则请求不得有响应,这意味着此标志和
SSAM_CDEV_REQUEST_HAS_RESPONSE
标志互斥。
-
struct ssam_cdev_request¶
控制器请求 IOCTL 参数。
定义:
struct ssam_cdev_request {
__u8 target_category;
__u8 target_id;
__u8 command_id;
__u8 instance_id;
__u16 flags;
__s16 status;
struct {
__u64 data;
__u16 length;
__u8 __pad[6];
} payload;
struct {
__u64 data;
__u16 length;
__u8 __pad[6];
} response;
};
成员
target_category
SAM 请求的目标类别。
target_id
SAM 请求的目标 ID。
command_id
SAM 请求的命令 ID。
instance_id
SAM 请求的实例 ID。
flags
请求标志(请参阅
enum ssam_cdev_request_flags
)。status
请求状态(输出)。
payload
请求有效负载(输入数据)。
payload.data
指向请求有效负载数据的指针。
payload.length
请求有效负载数据的长度(以字节为单位)。
response
请求响应(输出数据)。
response.data
指向响应缓冲区的指针。
response.length
输入:响应缓冲区的容量(以字节为单位)。 输出:请求响应的长度(缓冲区中实际使用的字节数)。
-
struct ssam_cdev_notifier_desc¶
通知器描述符。
定义:
struct ssam_cdev_notifier_desc {
__s32 priority;
__u8 target_category;
};
成员
priority
优先级值,确定调用通知器回调的顺序。 值越高意味着优先级越高,即关联的回调将比其他(较低优先级)回调更早执行。
target_category
此通知器应接收事件的事件目标类别。
描述
指定应注册或取消注册的通知器,特别是具有哪个优先级以及用于哪个目标类别的事件。
-
struct ssam_cdev_event_desc¶
事件描述符。
定义:
struct ssam_cdev_event_desc {
struct {
__u8 target_category;
__u8 target_id;
__u8 cid_enable;
__u8 cid_disable;
} reg;
struct {
__u8 target_category;
__u8 instance;
} id;
__u8 flags;
};
成员
reg
将通过其启用/禁用事件的注册表。
reg.target_category
事件注册表请求的目标类别。
reg.target_id
事件注册表请求的目标 ID。
reg.cid_enable
用于启用事件请求的命令 ID。
reg.cid_disable
用于禁用事件请求的命令 ID。
id
指定事件的 ID。
id.target_category
事件源的目标类别。
id.instance
事件源的实例 ID。
flags
用于启用事件的标志。
描述
指定应启用/禁用哪个事件以及如何执行此操作。
-
struct ssam_cdev_event¶
EC 发送的 SSAM 事件。
定义:
struct ssam_cdev_event {
__u8 target_category;
__u8 target_id;
__u8 command_id;
__u8 instance_id;
__u16 length;
__u8 data[];
};
成员
target_category
事件源的目标类别。 请参阅
enum ssam_ssh_tc
。target_id
事件源的目标 ID。
command_id
事件的命令 ID。
instance_id
事件源的实例 ID。
length
事件有效负载的长度,以字节为单位。
data
事件有效负载数据。