📄 usbs.c
字号:
endpoint->complete_fn = callback_fn;
endpoint->complete_data = callback_arg;
(*endpoint->start_tx_fn)(endpoint);
}
void
usbs_start(usbs_control_endpoint* endpoint)
{
CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
CYG_CHECK_FUNC_PTR( endpoint->start_fn, "The USB endpoint should have a start function");
(*endpoint->start_fn)(endpoint);
}
cyg_bool
usbs_rx_endpoint_halted(usbs_rx_endpoint* endpoint)
{
CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
return endpoint->halted;
}
cyg_bool
usbs_tx_endpoint_halted(usbs_tx_endpoint* endpoint)
{
CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
return endpoint->halted;
}
void
usbs_set_rx_endpoint_halted(usbs_rx_endpoint* endpoint, cyg_bool halted)
{
CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
(*endpoint->set_halted_fn)(endpoint, halted);
}
void
usbs_set_tx_endpoint_halted(usbs_tx_endpoint* endpoint, cyg_bool halted)
{
CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
(*endpoint->set_halted_fn)(endpoint, halted);
}
void
usbs_start_rx_endpoint_wait(usbs_rx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
{
endpoint->buffer = (unsigned char*) 0;
endpoint->buffer_size = 0;
endpoint->complete_fn = callback_fn;
endpoint->complete_data = callback_data;
(*endpoint->start_rx_fn)(endpoint);
}
void
usbs_start_tx_endpoint_wait(usbs_tx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
{
endpoint->buffer = (unsigned char*) 0;
endpoint->buffer_size = 0;
endpoint->complete_fn = callback_fn;
endpoint->complete_data = callback_data;
(*endpoint->start_tx_fn)(endpoint);
}
// ----------------------------------------------------------------------------
// Handling of standard control messages. This will be invoked by
// a USB device driver, usually at DSR level, to process any control
// messages that cannot be handled by the hardware itself and that
// have also not been handled by the application-specific handler
// (if any).
//
// Because this function can run at DSR level performance is important.
//
// The various standard control messages are affected as follows:
//
// clear-feature: nothing can be done here about device requests to
// disable remote-wakeup or about endpoint halt requests. It appears
// to be legal to clear no features on an interface.
//
// get-configuration: if the device is not configured a single byte 0
// should be returned. Otherwise this code assumes only one configuration
// is supported and its id can be extracted from the enumeration data.
// For more complicated devices get-configuration has to be handled
// at a higher-level.
//
// get-descriptor: this is the big one. It is used to obtain
// the enumeration data. An auxiliary refill function is needed.
//
// get-interface: this can be used to identify the current variant
// for a given interface within a configuration. For simple devices
// there will be only interface, 0. For anything more complicated
// higher level code will have to take care of the request.
//
// get-status. Much the same as clear-feature.
//
// set-address. Must be handled at the device driver level.
//
// set-configuration: a value of 0 is used to deconfigure the device,
// which can be handled here. Otherwise this code assumes that only
// a single configuration is supported and enables that. For anything
// more complicated higher-level code has to handle this request.
//
// set-descriptor: used to update the enumeration data. This is not
// supported here, although higher-level code can choose to do so.
//
// set-feature. See clear-feature and get-status.
//
// set-interface. Variant interfaces are not supported by the
// base code so this request has to be handled at a higher level.
//
// synch-frame. This is only relevant for isochronous transfers
// which are not yet supported, and anyway it is not clear what
// could be done about these requests here.
// This refill function handles GET_DESCRIPTOR requests for a
// configuration. For details of the control_buffer usage see
// the relevant code in the main callback.
static void
usbs_configuration_descriptor_refill(usbs_control_endpoint* endpoint)
{
usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
int length = (req->length_hi << 8) | req->length_lo;
int sent = (req->index_hi << 8) | req->index_lo;
int current_interface = req->type;
int last_interface = req->request;
int current_endpoint = req->value_lo;
int last_endpoint = req->value_hi;
cyg_bool done = false;
if (current_endpoint == last_endpoint) {
// The next transfer should be a single interface - unless we have already finished.
if (current_interface == last_interface) {
done = true;
} else {
endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->interfaces[current_interface]);
if (USB_INTERFACE_DESCRIPTOR_LENGTH >= (length - sent)) {
endpoint->buffer_size = length - sent;
done = true;
} else {
endpoint->buffer_size = USB_INTERFACE_DESCRIPTOR_LENGTH;
sent += USB_INTERFACE_DESCRIPTOR_LENGTH;
// Note that an interface with zero endpoints is ok. We'll just move
// to the next interface in the next call.
last_endpoint = current_endpoint +
endpoint->enumeration_data->interfaces[current_interface].number_endpoints;
current_interface++;
}
}
} else {
// The next transfer should be a single endpoint. The
// endpoints are actually contiguous array elements
// but may not be packed, so they have to be transferred
// one at a time.
endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->endpoints[current_endpoint]);
if ((sent + USB_ENDPOINT_DESCRIPTOR_LENGTH) >= length) {
endpoint->buffer_size = length - sent;
done = true;
} else {
endpoint->buffer_size = USB_ENDPOINT_DESCRIPTOR_LENGTH;
current_endpoint ++;
}
}
if (done) {
endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
} else {
req->type = (unsigned char) current_interface;
req->value_lo = (unsigned char) current_endpoint;
req->value_hi = (unsigned char) last_endpoint;
req->index_hi = (unsigned char) (sent >> 8);
req->index_lo = (unsigned char) (sent & 0x00FF);
}
}
usbs_control_return
usbs_handle_standard_control(usbs_control_endpoint* endpoint)
{
usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
int length;
int direction;
int recipient;
length = (req->length_hi << 8) | req->length_lo;
direction = req->type & USB_DEVREQ_DIRECTION_MASK;
recipient = req->type & USB_DEVREQ_RECIPIENT_MASK;
if (USB_DEVREQ_CLEAR_FEATURE == req->request) {
if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
// The host should expect no data back, the device must
// be configured, and there are no defined features to clear.
if ((0 == length) &&
(USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
(0 == req->value_lo)) {
int interface_id = req->index_lo;
CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
"Higher level code should have handled this request");
if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
result = USBS_CONTROL_RETURN_HANDLED;
} else {
result = USBS_CONTROL_RETURN_STALL;
}
} else {
result = USBS_CONTROL_RETURN_STALL;
}
}
} else if (USB_DEVREQ_GET_CONFIGURATION == req->request) {
// Return a single byte 0 if the device is not currently
// configured. Otherwise assume a single configuration
// in the enumeration data and return its id.
if ((1 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
if (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) {
CYG_ASSERT( 1 == endpoint->enumeration_data->device.number_configurations, \
"Higher level code should have handled this request");
endpoint->control_buffer[0] = endpoint->enumeration_data->configurations[0].configuration_id;
} else {
endpoint->control_buffer[0] = 0;
}
endpoint->buffer = endpoint->control_buffer;
endpoint->buffer_size = 1;
endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
result = USBS_CONTROL_RETURN_HANDLED;
} else {
result = USBS_CONTROL_RETURN_STALL;
}
} else if (USB_DEVREQ_GET_DESCRIPTOR == req->request) {
// The descriptor type is in value_hi. The descriptor index
// is in value_lo.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -