📄 usbs.c
字号:
// The hsot must expect at least one byte of data.
if ((0 == length) || (USB_DEVREQ_DIRECTION_IN != direction)) {
result = USBS_CONTROL_RETURN_STALL;
} else if (USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE == req->value_hi) {
// The device descriptor is easy, it is a single field in the
// enumeration data.
endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->device);
endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
if (length < USB_DEVICE_DESCRIPTOR_LENGTH) {
endpoint->buffer_size = length;
} else {
endpoint->buffer_size = USB_DEVICE_DESCRIPTOR_LENGTH;
}
result = USBS_CONTROL_RETURN_HANDLED;
} else if (USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION == req->value_hi) {
// This is where things get messy. We need to supply the
// specified configuration data, followed by some number of
// interfaces and endpoints. Plus there are length limits
// to consider. First check that the specified index is valid.
if (req->value_lo >= endpoint->enumeration_data->device.number_configurations) {
result = USBS_CONTROL_RETURN_STALL;
} else {
// No such luck. OK, supplying the initial block is easy.
endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->configurations[req->value_lo]);
endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
// How much data was actually requested. If only the
// configuration itself is of interest then there is
// no need to worry about the rest.
if (length <= USB_CONFIGURATION_DESCRIPTOR_LENGTH) {
endpoint->buffer_size = length;
endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
} else {
int i, j;
int start_interface;
int start_endpoint;
endpoint->buffer_size = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
endpoint->fill_buffer_fn = &usbs_configuration_descriptor_refill;
// The descriptor refill_fn needs to know what next to transfer.
// The desired interfaces and endpoints will be contiguous so
// we need to keep track of the following:
// 1) the current interface index being transferred.
// 2) the last interface that should be transferred.
// 3) the current endpoint index that should be transferred.
// 4) the last endpoint index. This marks interface/endpoint transitions.
// 5) how much has been transferred to date.
// This information can be held in the control_buffer,
// with the length field being preserved.
start_interface = 0;
start_endpoint = 0;
// For all configurations up to the desired one.
for (i = 0; i < req->value_lo; i++) {
int config_interfaces = endpoint->enumeration_data->configurations[i].number_interfaces;
// For all interfaces in this configuration.
for (j = 0; j < config_interfaces; j++) {
// Add the number of endpoints in this interface to the current count.
CYG_ASSERT( (j + start_interface) < endpoint->enumeration_data->total_number_interfaces, \
"Valid interface count in enumeration data");
start_endpoint += endpoint->enumeration_data->interfaces[j + start_interface].number_endpoints;
}
// And update the index for the starting interface.
start_interface += config_interfaces;
}
CYG_ASSERT( start_interface < endpoint->enumeration_data->total_number_interfaces, \
"Valid interface count in enumeration data");
CYG_ASSERT( ((0 == endpoint->enumeration_data->total_number_endpoints) && (0 == start_endpoint)) || \
(start_endpoint < endpoint->enumeration_data->total_number_endpoints), \
"Valid endpoint count in enumeration data");
req->type = (unsigned char) start_interface;
req->request = (unsigned char) (start_interface +
endpoint->enumeration_data->configurations[req->value_lo].number_interfaces
);
req->value_lo = (unsigned char) start_endpoint;
req->value_hi = (unsigned char) start_endpoint;
req->index_lo = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
req->index_hi = 0;
}
result = USBS_CONTROL_RETURN_HANDLED;
}
} else if (USB_DEVREQ_DESCRIPTOR_TYPE_STRING == req->value_hi) {
// As long as the index is valid, the rest is easy since
// the strings are just held in a simple array.
// NOTE: if multiple languages have to be supported
// then things get more difficult.
if (req->value_lo >= endpoint->enumeration_data->total_number_strings) {
result = USBS_CONTROL_RETURN_STALL;
} else {
endpoint->buffer = (unsigned char*) endpoint->enumeration_data->strings[req->value_lo];
endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
if (length < endpoint->buffer[0]) {
endpoint->buffer_size = length;
} else {
endpoint->buffer_size = endpoint->buffer[0];
}
result = USBS_CONTROL_RETURN_HANDLED;
}
} else {
result = USBS_CONTROL_RETURN_STALL;
}
} else if (USB_DEVREQ_GET_INTERFACE == req->request) {
if ((1 != length) ||
(USB_DEVREQ_DIRECTION_IN != direction) ||
(USBS_STATE_CONFIGURED != (endpoint->state & USBS_STATE_MASK))) {
result = USBS_CONTROL_RETURN_STALL;
} else {
int interface_id;
CYG_ASSERT( (1 == endpoint->enumeration_data->device.number_configurations) && \
(1 == endpoint->enumeration_data->total_number_interfaces), \
"Higher level code should have handled this request");
interface_id = (req->index_hi << 8) | req->index_lo;
if (interface_id != endpoint->enumeration_data->interfaces[0].interface_id) {
result = USBS_CONTROL_RETURN_STALL;
} else {
endpoint->control_buffer[0] = endpoint->enumeration_data->interfaces[0].alternate_setting;
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 if (USB_DEVREQ_GET_STATUS == req->request) {
if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
// The host should expect two bytes back, the device must
// be configured, the interface number must be valid.
// The host should expect no data back, the device must
// be configured, and there are no defined features to clear.
if ((2 == length) &&
(USB_DEVREQ_DIRECTION_IN == direction) &&
(USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK))) {
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) {
// The request is legit, but there are no defined features for an interface...
endpoint->control_buffer[0] = 0;
endpoint->control_buffer[1] = 0;
endpoint->buffer = endpoint->control_buffer;
endpoint->buffer_size = 2;
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 {
result = USBS_CONTROL_RETURN_STALL;
}
}
} else if (USB_DEVREQ_SET_CONFIGURATION == req->request) {
// Changing to configuration 0 means a state change from
// configured to addressed. Changing to anything else means a
// state change to configured. Both involve invoking the
// state change callback. If there are multiple configurations
// to choose from then this request has to be handled at
// a higher level.
int old_state = endpoint->state;
if (0 == req->value_lo) {
endpoint->state = USBS_STATE_ADDRESSED;
if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
(*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
USBS_STATE_CHANGE_DECONFIGURED, old_state);
}
result = USBS_CONTROL_RETURN_HANDLED;
} else {
CYG_ASSERT(1 == endpoint->enumeration_data->device.number_configurations, \
"Higher level code should have handled this request");
if (req->value_lo == endpoint->enumeration_data->configurations[0].configuration_id) {
endpoint->state = USBS_STATE_CONFIGURED;
if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
(*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
USBS_STATE_CHANGE_CONFIGURED, old_state);
}
result = USBS_CONTROL_RETURN_HANDLED;
} else {
result = USBS_CONTROL_RETURN_STALL;
}
}
} else if (USB_DEVREQ_SET_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;
}
}
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -