术语库
- HCI -- 主机控制器接口:主机控制器接口驱动程序是 负责将 USB 请求加入队列,以及管理状态, 同时作为 USB 主机运行的设备。
- DCI -- 设备控制器接口:设备控制器接口 负责将向设备所连接的 USB 主机的 USB 请求加入队列。 连接。
分配
USB 请求生命周期的第一步是分配。USB 请求包含 请求堆栈中所有驱动程序的数据。每个 作为 USB 设备驱动程序上游的驱动程序,应该提供 GetRequestSize 方法, 该方法会返回包含其本地请求上下文所需的大小。当 USB 设备驱动程序分配请求,它应调用此方法来 确定父级请求上下文的大小。
C 示例
size_t parent_req_size = usb_get_request_size(&usb);
usb_request_t* request;
usb_request_alloc(&request, transfer_length, endpoint_addr,
parent_req_size+sizeof(your_context_struct_t));
usb_request_complete_callback_t complete = {
.callback = usb_request_complete,
.ctx = your_context_pointer,
};
your_context_pointer.completion = complete;
usb_request_queue(&usb, request, &complete);
...
void usb_request_complete(void* cookie, usb_request_t* request) {
your_context_struct_t data;
// memcpy is needed to ensure alignment
memcpy(&data, cookie, sizeof(data));
// Do something here to process the response
// ...
// Requeue the request
usb_request_queue(&data.usb, request, &data.completion);
}
C++ 示例
parent_req_size = usb.GetRequestSize();
std::optional<usb::Request<void>> req;
status = usb::Request<void>::Alloc(&req, transfer_length,
endpoint_addr, parent_req_size);
usb_request_complete_callback_t complete = {
.callback =
[](void* ctx, usb_request_t* request) {
static_cast<YourDeviceClass*>(ctx)->YourHandlerFunction(request);
},
.ctx = this,
};
usb.RequestQueue(req->take(), &complete);
C++ 示例(使用 lambda)
size_t parent_size = usb_.GetRequestSize();
using Request = usb::CallbackRequest<sizeof(std::max_align_t) * 4>;
std::optional<Request> request;
Request::Alloc(&request, max_packet_size, endpoint_address,
parent_size, [=](Request request) {
// Do some processing here.
// ...
// Re-queue the request
Request::Queue(std::move(request), usb_client_);
});
提交内容
您可以使用
RequestQueue 方法定义,
或者 -- 如果是 CallbackRequests(如此处所示),请使用
Request::Queue
,或者干脆是 request.Queue(client)
。在所有情况下,
USB 请求会传输到父级驱动程序(通常为 usb-device
)。
USB 请求的典型生命周期(从设备驱动程序到主机) 控制器或设备控制器):
- USB 设备驱动程序将请求加入队列
usb-device
核心驱动程序收到请求,并且现在拥有该请求 对象。usb-device
核心驱动程序会注入自己的回调(如果直接标记 或者将请求(如果设置了 direct 标记)传递给 HCI 或 DCI 驱动程序。- HCI 或 DCI 驱动程序现在拥有该请求。HCI 或 DCI 驱动程序提交 向硬件发出此请求
- 请求完成。在这种情况下,如果设置了直接标记, 回调,并且设备驱动程序现在拥有 请求。如果未设置直接标志,usb-device(核心)驱动程序 现在拥有该请求
- 请求归核心驱动程序所有;它会添加到队列中 另一个线程。
- 核心驱动程序最终调用回调,请求现在 设备驱动程序所有。设备驱动程序现在可以重新提交 请求。
取消
请求可通过调用
CancelAll。时间
CancelAll 完成,所有
请求都归调用方所有。用于实现
CancelAll 函数(如
USB 设备核心驱动程序和任何 HCI/DCI 驱动程序)负责
通过 ZX_ERR_CANCELLED
状态代码将所有权转让给子级。
面向 HCI、DCI 或过滤器驱动程序编写人员的实现说明
实现 GetRequestSize
由
GetRequestSize 的大小
等于您父级发布商的值
GetRequestSize + 大小
请求上下文的一部分,包括加载网页时所需的
确保数据结构的一致性(如果适用)。如果您
实现 HCI 或 DCI 驱动程序,就必须将 sizeof(usb_request_t)
以及您所用的任何其他数据结构之外,
存储容量usb_request_t
没有特殊的对齐要求,因此
为该结构添加内边距所需的操作。
实现 RequestQueue
的实现者
RequestQueue(临时)
假定拥有来自其客户端驱动程序的 USB 请求的所有权。作为实施者
属于 RequestQueue 的一部分,
系统允许访问 usb_request_t
的所有字段,
已附加到 usb_request_t
结构的数据(通过请求
增加空间
GetRequestSize),但
不得修改您私人区域之外的任何数据,
位于 parent_req_size
字节(usb_request_t
结束之后)。
USB 请求堆栈 (HCI) 示例
xHCI(主机控制器)->usb-bus
->usb-device
(核心 USB 设备驱动程序)->
usb-mass-storage
USB 请求堆栈 (DCI) 示例
dwc2
(设备端控制器)->usb-peripheral
(外设核心驱动程序)->
usb-function
(核心功能驱动程序)->cdc-eth-function
(以太网)
外围设备模式驱动程序)