| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <ddk/phys-iter.h> |
| #include <ddk/protocol/usb/request.h> |
| #include <sys/types.h> |
| #include <zircon/compiler.h> |
| #include <zircon/types.h> |
| #include <zircon/hw/usb.h> |
| #include <zircon/hw/usb-hub.h> |
| #include <zircon/listnode.h> |
| |
| __BEGIN_CDECLS; |
| |
| typedef void (*usb_request_complete_cb)(usb_request_t* req, void* cookie); |
| |
| // Returns a batch of completed requests for an endpoint. |
| // The client should free the completed_reqs array once they are finished with it. |
| typedef void (*usb_batch_complete_cb)(usb_request_t** completed_reqs, size_t num_completed, |
| void* cookie); |
| |
| typedef struct { |
| zx_status_t (*control)(void* ctx, uint8_t request_type, uint8_t request, uint16_t value, |
| uint16_t index, void* data, size_t length, zx_time_t timeout, |
| size_t* out_length); |
| // queues a USB request |
| void (*request_queue)(void* ctx, usb_request_t* usb_request, usb_request_complete_cb, |
| void* cookie); |
| |
| zx_status_t (*configure_batch_callback)(void* ctx, uint8_t ep_address, |
| usb_batch_complete_cb cb, void* cookie); |
| |
| usb_speed_t (*get_speed)(void* ctx); |
| zx_status_t (*set_interface)(void* ctx, uint8_t interface_number, uint8_t alt_setting); |
| uint8_t (*get_configuration)(void* ctx); |
| zx_status_t (*set_configuration)(void* ctx, uint8_t configuration); |
| zx_status_t (*enable_endpoint)(void* ctx, usb_endpoint_descriptor_t* ep_desc, |
| usb_ss_ep_comp_descriptor_t* ss_comp_desc, bool enable); |
| zx_status_t (*reset_endpoint)(void* ctx, uint8_t ep_address); |
| size_t (*get_max_transfer_size)(void* ctx, uint8_t ep_address); |
| uint32_t (*get_device_id)(void* ctx); |
| void (*get_device_descriptor)(void* ctx, usb_device_descriptor_t* out_desc); |
| zx_status_t (*get_configuration_descriptor)(void* ctx, uint8_t configuration, |
| usb_configuration_descriptor_t** out, |
| size_t* out_length); |
| zx_status_t (*get_descriptor_list)(void* ctx, void** out_descriptors, size_t* out_length); |
| zx_status_t (*get_string_descriptor)(void* ctx, uint8_t desc_id, uint16_t lang_id, |
| uint8_t* buf, size_t buflen, size_t* out_actual, |
| uint16_t* out_actual_lang_id); |
| zx_status_t (*cancel_all)(void* ctx, uint8_t ep_address); |
| uint64_t (*get_current_frame)(void* ctx); |
| size_t (*get_request_size)(void* ctx); |
| } usb_protocol_ops_t; |
| |
| typedef struct usb_protocol { |
| usb_protocol_ops_t* ops; |
| void* ctx; |
| } usb_protocol_t; |
| |
| // synchronously executes a control request on endpoint zero |
| static inline zx_status_t usb_control(const usb_protocol_t* usb, uint8_t request_type, |
| uint8_t request, uint16_t value, uint16_t index, void* data, |
| size_t length, zx_time_t timeout, size_t* out_length) { |
| return usb->ops->control(usb->ctx, request_type, request, value, index, data, length, timeout, |
| out_length); |
| } |
| |
| static inline zx_status_t usb_get_descriptor(const usb_protocol_t* usb, uint8_t request_type, |
| uint16_t type, uint16_t index, void* data, |
| size_t length, zx_time_t timeout, size_t* out_length) { |
| return usb_control(usb, request_type | USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, |
| (uint16_t)(type << 8 | index), 0, data, length, timeout, out_length); |
| } |
| |
| static inline zx_status_t usb_get_status(const usb_protocol_t* usb, uint8_t request_type, |
| uint16_t index, void* data, size_t length, |
| zx_time_t timeout, size_t* out_length) { |
| return usb_control(usb, request_type | USB_DIR_IN, USB_REQ_GET_STATUS, 0, index, data, length, |
| timeout, out_length); |
| } |
| |
| static inline zx_status_t usb_set_feature(const usb_protocol_t* usb, uint8_t request_type, |
| uint16_t feature, uint16_t index, zx_time_t timeout) { |
| return usb_control(usb, request_type, USB_REQ_SET_FEATURE, feature, index, NULL, 0, timeout, |
| NULL); |
| } |
| |
| static inline zx_status_t usb_clear_feature(const usb_protocol_t* usb, uint8_t request_type, |
| uint16_t feature, uint16_t index, zx_time_t timeout) { |
| return usb_control(usb, request_type, USB_REQ_CLEAR_FEATURE, feature, index, NULL, 0, timeout, |
| NULL); |
| } |
| |
| static inline void usb_request_queue(const usb_protocol_t* usb, usb_request_t* usb_request, |
| usb_request_complete_cb cb, void* cookie) { |
| return usb->ops->request_queue(usb->ctx, usb_request, cb, cookie); |
| } |
| |
| // Configures an endpoint to batch multiple requests to a single callback. |
| // Requests will receive a callback if they have set require_batch_cb to true, or an error occurs. |
| // ep_address: the endpoint which requests will be queued on. |
| // complete_cb: callback for the batch of completed requests. |
| // cookie: user data passed to the |complete_cb|. |
| static inline zx_status_t usb_configure_batch_callback(const usb_protocol_t* usb, |
| uint8_t ep_address, |
| usb_batch_complete_cb complete_cb, |
| void* cookie) { |
| return usb->ops->configure_batch_callback(usb->ctx, ep_address, complete_cb, cookie); |
| } |
| |
| static inline usb_speed_t usb_get_speed(const usb_protocol_t* usb) { |
| return usb->ops->get_speed(usb->ctx); |
| } |
| |
| static inline zx_status_t usb_set_interface(const usb_protocol_t* usb, uint8_t interface_number, |
| uint8_t alt_setting) { |
| return usb->ops->set_interface(usb->ctx, interface_number, alt_setting); |
| } |
| |
| static inline uint8_t usb_get_configuration(const usb_protocol_t* usb) { |
| return usb->ops->get_configuration(usb->ctx); |
| } |
| |
| static inline zx_status_t usb_set_configuration(const usb_protocol_t* usb, uint8_t configuration) { |
| return usb->ops->set_configuration(usb->ctx, configuration); |
| } |
| |
| static inline zx_status_t usb_enable_endpoint(const usb_protocol_t* usb, |
| usb_endpoint_descriptor_t* ep_desc, |
| usb_ss_ep_comp_descriptor_t* ss_comp_desc, |
| bool enable) { |
| return usb->ops->enable_endpoint(usb->ctx, ep_desc, ss_comp_desc, enable); |
| } |
| |
| // Resets an endpoint that is in a halted or error state. |
| // Endpoints will be halted if the device returns a STALL in response to a USB transaction. |
| // When that occurs, the transaction will fail with ERR_IO_REFUSED. |
| // usb_reset_endpoint() the endpoint to normal running state. |
| static inline zx_status_t usb_reset_endpoint(const usb_protocol_t* usb, uint8_t ep_address) { |
| return usb->ops->reset_endpoint(usb->ctx, ep_address); |
| } |
| |
| // returns the maximum amount of data that can be transferred on an endpoint in a single transaction. |
| static inline size_t usb_get_max_transfer_size(const usb_protocol_t* usb, uint8_t ep_address) { |
| return usb->ops->get_max_transfer_size(usb->ctx, ep_address); |
| } |
| |
| // Returns the device ID for the device. |
| // This ID is generated by and used internally by the USB HCI controller driver. |
| static inline uint32_t usb_get_device_id(const usb_protocol_t* usb) { |
| return usb->ops->get_device_id(usb->ctx); |
| } |
| |
| // Returns the device's device descriptor. |
| static inline void usb_get_device_descriptor(const usb_protocol_t* usb, |
| usb_device_descriptor_t* out_desc) { |
| usb->ops->get_device_descriptor(usb->ctx, out_desc); |
| } |
| |
| // Returns the configuration descriptor for the given configuration. |
| static inline zx_status_t usb_get_configuration_descriptor(const usb_protocol_t* usb, |
| uint8_t configuration, |
| usb_configuration_descriptor_t** out, |
| size_t* out_length) { |
| return usb->ops->get_configuration_descriptor(usb->ctx, configuration, out, out_length); |
| } |
| |
| // returns the USB descriptors for the USB device or interface |
| // the returned value is de-allocated with free() |
| static inline zx_status_t usb_get_descriptor_list(const usb_protocol_t* usb, void** out_descriptors, |
| size_t* out_length) { |
| return usb->ops->get_descriptor_list(usb->ctx, out_descriptors, out_length); |
| } |
| |
| // Fetch the descriptor using the provided descriptor ID and language ID. If |
| // the language ID requested is not available, the first entry of the language |
| // ID table will be used instead and be provided in the updated version of the |
| // parameter. |
| // |
| // The string will be encoded using UTF-8, and will be truncated to fit the |
| // space provided by the buflen parameter. Embedded nulls may be present |
| // in the string, and the result may not be null terminated if the string |
| // occupies the entire provided buffer. |
| // |
| static inline zx_status_t usb_get_string_descriptor(const usb_protocol_t* usb, uint8_t desc_id, |
| uint16_t lang_id, uint8_t* buf, size_t buflen, |
| size_t* out_actual, |
| uint16_t* out_actual_lang_id) { |
| return usb->ops->get_string_descriptor(usb->ctx, desc_id, lang_id, buf, buflen, out_actual, |
| out_actual_lang_id); |
| } |
| |
| static inline zx_status_t usb_cancel_all(const usb_protocol_t* usb, uint8_t ep_address) { |
| return usb->ops->cancel_all(usb->ctx, ep_address); |
| } |
| |
| // returns the current frame (in milliseconds), used for isochronous transfers |
| static inline uint64_t usb_get_current_frame(const usb_protocol_t* usb) { |
| return usb->ops->get_current_frame(usb->ctx); |
| } |
| |
| // return the internal context size plus parents request size |
| static inline uint64_t usb_get_request_size(const usb_protocol_t* usb) { |
| return usb->ops->get_request_size(usb->ctx); |
| } |
| __END_CDECLS; |