1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <ddk/phys-iter.h> 8#include <sys/types.h> 9#include <zircon/compiler.h> 10#include <zircon/types.h> 11#include <zircon/hw/usb.h> 12#include <zircon/hw/usb-hub.h> 13#include <zircon/listnode.h> 14 15__BEGIN_CDECLS; 16 17typedef struct usb_request usb_request_t; 18 19// cache maintenance ops 20#define USB_REQUEST_CACHE_INVALIDATE ZX_VMO_OP_CACHE_INVALIDATE 21#define USB_REQUEST_CACHE_CLEAN ZX_VMO_OP_CACHE_CLEAN 22#define USB_REQUEST_CACHE_CLEAN_INVALIDATE ZX_VMO_OP_CACHE_CLEAN_INVALIDATE 23#define USB_REQUEST_CACHE_SYNC ZX_VMO_OP_CACHE_SYNC 24 25typedef void (*usb_request_complete_cb)(usb_request_t* req, void* cookie); 26 27// Should be set by the requestor. 28typedef struct usb_header { 29 // frame number for scheduling isochronous transfers 30 uint64_t frame; 31 uint32_t device_id; 32 // bEndpointAddress from endpoint descriptor 33 uint8_t ep_address; 34 // number of bytes to transfer 35 zx_off_t length; 36 // send zero length packet if length is multiple of max packet size 37 bool send_zlp; 38} usb_header_t; 39 40// response data 41// (filled in by processor before usb_request_complete() is called) 42typedef struct usb_response { 43 // status of transaction 44 zx_status_t status; 45 // number of bytes actually transferred (on success) 46 zx_off_t actual; 47} usb_response_t; 48 49typedef struct usb_request { 50 usb_header_t header; 51 52 // for control transactions 53 usb_setup_t setup; 54 55 // vmo_handle for payload 56 zx_handle_t vmo_handle; 57 zx_handle_t bti_handle; 58 size_t size; 59 // offset of the start of data from first page address of the vmo. 60 zx_off_t offset; 61 // mapped address of the first page of the vmo. 62 // Add offset to get actual data. 63 void* virt; 64 65 zx_handle_t pmt; 66 // phys addresses of the payload. 67 zx_paddr_t* phys_list; 68 // Number of physical pages of the payload. 69 uint64_t phys_count; 70 71 // The complete_cb() callback is set by the requestor and is 72 // invoked by the 'complete' ops method when it is called by 73 // the processor upon completion of the usb request. 74 // The saved_complete_cb field can be used to temporarily save 75 // the original callback and overwrite it with the desired intermediate 76 // callback. 77 usb_request_complete_cb complete_cb; 78 79 // Set by the requestor for opting out of the complete_cb() 80 // callback for successfully completed requests. The callback 81 // will still be invoked if an error is encountered. 82 // This is useful for isochronous requests, where the requestor 83 // may not care about most callbacks. They will still have to request 84 // callbacks at a regular interval to queue more data, and free or 85 // reuse previously silently completed requests. 86 bool cb_on_error_only; 87 88 // Set by requestor for passing data to complete_cb callback 89 // The saved_cookie field can be used to temporarily save the 90 // original cookie. 91 void* cookie; 92 93 // The current 'owner' of the usb request may save the original 94 // complete callback and cookie, allowing them to insert an 95 // intermediate callback. 96 usb_request_complete_cb saved_complete_cb; 97 void* saved_cookie; 98 99 usb_response_t response; 100 101 // list node and context 102 // the current "owner" of the usb_request may use these however desired 103 // (eg, the requestor may use node to hold the usb_request on a free list 104 // and when it's queued the processor may use node to hold the usb_request 105 // in a transaction queue) 106 list_node_t node; 107 108 void *context; 109 110 // The release_cb() callback is set by the allocator and is 111 // invoked by the 'usb_request_release' method when it is called 112 // by the requestor. 113 void (*release_cb)(usb_request_t* req); 114} usb_request_t; 115 116 117typedef struct { 118 zx_status_t (*req_alloc)(void* ctx, usb_request_t** out, uint64_t data_size, 119 uint8_t ep_address); 120 zx_status_t (*req_alloc_vmo)(void* ctx, usb_request_t** out, zx_handle_t vmo_handle, 121 uint64_t vmo_offset, uint64_t length, uint8_t ep_address); 122 zx_status_t (*req_init)(void* ctx, usb_request_t* req, zx_handle_t vmo_handle, 123 uint64_t vmo_offset, uint64_t length, uint8_t ep_address); 124 ssize_t (*req_copy_from)(void* ctx, usb_request_t* req, void* data, 125 size_t length, size_t offset); 126 ssize_t (*req_copy_to)(void* ctx, usb_request_t* req, const void* data, 127 size_t length, size_t offset); 128 zx_status_t (*req_mmap)(void* ctx, usb_request_t* req, void** data); 129 zx_status_t (*req_cacheop)(void* ctx, usb_request_t* req, uint32_t op, 130 size_t offset, size_t length); 131 zx_status_t (*req_cache_flush)(void* ctx, usb_request_t* req, 132 size_t offset, size_t length); 133 zx_status_t (*req_cache_flush_invalidate)(void* ctx, usb_request_t* req, 134 zx_off_t offset, size_t length); 135 zx_status_t (*req_physmap)(void* ctx, usb_request_t* req); 136 void (*req_release)(void* ctx, usb_request_t* req); 137 void (*req_complete)(void* ctx, usb_request_t* req, zx_status_t status, zx_off_t actual); 138 void (*req_phys_iter_init)(void* ctx, phys_iter_t* iter, usb_request_t* req, 139 size_t max_length); 140 zx_status_t (*control)(void* ctx, uint8_t request_type, uint8_t request, uint16_t value, 141 uint16_t index, void* data, size_t length, zx_time_t timeout, 142 size_t* out_length); 143 // queues a USB request 144 void (*request_queue)(void* ctx, usb_request_t* usb_request); 145 usb_speed_t (*get_speed)(void* ctx); 146 zx_status_t (*set_interface)(void* ctx, uint8_t interface_number, uint8_t alt_setting); 147 uint8_t (*get_configuration)(void* ctx); 148 zx_status_t (*set_configuration)(void* ctx, uint8_t configuration); 149 zx_status_t (*enable_endpoint)(void* ctx, usb_endpoint_descriptor_t* ep_desc, 150 usb_ss_ep_comp_descriptor_t* ss_comp_desc, bool enable); 151 zx_status_t (*reset_endpoint)(void* ctx, uint8_t ep_address); 152 size_t (*get_max_transfer_size)(void* ctx, uint8_t ep_address); 153 uint32_t (*get_device_id)(void* ctx); 154 void (*get_device_descriptor)(void* ctx, usb_device_descriptor_t* out_desc); 155 zx_status_t (*get_configuration_descriptor)(void* ctx, uint8_t configuration, 156 usb_configuration_descriptor_t** out, 157 size_t* out_length); 158 zx_status_t (*get_descriptor_list)(void* ctx, void** out_descriptors, size_t* out_length); 159 zx_status_t (*get_string_descriptor)(void* ctx, uint8_t desc_id, uint16_t* inout_lang_id, 160 uint8_t* buf, size_t* inout_buflen); 161 zx_status_t (*cancel_all)(void* ctx, uint8_t ep_address); 162 uint64_t (*get_current_frame)(void* ctx); 163} usb_protocol_ops_t; 164 165typedef struct usb_protocol { 166 usb_protocol_ops_t* ops; 167 void* ctx; 168} usb_protocol_t; 169 170static inline zx_status_t usb_req_alloc(const usb_protocol_t* usb, usb_request_t** out, 171 uint64_t data_size, uint8_t ep_address) { 172 return usb->ops->req_alloc(usb->ctx, out, data_size, ep_address); 173} 174 175static inline zx_status_t usb_req_alloc_vmo(const usb_protocol_t* usb, usb_request_t** out, 176 zx_handle_t vmo_handle, uint64_t vmo_offset, 177 uint64_t length, uint8_t ep_address) { 178 return usb->ops->req_alloc_vmo(usb->ctx, out, vmo_handle, vmo_offset, length, ep_address); 179} 180 181static inline zx_status_t usb_req_init(const usb_protocol_t* usb, usb_request_t* req, 182 zx_handle_t vmo_handle, uint64_t vmo_offset, 183 uint64_t length, uint8_t ep_address) { 184 return usb->ops->req_init(usb->ctx, req, vmo_handle, vmo_offset, length, ep_address); 185} 186 187static inline ssize_t usb_req_copy_from(const usb_protocol_t* usb, usb_request_t* req, void* data, 188 size_t length, size_t offset) { 189 return usb->ops->req_copy_from(usb->ctx, req, data, length, offset); 190} 191 192static inline ssize_t usb_req_copy_to(const usb_protocol_t* usb, usb_request_t* req, 193 const void* data, size_t length, size_t offset) { 194 return usb->ops->req_copy_to(usb->ctx, req, data, length, offset); 195} 196 197static inline zx_status_t usb_req_mmap(const usb_protocol_t* usb, usb_request_t* req, 198 void** data) { 199 return usb->ops->req_mmap(usb->ctx, req, data); 200} 201 202static inline zx_status_t usb_req_cacheop(const usb_protocol_t* usb, usb_request_t* req, 203 uint32_t op, size_t offset, size_t length) { 204 return usb->ops->req_cacheop(usb->ctx, req, op, offset, length); 205} 206 207static inline zx_status_t usb_req_cache_flush(const usb_protocol_t* usb, usb_request_t* req, 208 size_t offset, size_t length) { 209 return usb->ops->req_cache_flush(usb->ctx, req, offset, length); 210} 211 212static inline zx_status_t usb_req_cache_flush_invalidate(const usb_protocol_t* usb, 213 usb_request_t* req, zx_off_t offset, 214 size_t length) { 215 return usb->ops->req_cache_flush_invalidate(usb->ctx, req, offset, length); 216} 217 218static inline zx_status_t usb_req_physmap(const usb_protocol_t* usb, usb_request_t* req) { 219 return usb->ops->req_physmap(usb->ctx, req); 220} 221 222static inline void usb_req_release(const usb_protocol_t* usb, usb_request_t* req) { 223 usb->ops->req_release(usb->ctx, req); 224} 225 226static inline void usb_req_complete(const usb_protocol_t* usb, usb_request_t* req, 227 zx_status_t status, zx_off_t actual) { 228 usb->ops->req_complete(usb->ctx, req, status, actual); 229} 230 231static inline void usb_req_phys_iter_init(const usb_protocol_t* usb, phys_iter_t* iter, 232 usb_request_t* req, size_t max_length) { 233 usb->ops->req_phys_iter_init(usb->ctx, iter, req, max_length); 234} 235 236// synchronously executes a control request on endpoint zero 237static inline zx_status_t usb_control(const usb_protocol_t* usb, uint8_t request_type, 238 uint8_t request, uint16_t value, uint16_t index, void* data, 239 size_t length, zx_time_t timeout, size_t* out_length) { 240 return usb->ops->control(usb->ctx, request_type, request, value, index, data, length, timeout, 241 out_length); 242} 243 244static inline zx_status_t usb_get_descriptor(const usb_protocol_t* usb, uint8_t request_type, 245 uint16_t type, uint16_t index, void* data, 246 size_t length, zx_time_t timeout, size_t* out_length) { 247 return usb_control(usb, request_type | USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, 248 (uint16_t)(type << 8 | index), 0, data, length, timeout, out_length); 249} 250 251static inline zx_status_t usb_get_status(const usb_protocol_t* usb, uint8_t request_type, 252 uint16_t index, void* data, size_t length, 253 zx_time_t timeout, size_t* out_length) { 254 return usb_control(usb, request_type | USB_DIR_IN, USB_REQ_GET_STATUS, 0, index, data, length, 255 timeout, out_length); 256} 257 258static inline zx_status_t usb_set_feature(const usb_protocol_t* usb, uint8_t request_type, 259 uint16_t feature, uint16_t index, zx_time_t timeout) { 260 return usb_control(usb, request_type, USB_REQ_SET_FEATURE, feature, index, NULL, 0, timeout, 261 NULL); 262} 263 264static inline zx_status_t usb_clear_feature(const usb_protocol_t* usb, uint8_t request_type, 265 uint16_t feature, uint16_t index, zx_time_t timeout) { 266 return usb_control(usb, request_type, USB_REQ_CLEAR_FEATURE, feature, index, NULL, 0, timeout, 267 NULL); 268} 269 270static inline void usb_request_queue(const usb_protocol_t* usb, usb_request_t* usb_request) { 271 return usb->ops->request_queue(usb->ctx, usb_request); 272} 273 274static inline usb_speed_t usb_get_speed(const usb_protocol_t* usb) { 275 return usb->ops->get_speed(usb->ctx); 276} 277 278static inline zx_status_t usb_set_interface(const usb_protocol_t* usb, uint8_t interface_number, 279 uint8_t alt_setting) { 280 return usb->ops->set_interface(usb->ctx, interface_number, alt_setting); 281} 282 283static inline uint8_t usb_get_configuration(const usb_protocol_t* usb) { 284 return usb->ops->get_configuration(usb->ctx); 285} 286 287static inline zx_status_t usb_set_configuration(const usb_protocol_t* usb, uint8_t configuration) { 288 return usb->ops->set_configuration(usb->ctx, configuration); 289} 290 291static inline zx_status_t usb_enable_endpoint(const usb_protocol_t* usb, 292 usb_endpoint_descriptor_t* ep_desc, 293 usb_ss_ep_comp_descriptor_t* ss_comp_desc, 294 bool enable) { 295 return usb->ops->enable_endpoint(usb->ctx, ep_desc, ss_comp_desc, enable); 296} 297 298// Resets an endpoint that is in a halted or error state. 299// Endpoints will be halted if the device returns a STALL in response to a USB transaction. 300// When that occurs, the transaction will fail with ERR_IO_REFUSED. 301// usb_reset_endpoint() the endpoint to normal running state. 302static inline zx_status_t usb_reset_endpoint(const usb_protocol_t* usb, uint8_t ep_address) { 303 return usb->ops->reset_endpoint(usb->ctx, ep_address); 304} 305 306// returns the maximum amount of data that can be transferred on an endpoint in a single transaction. 307static inline size_t usb_get_max_transfer_size(const usb_protocol_t* usb, uint8_t ep_address) { 308 return usb->ops->get_max_transfer_size(usb->ctx, ep_address); 309} 310 311// Returns the device ID for the device. 312// This ID is generated by and used internally by the USB HCI controller driver. 313static inline uint32_t usb_get_device_id(const usb_protocol_t* usb) { 314 return usb->ops->get_device_id(usb->ctx); 315} 316 317// Returns the device's device descriptor. 318static inline void usb_get_device_descriptor(const usb_protocol_t* usb, 319 usb_device_descriptor_t* out_desc) { 320 usb->ops->get_device_descriptor(usb->ctx, out_desc); 321} 322 323// Returns the configuration descriptor for the given configuration. 324static inline zx_status_t usb_get_configuration_descriptor(const usb_protocol_t* usb, 325 uint8_t configuration, 326 usb_configuration_descriptor_t** out, 327 size_t* out_length) { 328 return usb->ops->get_configuration_descriptor(usb->ctx, configuration, out, out_length); 329} 330 331// returns the USB descriptors for the USB device or interface 332// the returned value is de-allocated with free() 333static inline zx_status_t usb_get_descriptor_list(const usb_protocol_t* usb, void** out_descriptors, 334 size_t* out_length) { 335 return usb->ops->get_descriptor_list(usb->ctx, out_descriptors, out_length); 336} 337 338// Fetch the descriptor using the provided descriptor ID and language ID. If 339// the language ID requested is not available, the first entry of the language 340// ID table will be used instead and be provided in the updated version of the 341// parameter. 342// 343// The string will be encoded using UTF-8, and will be truncated to fit the 344// space provided by the buflen parameter. buflen will be updated to indicate 345// the amount of space needed to hold the actual UTF-8 encoded string lenth, and 346// may be larger than the original value passed. Embedded nulls may be present 347// in the string, and the result may not be null terminated if the string 348// occupies the entire provided buffer. 349// 350static inline zx_status_t usb_get_string_descriptor(const usb_protocol_t* usb, 351 uint8_t desc_id, uint16_t* inout_lang_id, 352 uint8_t* buf, size_t* inout_buflen) { 353 return usb->ops->get_string_descriptor(usb->ctx, desc_id, inout_lang_id, buf, inout_buflen); 354} 355 356static inline zx_status_t usb_cancel_all(const usb_protocol_t* usb, uint8_t ep_address) { 357 return usb->ops->cancel_all(usb->ctx, ep_address); 358} 359 360// returns the current frame (in milliseconds), used for isochronous transfers 361static inline uint64_t usb_get_current_frame(const usb_protocol_t* usb) { 362 return usb->ops->get_current_frame(usb->ctx); 363} 364 365__END_CDECLS; 366