//! @brief This function configures the endpoints of the device application. //! This function is called when the set configuration request has been received. //! void usb_user_endpoint_init(uint8_t conf_nb) { #if (USB_HIGH_SPEED_SUPPORT==false) (void)Usb_configure_endpoint(EP_HID_MOUSE_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_FS, SINGLE_BANK); #else if( Is_usb_full_speed_mode() ) { (void)Usb_configure_endpoint(EP_HID_MOUSE_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_FS, SINGLE_BANK); }else{ (void)Usb_configure_endpoint(EP_HID_MOUSE_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_HS, SINGLE_BANK); } #endif }
//! @brief This function configures the endpoints of the device application. //! This function is called when the set configuration request has been received. //! void usb_user_endpoint_init(uint8_t conf_nb) { ms_multiple_drive = false; #if (USB_HIGH_SPEED_SUPPORT==true) if( !Is_usb_full_speed_mode() ) { (void)Usb_configure_endpoint(EP_MS_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_HS, DOUBLE_BANK); (void)Usb_configure_endpoint(EP_MS_OUT, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_HS, DOUBLE_BANK); return; } #endif (void)Usb_configure_endpoint(EP_MS_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_FS, DOUBLE_BANK); (void)Usb_configure_endpoint(EP_MS_OUT, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_FS, DOUBLE_BANK); }
//! @brief In host mode, display basic low level information about the device connected //! //! @note The device should be supported by the host (configured) //! void ushell_cmdusb_ls(void) { uint8_t i,j; // Check USB host status if( (!Is_host_ready()) && (!Is_host_suspended()) ) { fputs(MSG_NO_DEVICE, stdout); return; } if( Is_host_suspended() ) { fputs(MSG_USB_SUSPENDED, stdout); } printf("VID:%04X, PID:%04X, ",Get_VID(),Get_PID()); printf("MaxPower is %imA, ",2*Get_maxpower()); if (Is_device_self_powered()) { fputs(MSG_SELF_POWERED, stdout);} else { fputs(MSG_BUS_POWERED, stdout); } if (Is_usb_full_speed_mode()) { fputs(MSG_DEVICE_FULL_SPEED, stdout);} else #if (USB_HIGH_SPEED_SUPPORT==false) { fputs(MSG_DEVICE_LOW_SPEED, stdout); } #else { fputs(MSG_DEVICE_HIGH_SPEED, stdout); } #endif if (Is_device_supports_remote_wakeup()) { fputs(MSG_REMOTE_WAKEUP_OK, stdout);} else { fputs(MSG_REMOTE_WAKEUP_KO, stdout); } printf("Supported interface(s):%02i\n\r",Get_nb_supported_interface()); for(i=0;i<Get_nb_supported_interface();i++) { printf("Interface nb:%02i, AltS nb:%02i, Class:%02i, SubClass:%02i, Protocol:%02i\n\r",\ Get_interface_number(i), Get_altset_nb(i), Get_class(i), Get_subclass(i), Get_protocol(i)); printf(" Endpoint(s) Addr:"); if(Get_nb_ep(i)) { for(j=0;j<Get_nb_ep(i);j++) { printf(" %02lX", Get_ep_nbr(i,j)); } } else { printf("None"); } putchar(ASCII_CR);putchar(ASCII_LF); } }
//! @brief This function configures the endpoints of the device application. //! This function is called when the set configuration request has been received. //! void uac2_user_endpoint_init(U8 conf_nb) { if( Is_usb_full_speed_mode() ) { (void)Usb_configure_endpoint(UAC2_EP_AUDIO_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_FS, DOUBLE_BANK, 0); (void)Usb_configure_endpoint(UAC2_EP_AUDIO_OUT, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_FS, DOUBLE_BANK, 0); (void)Usb_configure_endpoint(UAC2_EP_AUDIO_OUT_FB, EP_ATTRIBUTES_3, DIRECTION_IN, EP_SIZE_3_FS, DOUBLE_BANK, 0); } else { (void)Usb_configure_endpoint(UAC2_EP_AUDIO_IN, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_HS, DOUBLE_BANK, 0); (void)Usb_configure_endpoint(UAC2_EP_AUDIO_OUT, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_HS, DOUBLE_BANK, 0); (void)Usb_configure_endpoint(UAC2_EP_AUDIO_OUT_FB, EP_ATTRIBUTES_3, DIRECTION_IN, EP_SIZE_3_HS, DOUBLE_BANK, 0); } }
//! @brief This function configures the endpoints of the device application. //! This function is called when the set configuration request has been received. //! void usb_user_endpoint_init(U8 conf_nb) { #if (USB_HIGH_SPEED_SUPPORT==ENABLED) if( !Is_usb_full_speed_mode() ) { (void)Usb_configure_endpoint(INT_EP, EP_ATTRIBUTES_3, DIRECTION_IN, EP_SIZE_3, SINGLE_BANK); (void)Usb_configure_endpoint(TX_EP, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_HS, DOUBLE_BANK); (void)Usb_configure_endpoint(RX_EP, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_HS, DOUBLE_BANK); return; } #endif (void)Usb_configure_endpoint(INT_EP, EP_ATTRIBUTES_3, DIRECTION_IN, EP_SIZE_3, SINGLE_BANK); (void)Usb_configure_endpoint(TX_EP, EP_ATTRIBUTES_1, DIRECTION_IN, EP_SIZE_1_FS, DOUBLE_BANK); (void)Usb_configure_endpoint(RX_EP, EP_ATTRIBUTES_2, DIRECTION_OUT, EP_SIZE_2_FS, DOUBLE_BANK); }
//! //! @brief Entry point of the AK5394A task management //! void AK5394A_task(void *pvParameters) { portTickType xLastWakeTime; xLastWakeTime = xTaskGetTickCount(); int i; while (TRUE) { // All the hardwork is done by the pdca and the interrupt handler. // Just check whether sampling freq is changed, to do rate change etc. vTaskDelayUntil(&xLastWakeTime, configTSK_AK5394A_PERIOD); if (freq_changed){ if (current_freq.frequency == 96000){ pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX); pdca_disable(PDCA_CHANNEL_SSC_RX); gpio_set_gpio_pin(AK5394_DFS0); // L H -> 96khz gpio_clr_gpio_pin(AK5394_DFS1); pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc 0, // osc_or_pll: use Osc (if 0) or PLL (if 1) 1, // pll_osc: select Osc0/PLL0 or Osc1/PLL1 1, // diven - enabled 0); // divided by 2. Therefore GCLK1 = 6.144Mhz pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); if (Is_usb_full_speed_mode()) FB_rate = 96 << 14; else FB_rate = (96) << 13; } else if (current_freq.frequency == 192000) { pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX); pdca_disable(PDCA_CHANNEL_SSC_RX); gpio_clr_gpio_pin(AK5394_DFS0); // H L -> 192khz gpio_set_gpio_pin(AK5394_DFS1); pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc 0, // osc_or_pll: use Osc (if 0) or PLL (if 1) 1, // pll_osc: select Osc0/PLL0 or Osc1/PLL1 0, // diven - disabled 0); // GCLK1 = 12.288Mhz pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); if (Is_usb_full_speed_mode()) FB_rate = 192 << 14; else FB_rate = (192) << 13; } else if (current_freq.frequency == 48000) // 48khz { pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX); pdca_disable(PDCA_CHANNEL_SSC_RX); gpio_clr_gpio_pin(AK5394_DFS0); // L L -> 48khz gpio_clr_gpio_pin(AK5394_DFS1); pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc 0, // osc_or_pll: use Osc (if 0) or PLL (if 1) 1, // pll_osc: select Osc0/PLL0 or Osc1/PLL1 1, // diven - enabled 1); // divided by 4. Therefore GCLK1 = 3.072Mhz pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1); if (Is_usb_full_speed_mode()) FB_rate = 48 << 14; else FB_rate = (48) << 13; } // re-sync SSC to LRCK // Wait for the next frame synchronization event // to avoid channel inversion. Start with left channel - FS goes low // However, the channels are reversed at 192khz if (current_freq.frequency == 192000) { while (gpio_get_pin_value(AK5394_LRCK)); while (!gpio_get_pin_value(AK5394_LRCK)); // exit when FS goes high } else { while (!gpio_get_pin_value(AK5394_LRCK)); while (gpio_get_pin_value(AK5394_LRCK)); // exit when FS goes low } // Enable now the transfer. pdca_enable(PDCA_CHANNEL_SSC_RX); // Init PDCA channel with the pdca_options. pdca_init_channel(PDCA_CHANNEL_SSC_RX, &PDCA_OPTIONS); // init PDCA channel with options. pdca_enable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX); // reset freq_changed flag freq_changed = FALSE; } if (usb_alternate_setting_out_changed){ if (usb_alternate_setting_out != 1){ for (i = 0; i < SPK_BUFFER_SIZE; i++){ spk_buffer_0[i] = 0; spk_buffer_1[i] = 0; } }; usb_alternate_setting_out_changed = FALSE; } } }
//! 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 usb_user_read_request(U8 type, U8 request) { U8 wValue_msb; U8 wValue_lsb; // Read wValue wValue_lsb = Usb_read_endpoint_data(EP_CONTROL, 8); wValue_msb = Usb_read_endpoint_data(EP_CONTROL, 8); /* U8 descriptor_type; Usb_read_endpoint_data(EP_CONTROL, 8); // string_type descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8); */ //** Specific request from Class HID if( 0x81 == type ) // USB_SETUP_GET_STAND_INTERFACE { switch( request ) { case GET_DESCRIPTOR: switch( wValue_msb ) // Descriptor ID { #if (USB_HIGH_SPEED_SUPPORT==false) case HID_DESCRIPTOR: hid_get_descriptor( sizeof(usb_conf_desc_fs.hid) , (const U8*)&usb_conf_desc_fs.hid); return true; #else case HID_DESCRIPTOR: if( Is_usb_full_speed_mode() ) { hid_get_descriptor( sizeof(usb_conf_desc_fs.hid) , (const U8*)&usb_conf_desc_fs.hid); }else{ hid_get_descriptor( sizeof(usb_conf_desc_hs.hid_mouse) , (const U8*)&usb_conf_desc_hs.hid); } return true; #endif case HID_REPORT_DESCRIPTOR: hid_get_descriptor( sizeof(usb_hid_report_descriptor) , usb_hid_report_descriptor); return true; case HID_PHYSICAL_DESCRIPTOR: // TODO break; } break; } } if( 0x21 == type ) // USB_SETUP_SET_CLASS_INTER { switch( request ) { case HID_SET_REPORT: // The MSB wValue field specifies the Report Type // The LSB wValue field specifies the Report ID switch (wValue_msb) { case HID_REPORT_INPUT: // TODO break; case HID_REPORT_OUTPUT: Usb_ack_setup_received_free(); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); return true; case HID_REPORT_FEATURE: usb_hid_set_report_feature(); return true; break; } break; case HID_SET_IDLE: usb_hid_set_idle(wValue_lsb, wValue_msb); return true; case HID_SET_PROTOCOL: // TODO break; } } if( 0xA1 == type ) // USB_SETUP_GET_CLASS_INTER { switch( request ) { case HID_GET_REPORT: // TODO break; case HID_GET_IDLE: usb_hid_get_idle(wValue_lsb); return true; case HID_GET_PROTOCOL: // TODO break; } } return false; // No supported request }
__interrupt #endif static void usb_general_interrupt(void) #endif { #ifdef FREERTOS_USED portBASE_TYPE task_woken = pdFALSE; #endif #if USB_HOST_FEATURE == true && USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE U8 i; #endif // ---------- DEVICE/HOST events management ------------------------------------ #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true // ID pin change detection if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled()) { g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST; Usb_ack_id_transition(); if (g_usb_mode != g_old_usb_mode) // Basic debounce { // Previously in device mode, check if disconnection was detected if (g_old_usb_mode == USB_MODE_DEVICE) { if (usb_connected) { // Device mode disconnection actions usb_connected = false; usb_configuration_nb = 0; Usb_vbus_off_action(); } } // Previously in host mode, check if disconnection was detected else if (Is_host_attached()) { // Host mode disconnection actions device_state = DEVICE_UNATTACHED; Host_device_disconnection_action(); } //LOG_STR(log_pin_id_changed); if (Is_usb_id_device() == USB_MODE_DEVICE) { LOG_STR(log_pin_id_changed_to_device); } else { LOG_STR(log_pin_id_changed_to_host); } Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION : EVT_USB_HOST_FUNCTION); Usb_id_transition_action(); // Easier to recover from ID signal de-bounce and ID pin transitions by shutting down the USB and resetting state machine to re-init #if ID_PIN_CHANGE_SHUTDOWN_USB == ENABLE Usb_disable(); Usb_disable_otg_pad(); extern void UsbResetStateMachine(void); UsbResetStateMachine(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif #endif #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE Reset_CPU(); #endif } } #endif // End DEVICE/HOST FEATURE MODE // ---------- DEVICE events management ----------------------------------------- #if USB_DEVICE_FEATURE == true #if USB_HOST_FEATURE == true // If both device and host features are enabled, check if device mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). if (Is_usb_device()) #endif { // VBus state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device(); Usb_send_event(EVT_USB_POWERED); Usb_vbus_on_action(); } else { Usb_unfreeze_clock(); Usb_detach(); usb_connected = false; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_vbus_off_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } } // Device Start-of-Frame received if (Is_usb_sof() && Is_usb_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); (void)Is_usb_wake_up_interrupt_enabled(); Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // Wake-up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled()) { Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // Resume state bus detection if (Is_usb_resume() && Is_usb_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // USB bus reset detection if (Is_usb_reset() && Is_usb_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } } #endif // End DEVICE FEATURE MODE // ---------- HOST events management ------------------------------------------- #if USB_HOST_FEATURE == true #if USB_DEVICE_FEATURE == true // If both device and host features are enabled, check if host mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). else #endif { // The device has been disconnected if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipes(); Host_ack_device_disconnection(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif device_state = DEVICE_UNATTACHED; LOG_STR(log_device_disconnected); Usb_send_event(EVT_HOST_DISCONNECTION); Host_device_disconnection_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } // Device connection if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipes(); Host_device_connection_action(); } // Host Start-of-Frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); #if (USB_HIGH_SPEED_SUPPORT==true) if( Is_usb_full_speed_mode() ) { private_sof_counter++; }else{ private_sof_counter_HS++; if( 0 == (private_sof_counter_HS%8) ) { private_sof_counter++; } } #else private_sof_counter++; #endif // Delay time-out management for interrupt transfer mode in host mode #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms) { private_sof_counter = 0; for (i = 0; i < MAX_PEP_NB; i++) { if (it_pipe_str[i].enable && ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT) { it_pipe_str[i].enable = false; it_pipe_str[i].status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(i); if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed { Host_disable_sof_interrupt(); } it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed); } } } #endif Host_sof_action(); } // Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)! //! @todo Implement this on the silicon version //Pll_start_auto(); // First Restart the PLL for USB operation //Wait_pll_ready(); // Make sure PLL is locked Usb_unfreeze_clock(); // Enable clock on USB interface (void)Is_usb_clock_frozen(); // Make sure USB interface clock is enabled Host_disable_hwup_interrupt(); // Wake-up interrupt should be disabled as host is now awoken! Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Host pipe interrupts while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i); #endif } #endif // End HOST FEATURE MODE #ifdef FREERTOS_USED return task_woken; #endif }
//! 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 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(); }
/*! * \brief In host mode, display basic low-level information about the connected device. * The device should be supported by the host (configured). * No parameters. * Format: lsusb * * \note This function must be of the type pfShellCmd defined by the shell module. * * \param xModId Input. The module that is calling this function. * \param FsNavId Ignored. * \param ac Input. The argument counter. Ignored. * \param av Input. The argument vector. Ignored * \param ppcStringReply Input/Output. The response string. * If Input is NULL, no response string will be output. * Else a malloc for the response string is performed here; * the caller must free this string. * * \return the status of the command execution. */ eExecStatus e_usbsys_lsusb( eModId xModId, signed short FsNavId, int ac, signed portCHAR *av[], signed portCHAR **ppcStringReply ) { #if USB_HOST_FEATURE == true signed portCHAR *pcStringToPrint; U8 i, j; if( NULL != ppcStringReply ) *ppcStringReply = NULL; if (!Is_host_ready() && !Is_host_suspended()) { v_shell_Print_String_To_Requester_Stream( xModId, (signed portCHAR *)MSG_NO_DEVICE ); return SHELL_EXECSTATUS_KO; } pcStringToPrint = (signed portCHAR *)pvPortMalloc( SHELL_MAX_MSGOUT_LEN ); // Alloc if( NULL == pcStringToPrint ) { return( SHELL_EXECSTATUS_KO ); } if (Is_host_suspended()) { v_shell_Print_String_To_Requester_Stream( xModId, (signed portCHAR *)MSG_USB_SUSPENDED CRLF ); } sprintf( (char *)pcStringToPrint, "VID: 0x%.4X, PID: 0x%.4X\r\n" "Device MaxPower is %d mA\r\n" "%s" "%s", Get_VID(), Get_PID(), 2 * Get_maxpower(), Is_device_self_powered() ? MSG_SELF_POWERED : MSG_BUS_POWERED, Is_usb_full_speed_mode() ? MSG_DEVICE_FULL_SPEED : MSG_DEVICE_LOW_SPEED ); v_shell_Print_String_To_Requester_Stream( xModId, pcStringToPrint ); sprintf( (char *)pcStringToPrint, "%s" "Supported interface(s): %u", Is_device_supports_remote_wakeup() ? MSG_REMOTE_WAKEUP_OK : MSG_REMOTE_WAKEUP_KO, Get_nb_supported_interface() ); v_shell_Print_String_To_Requester_Stream( xModId, pcStringToPrint ); for (i = 0; i < Get_nb_supported_interface(); i++) { sprintf( (char *)pcStringToPrint, "\r\nInterface nb: %u, AltS nb: %u, Class: 0x%.2X," " SubClass: 0x%.2X, Protocol: 0x%.2X\r\n" "\tAssociated Ep Nbrs:", Get_interface_number(i), Get_altset_nb(i), Get_class(i), Get_subclass(i), Get_protocol(i) ); v_shell_Print_String_To_Requester_Stream( xModId, pcStringToPrint ); if (Get_nb_ep(i)) { for (j = 0; j < Get_nb_ep(i); j++) { sprintf( (char *)pcStringToPrint, " %u", (U16)Get_ep_nbr(i, j) ); v_shell_Print_String_To_Requester_Stream( xModId, pcStringToPrint ); } } else { v_shell_Print_String_To_Requester_Stream( xModId, (signed portCHAR *)"None" ); } } vPortFree( pcStringToPrint ); v_shell_Print_String_To_Requester_Stream( xModId, (signed portCHAR *)CRLF ); #else v_shell_Print_String_To_Requester_Stream( xModId, (signed portCHAR *)MSG_NO_DEVICE ); #endif return( SHELL_EXECSTATUS_OK ); }
//! 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) { U8 *descriptor, *conf_end; U8 device_class, device_subclass, device_protocol; U8 c; #if HOST_AUTO_CFG_ENDPOINT == ENABLE U8 nb_endpoint_to_configure = 0; U8 ep_index = 0; U8 physical_pipe = P_1; // P_1 because physical pipe 0 is reserved for control // 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, *(U16 *)(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 Disable_global_interrupt(); #endif Host_disable_pipe(physical_pipe); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE (void)Is_host_pipe_enabled(physical_pipe); Enable_global_interrupt(); #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; // 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) descriptor[OFFSET_FIELD_EP_SIZE] | descriptor[OFFSET_FIELD_EP_SIZE + 1] << 8, // Pipe size ((TYPE_ISOCHRONOUS == (descriptor[OFFSET_FIELD_EP_TYPE] & TRANSFER_TYPE_MASK)) || (TYPE_BULK == (descriptor[OFFSET_FIELD_EP_TYPE] & TRANSFER_TYPE_MASK)) ? DOUBLE_BANK : SINGLE_BANK) // Number of banks to allocate for pipe ); #if (USB_HIGH_SPEED_SUPPORT==true) if( (TYPE_BULK == Host_get_pipe_type(physical_pipe)) && (TOKEN_OUT == Host_get_pipe_token(physical_pipe)) ) { if( !Is_usb_full_speed_mode() ) { // Enable PING management for bulk OUT endpoint each micro frame Host_configure_pipe_int_req_freq(physical_pipe,0); Host_enable_ping(physical_pipe); } } #endif // Update endpoint pipe table in supported interface structure interface_supported[nb_interface_supported - 1].ep_pipe[ep_index++] = physical_pipe++; } 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); }