//! This function manages the HID Get_Descriptor request. //! static void hid_get_descriptor(U8 size_of_report, const U8* p_usb_hid_report) { bool zlp; U16 wIndex; U16 wLength; zlp = false; /* no zero length packet */ data_to_transfer = size_of_report; pbuffer = p_usb_hid_report; wIndex = Usb_read_endpoint_data(EP_CONTROL, 16); wIndex = usb_format_usb_to_mcu_data(16, wIndex); wLength = Usb_read_endpoint_data(EP_CONTROL, 16); wLength = usb_format_usb_to_mcu_data(16, wLength); Usb_ack_setup_received_free(); //!< clear the setup received flag if (wLength > data_to_transfer) { zlp = !(data_to_transfer % EP_CONTROL_LENGTH); //!< zero length packet condition } else { data_to_transfer = wLength; //!< send only requested number of data bytes } Usb_ack_nak_out(EP_CONTROL); while (data_to_transfer && (!Is_usb_nak_out(EP_CONTROL))) { while( !Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL) ); if( Is_usb_nak_out(EP_CONTROL) ) break; // don't clear the flag now, it will be cleared after Usb_reset_endpoint_fifo_access(EP_CONTROL); data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer, data_to_transfer, &pbuffer); if( Is_usb_nak_out(EP_CONTROL) ) break; else Usb_ack_control_in_ready_send(); //!< Send data until necessary } if ( zlp && (!Is_usb_nak_out(EP_CONTROL)) ) { while (!Is_usb_control_in_ready()); Usb_ack_control_in_ready_send(); } while (!(Is_usb_nak_out(EP_CONTROL))); Usb_ack_nak_out(EP_CONTROL); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }
//! //! @brief USB Command Block Wrapper (CBW) management //! //! This function decodes the CBW command and stores the SCSI command. //! static void usb_mass_storage_cbw(void) { bool cbw_error; Usb_reset_endpoint_fifo_access(EP_MS_OUT); //! Check if dCBWSignature is correct cbw_error = (Usb_read_endpoint_data(EP_MS_OUT, 32) != *(U32 *)&"USBC"); //! Store CBW Tag to be repeated in CSW dCBWTag = Usb_read_endpoint_data(EP_MS_OUT, 32); g_scsi_data_remaining = Usb_read_endpoint_data(EP_MS_OUT, 32); g_scsi_data_remaining = usb_format_usb_to_mcu_data(32, g_scsi_data_remaining); //! if (bmCBWFlags.bit7 == 1) {direction = IN;} if (Usb_read_endpoint_data(EP_MS_OUT, 8)) { ms_endpoint = EP_MS_IN; if (cbw_error) { Usb_ack_out_received_free(EP_MS_OUT); Usb_enable_stall_handshake(EP_MS_IN); return; } } else { ms_endpoint = EP_MS_OUT; if (cbw_error) { Usb_enable_stall_handshake(EP_MS_OUT); Usb_ack_out_received_free(EP_MS_OUT); return; } } usb_LUN = Usb_read_endpoint_data(EP_MS_OUT, 8); if (!ms_multiple_drive) { usb_LUN = get_cur_lun(); } //! Dummy CBWCBLength read Usb_read_endpoint_data(EP_MS_OUT, 8); //! Store scsi_command usb_read_ep_rxpacket(EP_MS_OUT, g_scsi_command, sizeof(g_scsi_command), NULL); Usb_ack_out_received_free(EP_MS_OUT); // Take the USB Mutex(i.e. we're allowed to perform a ms cmd). /* if( ( pdFALSE == ( xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) ) || ( !scsi_decode_command() && g_scsi_data_remaining ) ) */ if( ( pdFALSE == (xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) ) || ( !scsi_decode_command() && g_scsi_data_remaining ) ) { Usb_enable_stall_handshake(ms_endpoint); } }
// ! // ! @brief USB Command Block Wrapper (CBW) management // ! // ! This function decodes the CBW command and stores the SCSI command. // ! static void usb_mass_storage_cbw (void) { Bool cbw_error; Usb_reset_endpoint_fifo_access (EP_MS_OUT); // ! Check if dCBWSignature is correct cbw_error = (Usb_read_endpoint_data (EP_MS_OUT, 32) != *(U32 *) & "USBC"); // ! Store CBW Tag to be repeated in CSW dCBWTag = Usb_read_endpoint_data (EP_MS_OUT, 32); g_scsi_data_remaining = Usb_read_endpoint_data (EP_MS_OUT, 32); g_scsi_data_remaining = usb_format_usb_to_mcu_data (32, g_scsi_data_remaining); /* Show the remaining bytes { U8 Text_u8[20]; CI_StringOut (" - "); itoa ((S32)g_scsi_data_remaining,Text_u8); CI_StringOut (Text_u8); CI_StringOut (" - "); } */ // ! if (bmCBWFlags.bit7 == 1) {direction = IN;} if (Usb_read_endpoint_data (EP_MS_OUT, 8)) { ms_endpoint = EP_MS_IN; if (cbw_error) { Usb_ack_out_received_free (EP_MS_OUT); Usb_enable_stall_handshake (EP_MS_IN); return; } } else { ms_endpoint = EP_MS_OUT; if (cbw_error) { Usb_enable_stall_handshake (EP_MS_OUT); Usb_ack_out_received_free (EP_MS_OUT); return; } } usb_LUN = Usb_read_endpoint_data (EP_MS_OUT, 8); if (!ms_multiple_drive) { usb_LUN = get_cur_lun (); } // ! Dummy CBWCBLength read Usb_read_endpoint_data (EP_MS_OUT, 8); // ! Store scsi_command usb_read_ep_rxpacket (EP_MS_OUT, g_scsi_command, sizeof (g_scsi_command), NULL); Usb_ack_out_received_free (EP_MS_OUT); if (!scsi_decode_command ()) { Usb_enable_stall_handshake (ms_endpoint); } }
//! @brief This function manages hid get idle request. //! //! @param u8_report_id 0 the idle rate applies to all input reports, else only applies to the Report ID //! static void usb_hid_get_idle (uint8_t u8_report_id) { uint16_t wLength; uint16_t wInterface; // Get interface number to put in idle mode wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); wLength =usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); Usb_ack_setup_received_free(); if( (wLength != 0) && (wInterface == INTERFACE_NB_KBD) ) { Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, g_u8_report_rate); Usb_ack_control_in_ready_send(); } while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }
//! This function manages the SETUP_GET_INTERFACE request. //! bool usb_get_interface (void) { U16 wInterface; U16 wValue; // Read wValue wValue = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); // wValue = Alternate Setting // wIndex = Interface wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); if(0!=wValue) return false; Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, usb_interface_status[wInterface] ); Usb_ack_control_in_ready_send(); while( !Is_usb_control_out_received() ); Usb_ack_control_out_received_free(); return true; }
static void usb_hid_set_idle (uint8_t u8_report_id, uint8_t u8_duration ) { uint16_t wInterface; // Get interface number to put in idle mode wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); Usb_ack_setup_received_free(); if( wInterface == INTERFACE_NB_KBD ) g_u8_report_rate = u8_duration; Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); }
//! This function checks if the VID and the PID are supported //! (if the VID & PID belong to the VID_PID table). //! //! @return bool: Status //! bool host_check_VID_PID(void) { uint8_t c, d; // Rebuild VID & PID from data stage device_VID = usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_VID)); device_PID = usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_PID)); // Look for received VID & PID in supported table for (c = 0; c < REG_VID_PID_CNT; ) { if (registered_VID_PID[c] == device_VID) // VID is correct { for (c += 2, d = c + registered_VID_PID[c - 1]; c < d; c++) { if (registered_VID_PID[c] == device_PID) return true; // PID is correct } } else c += 2 + registered_VID_PID[c + 1]; } return false; }
Status_t host_hid_get_descriptor(uint8_t descriptor_type, uint8_t descriptor_index, uint8_t s_interface) { Status_t status; const hid_descriptor_t *hid_descriptor = (hid_descriptor_t *)&data_stage; uint8_t i; usb_request.bmRequestType = 0x81; usb_request.bRequest = GET_DESCRIPTOR; usb_request.wValue = descriptor_type << 8 | descriptor_index; usb_request.wIndex = Get_interface_number(s_interface); usb_request.wLength = SIZEOF_DATA_STAGE; usb_request.incomplete_read = false; status = host_transfer_control(data_stage); switch (descriptor_type) { case HID_DESCRIPTOR: for (i = 0; i < hid_descriptor->bNumDescriptors; i++) { if (hid_descriptor->Descriptor[i].bType == HID_REPORT_DESCRIPTOR) { host_hid_report_descriptor_parser.length = usb_format_usb_to_mcu_data(16, hid_descriptor->Descriptor[i].wLength); break; } } break; case HID_REPORT_DESCRIPTOR: host_hid_report_descriptor_parser.item = (hid_item_t *)&data_stage; break; } return status; }
//! This function manages the SET INTERFACE request. //! void usb_set_interface(void) { U8 u8_i; // wValue = Alternate Setting // wIndex = Interface U16 wValue = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); U16 wIndex = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); Usb_ack_setup_received_free(); // Get descriptor #if (USB_HIGH_SPEED_SUPPORT==true) if( Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } #else data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); #endif //** Scan descriptor //* Find configuration selected if( usb_configuration_nb == 0 ) { // No configuration selected then no interface enable Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } u8_i = usb_configuration_nb; while( u8_i != 0 ) { if( CONFIGURATION_DESCRIPTOR != ((S_usb_configuration_descriptor*)pbuffer)->bDescriptorType ) { data_to_transfer -= ((S_usb_configuration_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->bLength; continue; } u8_i--; if( u8_i != 0 ) { data_to_transfer -= ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength; pbuffer = (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength; } } // Find interface selected if( wIndex >= ((S_usb_configuration_descriptor*)pbuffer)->bNumInterfaces ) { // Interface number unknown Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } while( 1 ) { if( data_to_transfer <= ((S_usb_interface_descriptor*)pbuffer)->bLength ) { // Interface unknown Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } data_to_transfer -= ((S_usb_interface_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_interface_descriptor*)pbuffer)->bLength; if( INTERFACE_DESCRIPTOR != ((S_usb_interface_descriptor*)pbuffer)->bDescriptorType ) continue; if( wIndex != ((S_usb_interface_descriptor*)pbuffer)->bInterfaceNumber ) continue; if( wValue != ((S_usb_interface_descriptor*)pbuffer)->bAlternateSetting ) continue; usb_interface_status[wIndex] = wValue; break; } //* Find endpoints of interface and reset it while( 1 ) { if( data_to_transfer <= ((S_usb_endpoint_descriptor*)pbuffer)->bLength ) break; // End of interface data_to_transfer -= ((S_usb_endpoint_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_endpoint_descriptor*)pbuffer)->bLength; if( INTERFACE_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType ) break; // End of interface if( ENDPOINT_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType ) { // Reset endpoint u8_i = ((S_usb_endpoint_descriptor*)pbuffer)->bEndpointAddress & (~MSK_EP_DIR); Usb_disable_stall_handshake(u8_i); Usb_reset_endpoint(u8_i); Usb_reset_data_toggle(u8_i); } } // send a ZLP for STATUS phase Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); }
//! This function manages the SET FEATURE request. The USB test modes are //! supported by this function. //! void usb_set_feature(void) { U16 wValue = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); U16 wIndex = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); U16 wLength = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); if (wLength) goto unsupported_request; if (bmRequestType==USB_SETUP_SET_STAND_DEVICE) { #if (USB_REMOTE_WAKEUP_FEATURE == true) if (FEATURE_DEVICE_REMOTE_WAKEUP == wValue) { device_status |= USB_DEV_STATUS_REMOTEWAKEUP; remote_wakeup_feature = true; Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); return; } #endif goto unsupported_request; } switch (wValue) { case FEATURE_ENDPOINT_HALT: wIndex = Get_desc_ep_nbr(wIndex); // clear direction flag if (bmRequestType != ENDPOINT_TYPE || wIndex == EP_CONTROL || !Is_usb_endpoint_enabled(wIndex)) goto unsupported_request; Usb_enable_stall_handshake(wIndex); Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); break; #if (USB_HIGH_SPEED_SUPPORT==true) case FEATURE_TEST_MODE: if (bmRequestType != DEVICE_TYPE || wIndex & 0x00FF) goto unsupported_request; switch (wIndex >> 8) { case TEST_J: Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2); Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTJ_MASK); break; case TEST_K: Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2); Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTK_MASK); break; case TEST_SE0_NAK: Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2); break; case TEST_PACKET: { static const U8 test_packet[] = { // 00000000 * 9 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 01010101 * 8 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 01110111 * 8 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, // 0, {111111S * 15}, 111111 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // S, 111111S, {0111111S * 7} 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, // 00111111, {S0111111 * 9}, S0 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E }; Usb_ack_setup_received_free(); Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2); Usb_disable_endpoint(EP_CONTROL); Usb_unallocate_memory(EP_CONTROL); (void)Usb_configure_endpoint(EP_CONTROL, TYPE_BULK, DIRECTION_IN, 64, SINGLE_BANK); Usb_reset_endpoint(EP_CONTROL); Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTPCKT_MASK); usb_write_ep_txpacket(EP_CONTROL, &test_packet, sizeof(test_packet), NULL); Usb_send_in(EP_CONTROL); } break; case TEST_FORCE_ENABLE: // Only for downstream facing hub ports default: goto unsupported_request; } break; #endif case FEATURE_DEVICE_REMOTE_WAKEUP: default: goto unsupported_request; } return; unsupported_request: Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); }
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! void usb_get_descriptor(void) { bool zlp; U16 wLength; U8 descriptor_type; U8 string_type; Union32 temp; #if (USB_HIGH_SPEED_SUPPORT==true) bool b_first_data = true; #endif zlp = false; /* no zero length packet */ string_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read LSB of wValue */ descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read MSB of wValue */ switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof(usb_dev_desc); pbuffer = Usb_get_dev_desc_pointer(); break; #if (USB_HIGH_SPEED_SUPPORT==false) case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); break; #else case CONFIGURATION_DESCRIPTOR: if( Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } break; case OTHER_SPEED_CONFIGURATION_DESCRIPTOR: if( !Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } break; case DEVICE_QUALIFIER_DESCRIPTOR: data_to_transfer = Usb_get_qualifier_desc_length(); //!< sizeof(usb_qualifier_desc); pbuffer = Usb_get_qualifier_desc_pointer(); break; #endif default: if (!usb_user_get_descriptor(descriptor_type, string_type)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } break; } temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32); //!< read wIndex and wLength with a 32-bit access //!< since this access is aligned with a 32-bit //!< boundary from the beginning of the endpoint wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]); //!< ignore wIndex, keep and format wLength Usb_ack_setup_received_free(); //!< clear the setup received flag if (wLength > data_to_transfer) { zlp = !(data_to_transfer % EP_CONTROL_LENGTH); //!< zero length packet condition } else { // No need to test ZLP sending since we send the exact number of bytes as // expected by the host. data_to_transfer = wLength; //!< send only requested number of data bytes } Usb_ack_nak_out(EP_CONTROL); while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL)); if (Is_usb_nak_out(EP_CONTROL)) break; // don't clear the flag now, it will be cleared after Usb_reset_endpoint_fifo_access(EP_CONTROL); #if (USB_HIGH_SPEED_SUPPORT==true) // To support other descriptors like OTHER_SPEED_CONFIGURATION_DESCRIPTOR if( b_first_data ) { b_first_data = false; if( 0!= data_to_transfer ) { usb_write_ep_txpacket(EP_CONTROL, pbuffer, 1, &pbuffer); data_to_transfer--; } if( 0!= data_to_transfer ) { usb_write_ep_txpacket(EP_CONTROL, &descriptor_type, 1, NULL); pbuffer = ((const U8*)pbuffer)+1; data_to_transfer--; } } #endif if( 0!= data_to_transfer ) { data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer, data_to_transfer, &pbuffer); } if (Is_usb_nak_out(EP_CONTROL)) break; Usb_ack_control_in_ready_send(); //!< Send data until necessary } if (zlp && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready()); Usb_ack_control_in_ready_send(); } while (!Is_usb_nak_out(EP_CONTROL)); Usb_ack_nak_out(EP_CONTROL); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }
//! This function checks if the device class is supported. //! The function looks in all interfaces declared in the received descriptors if //! one of them matches an entry of the CLASS/SUB_CLASS/PROTOCOL table. //! If HOST_AUTO_CFG_ENDPOINT is enabled, a pipe is configured for each endpoint //! of supported interfaces. //! //! @return bool: Status //! bool host_check_class(void) { uint8_t *descriptor, *conf_end; uint8_t device_class, device_subclass, device_protocol; uint8_t c; #if HOST_AUTO_CFG_ENDPOINT == ENABLE uint8_t nb_endpoint_to_configure = 0; uint8_t ep_index = 0; uint8_t physical_pipe = P_1; // P_1 because physical pipe 0 is reserved for control uint16_t ep_size; // By default, the host is configured when returning Host_set_configured(); #endif // First, assume no interface is supported nb_interface_supported = 0; // Check if configuration descriptor if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != CONFIGURATION_DESCRIPTOR) return false; bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES]; maxpower = data_stage[OFFSET_FIELD_MAXPOWER]; conf_end = data_stage + min(usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_TOTAL_LENGTH)), SIZEOF_DATA_STAGE - OFFSET_FIELD_PROTOCOL); // Look in all interfaces declared in the configuration for (descriptor = data_stage + data_stage[OFFSET_DESCRIPTOR_LENGTH]; descriptor < conf_end; descriptor += descriptor[OFFSET_DESCRIPTOR_LENGTH]) { // Find next interface descriptor switch (descriptor[OFFSET_FIELD_DESCRIPTOR_TYPE]) { case INTERFACE_DESCRIPTOR: // Check the number of supported interfaces does not exceed the maximum if (nb_interface_supported >= MAX_INTERFACE_SUPPORTED) return true; #if HOST_AUTO_CFG_ENDPOINT == ENABLE // If there are still endpoints to configure although a new interface descriptor has been found if (nb_endpoint_to_configure) { // Mark the host as not configured Host_clear_configured(); // Reset the number of endpoints to configure nb_endpoint_to_configure = 0; } #endif // Found an interface descriptor // Get characteristics of this interface device_class = descriptor[OFFSET_FIELD_CLASS]; device_subclass = descriptor[OFFSET_FIELD_SUB_CLASS]; device_protocol = descriptor[OFFSET_FIELD_PROTOCOL]; // Look in registered class table for match for (c = 0; c < REG_CLASS_CNT; c += 3) { if (registered_class[c] == device_class && // Class is correct registered_class[c + 1] == device_subclass && // Subclass is correct registered_class[c + 2] == device_protocol) // Protocol is correct { // Store this interface as supported interface // Memorize its interface nb interface_supported[nb_interface_supported].interface_nb = descriptor[OFFSET_FIELD_INTERFACE_NB]; // its alternate setting interface_supported[nb_interface_supported].altset_nb = descriptor[OFFSET_FIELD_ALT]; // its USB class interface_supported[nb_interface_supported].uclass = device_class; // its USB subclass interface_supported[nb_interface_supported].subclass = device_subclass; // its USB protocol interface_supported[nb_interface_supported].protocol = device_protocol; // the number of endpoints associated with this interface #if HOST_AUTO_CFG_ENDPOINT == ENABLE ep_index = 0; nb_endpoint_to_configure = #endif interface_supported[nb_interface_supported].nb_ep = min(descriptor[OFFSET_FIELD_NB_OF_EP], MAX_EP_PER_INTERFACE); // Update the number of supported interfaces nb_interface_supported++; // Class/subclass/protocol is registered, so look for next interface descriptor break; } } break; #if HOST_AUTO_CFG_ENDPOINT == ENABLE case ENDPOINT_DESCRIPTOR: // If there are still endpoints to configure while there are free pipes if (physical_pipe < MAX_PEP_NB && nb_endpoint_to_configure) { nb_endpoint_to_configure--; // Reconfigure the new physical pipe to get rid of any previous configuration #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE cpu_irq_disable(); #endif Host_disable_pipe(physical_pipe); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE (void)Is_host_pipe_enabled(physical_pipe); cpu_irq_enable(); #endif Host_unallocate_memory(physical_pipe); Host_enable_pipe(physical_pipe); // Fix HW, set freq at 0 in case of no interrupt endpoint if( TYPE_INTERRUPT != descriptor[OFFSET_FIELD_EP_TYPE] ) descriptor[OFFSET_FIELD_EP_INTERVAL] = 0; ep_size = descriptor[OFFSET_FIELD_EP_SIZE] | descriptor[OFFSET_FIELD_EP_SIZE + 1] << 8; #if BOARD != EVK1104 if (ep_size <= 64) { #endif // Build the pipe configuration according to the endpoint descriptor fields received (void)Host_configure_pipe( physical_pipe, // Pipe nb in USB interface descriptor[OFFSET_FIELD_EP_INTERVAL], // Interrupt period (for interrupt pipe) Get_desc_ep_nbr(descriptor[OFFSET_FIELD_EP_ADDR]), // Pipe endpoint number descriptor[OFFSET_FIELD_EP_TYPE], // Pipe type (isochronous/bulk/interrupt) Get_pipe_token(descriptor[OFFSET_FIELD_EP_ADDR]), // Pipe token (IN/OUT) ep_size, // Pipe size (descriptor[OFFSET_FIELD_EP_TYPE] == TYPE_BULK) ? SINGLE_BANK : DOUBLE_BANK // Number of banks to allocate for pipe ); // Update endpoint pipe table in supported interface structure interface_supported[nb_interface_supported - 1].ep_pipe[ep_index++] = physical_pipe++; } #if BOARD != EVK1104 else { // Build the pipe configuration according to the endpoint descriptor fields received (void)Host_configure_pipe( MAX_PEP_NB - 1, // Pipe nb in USB interface descriptor[OFFSET_FIELD_EP_INTERVAL], // Interrupt period (for interrupt pipe) Get_desc_ep_nbr(descriptor[OFFSET_FIELD_EP_ADDR]), // Pipe endpoint number descriptor[OFFSET_FIELD_EP_TYPE], // Pipe type (isochronous/bulk/interrupt) Get_pipe_token(descriptor[OFFSET_FIELD_EP_ADDR]), // Pipe token (IN/OUT) ep_size, // Pipe size (descriptor[OFFSET_FIELD_EP_TYPE] == TYPE_BULK) ? SINGLE_BANK : DOUBLE_BANK // Number of banks to allocate for pipe ); // Update endpoint pipe table in supported interface structure interface_supported[nb_interface_supported - 1].ep_pipe[ep_index++] = MAX_PEP_NB - 1; } } #endif break; #endif } // Call user callback to look more deeply into the configuration descriptor Host_user_check_class_action(descriptor); } #if HOST_AUTO_CFG_ENDPOINT == ENABLE // If there are still endpoints to configure although all descriptors have been parsed if (nb_endpoint_to_configure) { // Mark the host as not configured Host_clear_configured(); } #endif return (nb_interface_supported > 0); }
Status_bool_t host_hid_get_item(host_hid_item_t *item) { const hid_item_t *hid_item = host_hid_report_descriptor_parser.item; uint8_t size; if (host_hid_report_descriptor_parser.length < (uint8_t *)&hid_item->header - (uint8_t *)hid_item + sizeof(hid_item->header)) return false; item->type = hid_item->header.bType; if (hid_item->header.bTag == HID_ITEM_TAG_LONG_ITEM) { if (host_hid_report_descriptor_parser.length < (uint8_t *)&hid_item->long_format.bDataSize - (uint8_t *)hid_item + sizeof(hid_item->long_format.bDataSize)) return false; size = hid_item->long_format.bDataSize; if (host_hid_report_descriptor_parser.length < (uint8_t *)&hid_item->long_format.data - (uint8_t *)hid_item + size) return false; item->tag = hid_item->long_format.bLongItemTag; item->long_format = true; item->long_data.size = size; item->long_data.data = &hid_item->long_format.data; host_hid_report_descriptor_parser.length -= (uint8_t *)&hid_item->long_format.data - (uint8_t *)hid_item + size; host_hid_report_descriptor_parser.item = (hid_item_t *)&hid_item->long_format.data[size]; } else { uint8_t i; size = (hid_item->short_format.bSize) ? 1 << (hid_item->short_format.bSize - 1) : 0; if (host_hid_report_descriptor_parser.length < (uint8_t *)&hid_item->short_format.data - (uint8_t *)hid_item + size) return false; item->tag = hid_item->short_format.bTag; item->long_format = false; item->short_data.value = 0x00000000; for (i = 0; i < size; i++) { item->short_data.value = item->short_data.value << 8 | hid_item->short_format.data[i]; } item->short_data.value = usb_format_usb_to_mcu_data(32, item->short_data.value << ((sizeof(uint32_t) - size) << 3)); host_hid_report_descriptor_parser.length -= (uint8_t *)&hid_item->short_format.data - (uint8_t *)hid_item + size; host_hid_report_descriptor_parser.item = (hid_item_t *)&hid_item->short_format.data[size]; } return true; }
//! This function is called by the standard USB read request function when //! the USB request is not supported. This function returns TRUE when the //! request is processed. This function returns FALSE if the request is not //! supported. In this case, a STALL handshake will be automatically //! sent by the standard USB read request function. //! Bool uac2_user_read_request(U8 type, U8 request) { int i; // Read wValue // why are these file statics? wValue_lsb = Usb_read_endpoint_data(EP_CONTROL, 8); wValue_msb = Usb_read_endpoint_data(EP_CONTROL, 8); wIndex = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); wLength = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); if (type == IN_CL_INTERFACE || type == OUT_CL_INTERFACE){ // process Class Specific Interface // request for AUDIO interfaces if (wIndex == DSC_INTERFACE_AS){ // Audio Streaming Interface if (type == IN_CL_INTERFACE){ // get controls if (wValue_msb == AUDIO_AS_VAL_ALT_SETTINGS && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, 0x01); Usb_write_endpoint_data(EP_CONTROL, 8, 0b00000011); // alt 0 and 1 valid Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, usb_alternate_setting); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_AS_AUDIO_DATA_FORMAT && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, 0x01); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); // only PCM format Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; } else if (type == OUT_CL_INTERFACE){ // set controls if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); usb_alternate_setting = Usb_read_endpoint_data(EP_CONTROL, 8); usb_alternate_setting_changed = TRUE; Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done return FALSE; } } // end OUT_CL_INTERFACE } // end DSC_INTERFACE_AS if (wIndex == DSC_INTERFACE_AS_OUT){ // Playback Audio Streaming Interface if (type == IN_CL_INTERFACE){ // get controls if (wValue_msb == AUDIO_AS_VAL_ALT_SETTINGS && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, 0x01); Usb_write_endpoint_data(EP_CONTROL, 8, 0b00000011); // alt 0 and 1 valid Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, usb_alternate_setting_out); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_AS_AUDIO_DATA_FORMAT && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, 0x01); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); // only PCM format Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; } else if (type == OUT_CL_INTERFACE){ // set controls if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); usb_alternate_setting_out = Usb_read_endpoint_data(EP_CONTROL, 8); usb_alternate_setting_out_changed = TRUE; Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done return FALSE; } } // end OUT_CL_INTERFACE } // end DSC_INTERFACE_AS_OUT if ( (wIndex % 256) == DSC_INTERFACE_AUDIO){// low byte wIndex is Interface number // high byte is for EntityID if (type == IN_CL_INTERFACE){ // get controls switch (wIndex /256){ case CSD_ID_1: if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[3]); // 0x0000bb80 is 48khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[2]); // 0x00017700 is 96khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[1]); // 0x0002ee00 is 192khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[0]); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_CS_CONTROL_CLOCK_VALID && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, TRUE); // always valid // temp hack to give total # of bytes requested for (i = 0; i < (wLength - 1); i++) Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_RANGE){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); // give total # of bytes requested for (i = 0; i < (wLength); i++){ if (FEATURE_DAC_ES9022) Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_1[i]); else Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_2[i]); } Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case CSD_ID_2: if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[3]); // 0x0000bb80 is 48khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[2]); // 0x00017700 is 96khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[1]); // 0x0002ee00 is 192khz Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[0]); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_CS_CONTROL_CLOCK_VALID && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, TRUE); // always valid // temp hack to give total # of bytes requested for (i = 0; i < (wLength - 1); i++) Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_RANGE){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); // give total # of bytes requested for (i = 0; i < (wLength); i++) Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_2[i]); // LED_Toggle(LED0); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case CSX_ID: if (wValue_msb == AUDIO_CX_CLOCK_SELECTOR && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, clock_selected); // temp hack to give total # of bytes requested for (i = 0; i < (wLength - 1); i++) Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case MIC_FEATURE_UNIT_ID: if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, mute); // temp hack to give total # of bytes requested for (i = 0; i < (wLength - 1); i++) Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case SPK_FEATURE_UNIT_ID: if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); Usb_write_endpoint_data(EP_CONTROL, 8, spk_mute); // temp hack to give total # of bytes requested for (i = 0; i < (wLength - 1); i++) Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case INPUT_TERMINAL_ID: if (wValue_msb == AUDIO_TE_CONTROL_CS_CLUSTER && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); if (usb_alternate_setting == 1) { Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_NB_CHANNELS); Usb_write_endpoint_data(EP_CONTROL, 8, (U8) INPUT_TERMINAL_CHANNEL_CONF); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_STRING_DESC); } else { // zero's at startup alt setting 0 Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); }; Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; case SPK_INPUT_TERMINAL_ID: if (wValue_msb == AUDIO_TE_CONTROL_CS_CLUSTER && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); Usb_reset_endpoint_fifo_access(EP_CONTROL); if (usb_alternate_setting_out == 1) { Usb_write_endpoint_data(EP_CONTROL, 8, SPK_INPUT_TERMINAL_NB_CHANNELS); Usb_write_endpoint_data(EP_CONTROL, 8, (U8) SPK_INPUT_TERMINAL_CHANNEL_CONF); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_STRING_DESC); } else { // zero's at startup alt setting 0 Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); Usb_write_endpoint_data(EP_CONTROL, 8, 0x00); }; Usb_ack_control_in_ready_send(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); return TRUE; } else return FALSE; default: return FALSE; } // end switch EntityID } else if (type == OUT_CL_INTERFACE){ // set controls switch (wIndex /256){ case CSD_ID_1: // set CUR freq case CSD_ID_2: if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); current_freq.freq_bytes[3]=Usb_read_endpoint_data(EP_CONTROL, 8); // read 4 bytes freq to set current_freq.freq_bytes[2]=Usb_read_endpoint_data(EP_CONTROL, 8); current_freq.freq_bytes[1]=Usb_read_endpoint_data(EP_CONTROL, 8); current_freq.freq_bytes[0]=Usb_read_endpoint_data(EP_CONTROL, 8); freq_changed = TRUE; Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done return TRUE; } else return FALSE; case CSX_ID: if (wValue_msb == AUDIO_CX_CLOCK_SELECTOR && wValue_lsb == 0 && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); clock_selected = Usb_read_endpoint_data(EP_CONTROL, 8); clock_changed = TRUE; Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done if (clock_selected < 1 || clock_selected > CSX_INPUT_PINS) clock_selected = 1; return TRUE; } else return FALSE; case MIC_FEATURE_UNIT_ID: if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); mute = Usb_read_endpoint_data(EP_CONTROL, 8); Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done return TRUE; } else return FALSE; case SPK_FEATURE_UNIT_ID: if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE && request == AUDIO_CS_REQUEST_CUR){ Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_reset_endpoint_fifo_access(EP_CONTROL); spk_mute = Usb_read_endpoint_data(EP_CONTROL, 8); Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); //!< send a ZLP for STATUS phase while (!Is_usb_control_in_ready()); //!< waits for status phase done return TRUE; } else return FALSE; default: return FALSE; } } // end OUT_CL_INTERFACE } // end Audio Control Interface } // end CL_INTERFACE return FALSE; // No supported request }
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! void usb_get_descriptor(void) { Bool zlp; U16 wLength; U8 descriptor_type; U8 string_type; Union32 temp; zlp = FALSE; /* no zero length packet */ string_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read LSB of wValue */ descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read MSB of wValue */ switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof(usb_dev_desc); pbuffer = Usb_get_dev_desc_pointer(); break; case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); break; default: if (!usb_user_get_descriptor(descriptor_type, string_type)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } break; } temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32); //!< read wIndex and wLength with a 32-bit access //!< since this access is aligned with a 32-bit //!< boundary from the beginning of the endpoint wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]); //!< ignore wIndex, keep and format wLength Usb_ack_setup_received_free(); //!< clear the setup received flag if (wLength > data_to_transfer) { zlp = !(data_to_transfer % EP_CONTROL_LENGTH); //!< zero length packet condition } else { // No need to test ZLP sending since we send the exact number of bytes as // expected by the host. data_to_transfer = (U8)wLength; //!< send only requested number of data bytes } Usb_ack_nak_out(EP_CONTROL); while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL)); if (Is_usb_nak_out(EP_CONTROL)) break; // don't clear the flag now, it will be cleared after Usb_reset_endpoint_fifo_access(EP_CONTROL); data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer, data_to_transfer, &pbuffer); if (Is_usb_nak_out(EP_CONTROL)) break; else Usb_ack_control_in_ready_send(); //!< Send data until necessary } if (zlp && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready()); Usb_ack_control_in_ready_send(); } while (!Is_usb_nak_out(EP_CONTROL)); Usb_ack_nak_out(EP_CONTROL); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }