static usb_request_status_t usb_standard_request_get_descriptor_setup( usb_endpoint_t* const endpoint ) { switch( endpoint->setup.value_h ) { case USB_DESCRIPTOR_TYPE_DEVICE: return usb_send_descriptor(endpoint, endpoint->device->descriptor); case USB_DESCRIPTOR_TYPE_CONFIGURATION: // TODO: Duplicated code. Refactor. if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) { return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l); } else { return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l); } case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: return usb_send_descriptor(endpoint, endpoint->device->qualifier_descriptor); case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: // TODO: Duplicated code. Refactor. if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) { return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l); } else { return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l); } case USB_DESCRIPTOR_TYPE_STRING: return usb_send_descriptor_string(endpoint); case USB_DESCRIPTOR_TYPE_INTERFACE: case USB_DESCRIPTOR_TYPE_ENDPOINT: default: return USB_REQUEST_STATUS_STALL; } }
static void usb_setup_get_descriptor(int type, int index, int lang, int len) { (void)lang; usb_data_stage_enable(DIR_TX); switch (type) { case 1: if (index == 0) usb_send_descriptor(device_descriptor, sizeof(device_descriptor), len); else usb_request_error(); break; case 2: if (index == 0) usb_send_descriptor(cfg_descriptor, sizeof(cfg_descriptor), len); else usb_request_error(); break; case 3: if (index == 0) usb_send_descriptor(lang_descriptor, sizeof(lang_descriptor), len); else if (index <= N_STRING_DESCRIPTORS) usb_send_descriptor(string_descriptor[index - 1], string_descriptor[index - 1][0], len); else usb_request_error(); break; default: usb_request_error(); } }
static usb_request_status_t usb_send_descriptor_string( usb_endpoint_t* const endpoint ) { if ((endpoint->setup.value_l == 0xee) && (endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */ return usb_send_descriptor(endpoint, endpoint->device->wcid_string_descriptor); } else { uint_fast8_t index = endpoint->setup.value_l; for( uint_fast8_t i=0; endpoint->device->descriptor_strings[i] != 0; i++ ) { if( i == index ) { return usb_send_descriptor(endpoint, endpoint->device->descriptor_strings[i]); } } } return USB_REQUEST_STATUS_STALL; }
usb_request_status_t usb_vendor_request_read_wcid( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage ) { if( stage == USB_TRANSFER_STAGE_SETUP ) { if ((endpoint->setup.index == 0x04) && (endpoint->device->wcid_feature_descriptor != NULL)) { usb_send_descriptor(endpoint, endpoint->device->wcid_feature_descriptor); return USB_REQUEST_STATUS_OK; } if ((endpoint->setup.index == 0x05) && (endpoint->device->wcid_extended_properties_descriptor != NULL)) { usb_send_descriptor(endpoint, endpoint->device->wcid_extended_properties_descriptor); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; } return USB_REQUEST_STATUS_OK; }
static usb_request_status_t usb_send_descriptor_string( usb_endpoint_t* const endpoint ) { uint_fast8_t index = endpoint->setup.value_l; for( uint_fast8_t i=0; usb_descriptor_strings[i] != 0; i++ ) { if( i == index ) { return usb_send_descriptor(endpoint, usb_descriptor_strings[i]); } } return USB_REQUEST_STATUS_STALL; }
static usb_request_status_t usb_send_descriptor_config( usb_endpoint_t* const endpoint, usb_speed_t speed, const uint8_t config_num ) { usb_configuration_t** config = *(endpoint->device->configurations); unsigned int i = 0; for( ; *config != NULL; config++ ) { if( (*config)->speed == speed) { if (i == config_num) { return usb_send_descriptor(endpoint, (*config)->descriptor); } else { i++; } } } return USB_REQUEST_STATUS_STALL; }
void usb_handle_StandardDeviceRequest(BDentry *bdp) { unsigned char *packet = bdp->BDADDR; int i; switch (packet[USB_bRequest]) { case USB_REQUEST_GET_STATUS: rbdp->BDADDR[0] = usb_device_status & 0xFF; rbdp->BDADDR[1] = usb_device_status >> 8; // JTR I added usb_ack_dat1() simply so that the handling // of STANDARD and CLASS requests (in cdc.c) were consistant // rather than have the same thing done in two different ways. usb_ack_dat1(rbdp, 2); // JTR common addition for STD and CLASS ACK break; case USB_REQUEST_CLEAR_FEATURE: if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE) usb_device_status &= ~0x0002; usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK } else usb_RequestError(); break; case USB_REQUEST_SET_FEATURE: if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE) usb_device_status |= 0x0002; usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK } else usb_RequestError(); break; case USB_REQUEST_SET_ADDRESS: if (0x00u == packet[USB_wValueHigh] && 0x7Fu >= packet[USB_wValue]) { usb_addr_pending = packet[USB_wValue]; usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK usb_set_in_handler(0, usb_set_address); } else usb_RequestError(); break; case USB_REQUEST_GET_DESCRIPTOR: switch (packet[USB_bDescriptorType]) { case USB_DEVICE_DESCRIPTOR_TYPE: usb_desc_ptr = usb_device_descriptor; usb_desc_len = usb_device_descriptor[0]; if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_desc_ptr[0])) usb_desc_len = packet[USB_wLength]; break; case USB_CONFIGURATION_DESCRIPTOR_TYPE: if (packet[USB_bDescriptorIndex] >= usb_device_descriptor[17]) // TODO: remove magic usb_RequestError(); usb_desc_ptr = usb_config_descriptor; usb_desc_len = usb_desc_ptr[2] + usb_desc_ptr[3] * 256; for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration usb_desc_ptr += usb_desc_len; usb_desc_len = usb_desc_ptr[2] + usb_desc_ptr[3] * 256; } if ((packet[USB_wLengthHigh] < usb_desc_ptr[3]) || (packet[USB_wLengthHigh] == usb_desc_ptr[3] && packet[USB_wLength] < usb_desc_ptr[2])) usb_desc_len = packet[USB_wLength] + packet[USB_wLengthHigh] * 256; break; case USB_STRING_DESCRIPTOR_TYPE: // TODO: Handle language request. For now return standard language. if (packet[USB_bDescriptorIndex] >= usb_num_string_descriptors) usb_RequestError(); usb_desc_ptr = usb_string_descriptor; usb_desc_len = usb_desc_ptr[0]; for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration usb_desc_ptr += usb_desc_len; usb_desc_len = usb_desc_ptr[0]; } if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_desc_ptr[0])) usb_desc_len = packet[USB_wLength]; break; case USB_INTERFACE_DESCRIPTOR_TYPE: case USB_ENDPOINT_DESCRIPTOR_TYPE: default: usb_RequestError(); } usb_send_descriptor(); // Send first part of packet right away usb_set_in_handler(0, usb_send_descriptor); break; case USB_REQUEST_GET_CONFIGURATION: rbdp->BDADDR[0] = usb_current_cfg; usb_ack_dat1(rbdp, 1); // JTR common addition for STD and CLASS ACK // rbdp->BDCNT = 1; // rbdp->BDSTAT = UOWN + DTS + DTSEN; break; case USB_REQUEST_SET_CONFIGURATION: if (USB_NUM_CONFIGURATIONS >= packet[USB_wValue]) { // TODO: Support multiple configurations /* Configure endpoints (USB_UEPn - registers) */ usb_current_cfg = packet[USB_wValue]; if (usb_current_cfg != 0) { // JTR user_configured_init major addition. This is a CALLBACK to the USER when the device is enumerated. // This is when we setup non EP0 endpoints. // TODO: This really could be a function pointer usb_device_state = CONFIGURED_STATE; user_configured_init(); } else { usb_device_state = ADDRESS_STATE; } usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK } else usb_RequestError(); break; case USB_REQUEST_SET_DESCRIPTOR: default: usb_RequestError(); } }