usbs.c
来自「eCos操作系统源码」· C语言 代码 · 共 714 行 · 第 1/3 页
C
714 行
// 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 + =
减小字号Ctrl + -
显示快捷键?