blob: 54d2491c48e809f5149551904848865155d66eee [file] [log] [blame]
// 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 struct usb_request usb_request_t;
// cache maintenance ops
#define USB_REQUEST_CACHE_INVALIDATE ZX_VMO_OP_CACHE_INVALIDATE
#define USB_REQUEST_CACHE_CLEAN ZX_VMO_OP_CACHE_CLEAN
#define USB_REQUEST_CACHE_CLEAN_INVALIDATE ZX_VMO_OP_CACHE_CLEAN_INVALIDATE
#define USB_REQUEST_CACHE_SYNC ZX_VMO_OP_CACHE_SYNC
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;