⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
        // 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 + -