USB 要求的生命週期

詞彙解釋

  • 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::Queuerequest.Queue(client)。在任何情況下 USB 要求會傳輸到父項驅動程式庫 (通常是 usb-device)。

USB 要求的典型生命週期 (從裝置驅動程式庫到主機) 控制器或裝置控制器如下:

  • USB 裝置驅動程式庫會將要求排入佇列
  • usb-device 核心驅動程式收到要求,現在擁有要求 物件。
  • usb-device 核心驅動程式會插入自己的回呼 (如果直接標記) 未設定),或透過要求 (如果已設定直接標記) 傳送給 HCI 或 DCI 驅動程式庫
  • HCI 或 DCI 驅動程式庫現在擁有要求。HCI 或 DCI 驅動程式庫提交 發出硬體要求
  • 要求已完成。發生這種情況時,如果設定直接旗標, 系統叫用裝置驅動程式庫中的回呼,且裝置驅動程式庫現已擁有 要求。如果未設定直接旗標,則 usb-device (core) 驅動程式庫 現在擁有要求
  • 如果核心驅動程式擁有要求;則排入佇列,以便 另一個執行緒。
  • 核心驅動程式最終會叫用回呼,而要求現已 裝置驅動程式庫擁有的權限。裝置驅動程式庫現在可以 請求。

取消

您可以透過叫用 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 (乙太網路) 週邊裝置模式驅動程式庫)