詞彙解釋
- 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
核心驅動程式會插入自己的回呼 (如果未設定直接標記),或是透過要求 (如果已設定直接標記) 傳遞至 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 要求額外空間),但您無法修改不公開區域外的任何資料 (從 usb_request_t
結尾到 usb_request_t
結束)。parent_req_size
USB 要求堆疊範例 (HCI)
xHCI (主機控制器) -> usb-bus
-> usb-device
(核心 USB 裝置驅動程式庫) -> usb-mass-storage
USB 要求堆疊範例 (DCI)
dwc2
(裝置端控制器) -> usb-peripheral
(週邊裝置核心驅動程式) -> usb-function
(核心功能驅動程式庫) -> cdc-eth-function
(乙太網路週邊模式驅動程式庫)