void cdc_ecm_notify_network_connection(uint8_t value) { #if CDC_ECM_USES_INTERRUPT_ENDPOINT Usb_select_endpoint(INT_EP); if(!Is_usb_endpoint_enabled()) { //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: endpoint not enabled\n")); return; } if(usb_endpoint_wait_for_IN_ready()!=0) { //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: Timeout waiting for interrupt endpoint to be available\n")); return; } Usb_send_control_in(); Usb_write_byte(0x51); // 10100001b Usb_write_byte(CDC_NOTIFY_NETWORK_CONNECTION); Usb_write_byte(value); Usb_write_byte(0x00); Usb_write_word(ECM_INTERFACE0_NB); Usb_write_word(0x0000); Usb_send_in(); PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_NETWORK_CONNECTION %d\n"),value); #endif }
/** * @brief This function transmits a ram buffer content to the USB. * This function is mode efficient in term of USB bandwith transfer. * * @param U8 *buffer : the pointer to the RAM buffer to be sent * @param data_to_send : the number of data to be sent */ void uart_usb_send_buffer(U8 *buffer, U8 nb_data) { U8 zlp; if(!Is_device_enumerated()) return; // Compute if zlp required if(nb_data%TX_EP_SIZE) zlp=FALSE; else zlp=TRUE; Usb_select_endpoint(TX_EP); while (nb_data) { while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready while(Is_usb_write_enabled() && nb_data) { Usb_write_byte(*buffer); buffer++; nb_data--; } Usb_ack_in_ready(); } if(zlp) { while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready Usb_ack_in_ready(); } }
//! usb_init_device. //! //! This function initializes the USB device controller and //! configures the Default Control Endpoint. //! //! //! @param none //! //! @return status //! U8 usb_init_device (void) { Usb_select_device(); if(Is_usb_id_device()) { Usb_select_endpoint(EP_CONTROL); if(!Is_usb_endpoint_enabled()) { #if (USB_LOW_SPEED_DEVICE==DISABLE) return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_64, \ ONE_BANK, \ NYET_DISABLED); #else return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_8, \ ONE_BANK, \ NYET_DISABLED); #endif } } return FALSE; }
void cdc_ecm_notify_connection_speed_change(uint32_t upstream,uint32_t downstream) { #if CDC_ECM_USES_INTERRUPT_ENDPOINT Usb_select_endpoint(INT_EP); if(!Is_usb_endpoint_enabled()) return; if(usb_endpoint_wait_for_IN_ready()!=0) return; Usb_send_control_in(); Usb_write_byte(0x51); // 10100001b Usb_write_byte(CDC_NOTIFY_CONNECTION_SPEED_CHANGE); Usb_write_word(0x0000); Usb_write_word(ECM_INTERFACE0_NB); Usb_write_word(0x0008); Usb_send_in(); if(usb_endpoint_wait_for_write_enabled()!=0) return; Usb_write_long(upstream); Usb_write_long(downstream); Usb_send_in(); PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_CONNECTION_SPEED_CHANGE UP:%d DOWN:%d\n"),upstream,downstream); #endif }
/** * @brief This function fills the USB transmit buffer with the new data. This buffer * is sent if complete. To flush this buffer before waiting full, launch * the uart_usb_flush() function. * * @param data_to_send Data to send * * @return data_to_send Data that was sent */ int uart_usb_putchar(int data_to_send) { // Preserve the currently selected endpoint uint8_t uenum = UENUM; USB_CDC_ACM_HOOK_TX_START(data_to_send); Usb_select_endpoint(VCP_TX_EP); if(usb_endpoint_wait_for_write_enabled()!=0) { data_to_send=-1; goto bail; } Usb_write_byte(data_to_send); tx_counter++; //If Endpoint full -> flush if(!Is_usb_write_enabled()) uart_usb_flush(); USB_CDC_ACM_HOOK_TX_END(data_to_send); bail: // Restore previously selected endpoint UENUM = uenum; return data_to_send; }
/** * @brief This function reads one byte from the USB bus * * If one byte is present in the USB fifo, this byte is returned. If no data * is present in the USB fifo, this function waits for USB data. * * @return U8 byte received */ char uart_usb_getchar(void) { register Uchar data_rx; // Preserve the currently selected endpoint uint8_t uenum = Usb_get_selected_endpoint(); Usb_select_endpoint(VCP_RX_EP); if (!rx_counter) while (!uart_usb_test_hit()); data_rx=Usb_read_byte(); rx_counter--; if (!rx_counter) Usb_ack_receive_out(); #if USB_CDC_ACM_CONF_LOCAL_ECHO //Local echo uart_usb_putchar(data_rx); #endif USB_CDC_ACM_HOOK_RX(data_rx); // Restore previously selected endpoint UENUM = uenum; return data_rx; }
//! @brief This function selects (and resets) the interface alternate setting //! //! @param wInterface Interface selected //! @param alternate_setting alternate setting selected //! void usb_user_interface_reset(U16 wInterface, U8 alternate_setting) { // default setting selected = reset data toggle if( INTERFACE_NB == wInterface ) { // Interface Mass Storage Usb_select_endpoint(EP_MS_IN); Usb_disable_stall_handshake(); Usb_reset_endpoint(EP_MS_IN); Usb_reset_data_toggle(); Usb_select_endpoint(EP_MS_OUT); Usb_disable_stall_handshake(); Usb_reset_endpoint(EP_MS_OUT); Usb_reset_data_toggle(); } }
//! usb_set_feature. //! //! This function manages the SET FEATURE request. The USB test modes are //! supported by this function. //! //! @warning Code:xx bytes (function code length) //! void usb_set_feature(void) { U8 wValue; U8 wIndex; U8 dummy; if (bmRequestType == INTERFACE_TYPE) { return; } else if (bmRequestType == ENDPOINT_TYPE) { wValue = Usb_read_byte(); dummy = Usb_read_byte(); //!< dummy read if (wValue == FEATURE_ENDPOINT_HALT) { wIndex = (Usb_read_byte() & MSK_EP_DIR); if (wIndex == EP_CONTROL) { return; } Usb_select_endpoint(wIndex); if(Is_usb_endpoint_enabled()) { Usb_enable_stall_handshake(); Usb_select_endpoint(EP_CONTROL); endpoint_status[wIndex] = 0x01; Usb_ack_receive_setup(); Usb_send_control_in(); } else { Usb_select_endpoint(EP_CONTROL); return; } } else { return; } } }
//! @brief Send data report to Host //! void hid_report_in(void) { Usb_select_endpoint(EP_HID_IN); if(!Is_usb_write_enabled()) return; // Not ready to send report setINreport(); }
//! Task which links mouse events with the USB HID mouse device //! void mouse_task(void) { if(Is_usb_vbus_low()) { Setup_power_down_mode(); Sleep_instruction(); } if(!Is_device_enumerated()) return; // Device not ready #if (USB_LOW_SPEED_DEVICE==DISABLE) // The SOF is used to schedule the task at the same frequency that Endpoint Interrupt frequency // This check allow to win a CPU time if(g_u8_cpt_sof<NB_IDLE_POLLING_SOF) return; // Wait a delay g_u8_cpt_sof=0; #endif if(!g_b_send_report) { // No report sending on going, then check mouse event to eventualy fill a new report if(is_mouse_event()) { // Enable sending of report g_b_send_report = TRUE; } } if((!g_b_send_report)&&(!g_b_send_ack_report)) return; // No report and ack to send //** A report or ack must be send Usb_select_endpoint(EP_MOUSE_IN); if(!Is_usb_write_enabled()) return; // Endpoint no free Led0_on(); if( g_b_send_report ) { g_b_send_report = FALSE; // Send an ack after a "clic" report only g_b_send_ack_report = (0!=g_hid_mouse_report[0]); } else { Hid_mouse_report_reset(); // Reset report to have a ack report g_b_send_ack_report = FALSE; } // Send report Usb_write_byte(g_hid_mouse_report[0]); Usb_write_byte(g_hid_mouse_report[1]); Usb_write_byte(g_hid_mouse_report[2]); Usb_write_byte(g_hid_mouse_report[3]); Usb_ack_in_ready(); Led0_off(); }
/** * @brief This function reads one byte from the USB bus * * If one byte is present in the USB fifo, this byte is returned. If no data * is present in the USB fifo, this function waits for USB data. * * @return U8 byte received */ char uart_usb_getchar(void) { register Uchar data_rx; Usb_select_endpoint(RX_EP); if (!rx_counter) while (!uart_usb_test_hit()); data_rx=Usb_read_byte(); rx_counter--; if (!rx_counter) Usb_ack_receive_out(); return data_rx; }
uint8_t ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) { U8 byte_in_packet = 0; //Send Data Usb_select_endpoint(TX_EP); if(usb_endpoint_wait_for_write_enabled()!=0) { USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); return 0; } #ifdef USB_ETH_HOOK_TX_START USB_ETH_HOOK_TX_START(); #endif //Send packet while(sendlen) { Usb_write_byte(*senddata); senddata++; sendlen--; byte_in_packet++; //If endpoint is full, send data in //And then wait for data to transfer if (!Is_usb_write_enabled()) { Usb_ack_in_ready(); if(usb_endpoint_wait_for_write_enabled()!=0) { USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); return 0; } byte_in_packet=0; } } //Send last data in - also handles sending a ZLP if needed Usb_ack_in_ready(); #ifdef USB_ETH_HOOK_TX_END USB_ETH_HOOK_TX_END(); #endif //Wait for ready if(usb_endpoint_wait_for_IN_ready()!=0) { USB_ETH_HOOK_TX_ERROR("Timeout: IN ready"); return 0; } return 1; }
//! usb_send_packet. //! //! This function moves the data pointed by tbuf to the selected endpoint fifo //! and sends it through the USB. //! //! //! @param ep_num number of the addressed endpoint //! @param *tbuf address of the first data to send //! @param data_length number of bytes to send //! //! @return address of the next U8 to send. //! //! Example: //! usb_send_packet(3,&first_data,0x20); // send packet on the endpoint #3 //! while(!(Usb_tx_complete)); // wait packet ACK'ed by the Host //! Usb_clear_tx_complete(); // acknowledge the transmit //! //! Note: //! tbuf is incremented of 'data_length'. //! U8 usb_send_packet(U8 ep_num, U8* tbuf, U8 data_length) { U8 remaining_length; remaining_length = data_length; Usb_select_endpoint(ep_num); while(Is_usb_write_enabled() && (0 != remaining_length)) { Usb_write_byte(*tbuf); remaining_length--; tbuf++; } return remaining_length; }
//! usb_send_packet. //! //! This function moves the data pointed by tbuf to the selected endpoint fifo //! and sends it through the USB. //! //! @warning Code:xx bytes (function code length) //! //! @param ep_num number of the addressed endpoint //! @param *tbuf address of the first data to send //! @param data_length number of bytes to send //! //! @return address of the next uint8_t to send. //! //! Example: //! usb_send_packet(3,&first_data,0x20); // send packet on the endpoint #3 //! while(!(Usb_tx_complete)); // wait packet ACK'ed by the Host //! Usb_clear_tx_complete(); // acknowledge the transmit //! //! Note: //! tbuf is incremented of 'data_length'. //! uint8_t usb_send_packet(uint8_t ep_num, uint8_t* tbuf, uint8_t data_length) { uint8_t remaining_length; remaining_length = data_length; Usb_select_endpoint(ep_num); while(Is_usb_write_enabled() && (0 != remaining_length)) { Usb_write_byte(*tbuf); remaining_length--; tbuf++; } return remaining_length; }
uint8_t my_uart_usb_num_to_read(void){ uint8_t num=0; if(!Is_device_enumerated()) return 0; Usb_select_endpoint(RX_EP); if (Is_usb_receive_out()){ num = Usb_byte_counter(); if (num == 0) Usb_ack_receive_out(); } return num; }
//! usb_read_packet. //! //! This function moves the data stored in the selected endpoint fifo to //! the address specified by *rbuf. //! //! @warning Code:xx bytes (function code length) //! //! @param ep_num number of the addressed endpoint //! @param *rbuf aaddress of the first data to write with the USB data //! @param data_length number of bytes to read //! //! @return address of the next uint8_t to send. //! //! Example: //! while(!(Usb_rx_complete)); // wait new packet received //! usb_read_packet(4,&first_data,usb_get_nb_byte); // read packet from ep 4 //! Usb_clear_rx(); // acknowledge the transmit //! //! Note: //! rbuf is incremented of 'data_length'. //! uint8_t usb_read_packet(uint8_t ep_num, uint8_t* rbuf, uint8_t data_length) { uint8_t remaining_length; remaining_length = data_length; Usb_select_endpoint(ep_num); while(Is_usb_read_enabled() && (0 != remaining_length)) { *rbuf = Usb_read_byte(); remaining_length--; rbuf++; } return remaining_length; }
//! usb_read_packet. //! //! This function moves the data stored in the selected endpoint fifo to //! the address specified by *rbuf. //! //! //! @param ep_num number of the addressed endpoint //! @param *rbuf aaddress of the first data to write with the USB data //! @param data_length number of bytes to read //! //! @return address of the next U8 to send. //! //! Example: //! while(!(Usb_rx_complete)); // wait new packet received //! usb_read_packet(4,&first_data,usb_get_nb_byte); // read packet from ep 4 //! Usb_clear_rx(); // acknowledge the transmit //! //! Note: //! rbuf is incremented of 'data_length'. //! U8 usb_read_packet(U8 ep_num, U8* rbuf, U8 data_length) { U8 remaining_length; remaining_length = data_length; Usb_select_endpoint(ep_num); while(Is_usb_read_enabled() && (0 != remaining_length)) { *rbuf = Usb_read_byte(); remaining_length--; rbuf++; } return remaining_length; }
/** * @brief This function sends the data stored in the USB transmit buffer. * This function does nothing if there is no data in the buffer. */ void uart_usb_flush (void) { if(tx_counter) { // Preserve the currently selected endpoint uint8_t uenum = Usb_get_selected_endpoint(); Usb_select_endpoint(VCP_TX_EP); Usb_send_in(); tx_counter = 0; usb_endpoint_wait_for_IN_ready(); // Restore previously selected endpoint UENUM = uenum; } }
/** * @brief This function checks if a character has been received on the USB bus. * * @return bit (true if a byte is ready to be read) */ bit uart_usb_test_hit(void) { if (!rx_counter) { // Preserve the currently selected endpoint uint8_t uenum = Usb_get_selected_endpoint(); Usb_select_endpoint(VCP_RX_EP); if (Is_usb_receive_out()) { rx_counter = Usb_byte_counter(); if (!rx_counter) Usb_ack_receive_out(); } // Restore previously selected endpoint UENUM = uenum; } return (rx_counter!=0); }
/** * @brief This function checks if a character has been received on the USB bus. * * @return bit (true if a byte is ready to be read) */ bit uart_usb_test_hit(void) { if(!Is_device_enumerated()) return FALSE; if (!rx_counter) { Usb_select_endpoint(RX_EP); if (Is_usb_receive_out()) { rx_counter = Usb_byte_counter(); if (!rx_counter) { Usb_ack_receive_out(); } } } return (rx_counter!=0); }
//! usb_init_device. //! //! This function initializes the USB device controller and //! configures the Default Control Endpoint. //! //! @returns Zero is returned if the device could not be initialized. A non-zero, //! positive number is returned if the initialization was successful. uint8_t usb_init_device (void) { Usb_select_device(); if(Is_usb_id_device()) { Usb_select_endpoint(EP_CONTROL); if(!Is_usb_endpoint_enabled()) { return usb_configure_endpoint(EP_CONTROL, \ TYPE_CONTROL, \ DIRECTION_OUT, \ SIZE_64, \ ONE_BANK, \ NYET_DISABLED); } } return false; }
int USB::write(char* buf, int len) { if(!isEnumerated()) return 0; Usb_select_endpoint(EP_TEMP_IN); //if(!canSend()) // return 0; char* ptr = buf; for(int i = 0; i<len; i++) Usb_write_byte(*ptr++); for(int i; i<EP_IN_LENGTH_TEMP1; i++) Usb_write_byte(0); Usb_ack_in_ready(); return len; }
int USB::read(char* buf, int len) { if(!isEnumerated()) return 0; Usb_select_endpoint(EP_TEMP_OUT); if(!hasData()) return 0; U16 num = Usb_byte_counter(); if(len < num) num = len; char* ptr = buf; for(U16 i = num; i; i--) *ptr++ = Usb_read_byte(); Usb_ack_receive_out(); return num; }
//! @brief Get data report from Host //! void hid_report_out(void) { Usb_select_endpoint(EP_HID_OUT); if(Is_usb_receive_out()) { //Message Definition //Section //Instruction //Flags //Flags //datalength //Retrieve message parts unsigned char section, instruction, dataLength, flagH, flagL, i; section = Usb_read_byte(); instruction = Usb_read_byte(); flagL = Usb_read_byte(); flagH = Usb_read_byte(); dataLength = Usb_read_byte(); for(i = 0; i < HID_OUT_DATAPACKET_LENGTH; i++) //copy datapacket to global buffer hid_OUT_dataPkt[i] = Usb_read_byte(); //handle message sectionCall(section, instruction, &hid_OUT_dataPkt[0], dataLength); //ack message Usb_ack_receive_out(); } // //** Check if we received DFU mode command from host // if(jump_bootloader) // { // U32 volatile tempo; // Leds_off(); // Usb_detach(); // Detach actual generic HID application // for(tempo=0;tempo<70000;tempo++); // Wait some time before // start_boot(); // Jumping to booltoader // } }
uint8_t cdc_ecm_process(void) { static uint8_t doInit = 1; Usb_select_endpoint(RX_EP); if(!Is_usb_endpoint_enabled()) { return 0; } if (doInit) { #ifdef USB_ETH_HOOK_INIT USB_ETH_HOOK_INIT(); #endif cdc_ecm_notify_network_connection(1); cdc_ecm_notify_connection_speed_change(250000,250000); doInit = 0; if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) { #if RF230BB rf230_set_promiscuous_mode(true); #else radio_set_trx_state(RX_ON); #endif } // Select again, just to make sure. Usb_select_endpoint(RX_EP); } if(!usb_eth_is_active) { // If we aren't active, just eat the packets. if(Is_usb_read_enabled()) { Usb_ack_receive_out(); } return 0; } //Connected! Led0_on(); if(Is_usb_read_enabled()) { uint16_t bytecounter; uint16_t bytes_received = 0; U8 * buffer = uip_buf; if(!usb_eth_ready_for_next_packet()) { // Since we aren't ready for a packet yet, // just return. goto bail; } #ifdef USB_ETH_HOOK_RX_START USB_ETH_HOOK_RX_START(); #endif while((bytecounter=Usb_byte_counter_8())==CDC_ECM_DATA_ENDPOINT_SIZE) { while((bytes_received<USB_ETH_MTU) && (bytecounter--)) { *buffer++ = Usb_read_byte(); bytes_received++; } bytes_received+=bytecounter+1; //ACK previous data Usb_ack_receive_out(); //Wait for new data if(usb_endpoint_wait_for_read_enabled()!=0) { USB_ETH_HOOK_RX_ERROR("Timeout: read enabled"); goto bail; } } bytecounter = Usb_byte_counter_8(); while((bytes_received<USB_ETH_MTU) && (bytecounter--)) { *buffer++ = Usb_read_byte(); bytes_received++; } bytes_received+=bytecounter+1; //Ack final data packet Usb_ack_receive_out(); //PRINTF_P(PSTR("cdc_ecm: Got packet %d bytes long\n"),bytes_received); #ifdef USB_ETH_HOOK_RX_END USB_ETH_HOOK_RX_END(); #endif //Send data over RF or to local stack if(bytes_received<=USB_ETH_MTU) { USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,bytes_received); } else { USB_ETH_HOOK_RX_ERROR("Oversized packet"); } } bail: return 1; }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else goto user_read; break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else goto user_read; break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else goto user_read; break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else goto user_read; break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else goto user_read; break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else goto user_read; break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else goto user_read; break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else goto user_read; break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request user_read: usb_user_read_request(bmRequestType, bmRequest); break; } Usb_select_endpoint(EP_CONTROL); // If the receive setup flag hasn't been cleared // by this point then we can assume that we didn't // support this request and should stall. if(Is_usb_receive_setup()) Usb_enable_stall_handshake(); // Clear some flags. Usb_ack_receive_setup(); Usb_ack_receive_out(); Usb_ack_in_ready(); }
//! usb_clear_feature. //! //! This function manages the SET FEATURE request. //! //! @warning Code:xx bytes (function code length) //! //! @param none //! //! @return none //! void usb_clear_feature(void) { U8 wValue; U8 wIndex; U8 dummy; if (bmRequestType == ZERO_TYPE) { //!< keep that order (set StallRq/clear RxSetup) or a //!< OUT request following the SETUP may be acknowledged Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } else if (bmRequestType == INTERFACE_TYPE) { //!< keep that order (set StallRq/clear RxSetup) or a //!< OUT request following the SETUP may be acknowledged Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } else if (bmRequestType == ENDPOINT_TYPE) { wValue = Usb_read_byte(); dummy = Usb_read_byte(); //!< dummy read if (wValue == FEATURE_ENDPOINT_HALT) { wIndex = (Usb_read_byte() & MSK_EP_DIR); Usb_select_endpoint(wIndex); if(Is_usb_endpoint_enabled()) { if(wIndex != EP_CONTROL) { Usb_disable_stall_handshake(); Usb_reset_endpoint(wIndex); Usb_reset_data_toggle(); } Usb_select_endpoint(EP_CONTROL); endpoint_status[wIndex] = 0x00; Usb_ack_receive_setup(); Usb_send_control_in(); } else { Usb_select_endpoint(EP_CONTROL); Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } } else { Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } } }
//! usb_halt_endpoint. //! //! This function sends a STALL handshake for the next Host request. A STALL //! handshake will be send for each next request untill a SETUP or a Clear Halt //! Feature occurs for this endpoint. //! //! @param ep_num number of the addressed endpoint //! //! @return none //! void usb_halt_endpoint (U8 ep_num) { Usb_select_endpoint(ep_num); Usb_enable_stall_handshake(); }
/** * @brief This function checks if the USB emission buffer is ready to accept at * at least 1 byte * * @retval TRUE if the firmware can write a new byte to transmit. * @retval FALSE otherwise */ bit uart_usb_tx_ready(void) { Usb_select_endpoint(VCP_TX_EP); return !!Is_usb_write_enabled(); }
//! @brief Entry point of the USB device mamagement //! //! This function is the entry point of the USB management. Each USB //! event is checked here in order to launch the appropriate action. //! If a Setup request occurs on the Default Control Endpoint, //! the usb_process_request() function is call in the usb_standard_request.c file //! //! @param none //! //! @return none void usb_device_task(void) { #if (USB_OTG_FEATURE == ENABLED) // Check if a reset has been received if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; otg_b_device_state = B_IDLE; Clear_otg_features_from_host(); } // When OTG mode enabled, B-Device is managed thanks to its state machine switch (otg_b_device_state) { //------------------------------------------------------ // B_IDLE state // // - waits for Vbus to rise // - initiate SRP if asked by user // case B_IDLE: if (Is_usb_vbus_high()) { // Vbus rise usb_connected = TRUE; remote_wakeup_feature = DISABLED; usb_start_device(); Usb_vbus_on_action(); Usb_attach(); otg_b_device_state = B_PERIPHERAL; Ack_user_request_srp(); Clear_otg_features_from_host(); remote_wakeup_feature = DISABLED; End_session_with_srp(); if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } Usb_enable_sof_interrupt(); } else { if (Is_user_requested_srp() && Is_usb_id_device()) { // User has requested a SRP Ack_user_request_srp(); if (!Is_srp_sent_and_waiting_answer()) { Pll_start_auto(); // reinit device mode Wait_pll_ready(); Usb_disable(); Usb_enable_uid_pin(); Usb_enable(); Usb_unfreeze_clock(); Usb_select_device(); Usb_attach(); otg_b_device_state = B_SRP_INIT; Usb_device_initiate_srp(); // hardware waits for initial condition (SE0, Session End level) sof_seen_in_session = FALSE; } } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } } break; //------------------------------------------------------ // B_SRP_INIT // // - a SRP has been initiated // - B-Device waits it is finished to initialize variables // case B_SRP_INIT: if (!Is_usb_device_initiating_srp()) { otg_b_device_state = B_IDLE; // SRP initiated, return to Idle state (wait for Vbus to rise) Srp_sent_and_waiting_answer(); Init_tb_srp_counter(); Start_session_with_srp(); Otg_print_new_event_message(OTGMSG_SRP_STARTED,TB_SRP_FAIL_MIN); } break; //------------------------------------------------------ // B_PERIPHERAL : the main state of OTG Peripheral // // - all events are interrupt-handled // - but they are saved and this function can execute alternate actions // - also handle user requests (disconnect) // // ====================================================================================== case B_PERIPHERAL: if (Is_otg_event(EVT_OTG_DEVICE_CONNECTED)) { Otg_ack_event(EVT_OTG_DEVICE_CONNECTED); // set on a SetConfiguration descriptor reception Otg_print_new_event_message(OTGMSG_CONNECTED_TO_A,OTG_TEMPO_4SEC); } if (Is_usb_event(EVT_USB_SUSPEND)) // SUSPEND state { // Suspend and HNP operations are handled in the interrupt functions } if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } if (Is_usb_event(EVT_USB_RESUME) && !Is_usb_pending_remote_wake_up()) // RESUME signal detected { Usb_ack_event(EVT_USB_RESUME); Usb_ack_event(EVT_USB_SUSPEND); Usb_ack_remote_wake_up_start(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Clear_all_user_request(); otg_b_device_state = B_IDLE; } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; Clear_otg_features_from_host(); } if (Is_otg_event(EVT_OTG_HNP_ERROR)) { Otg_ack_event(EVT_OTG_HNP_ERROR); Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC); PORTC &= ~0x10; } if (Is_user_requested_disc()) { Ack_user_request_disc(); if (Is_usb_id_device()) { Usb_detach(); Usb_freeze_clock(); while (Is_usb_vbus_high()); // wait for Vbus to be under Va_vbus_valid otg_b_device_state = B_IDLE; usb_configuration_nb = 0; usb_connected = FALSE; Clear_all_user_request(); } } break; //------------------------------------------------------ // B_HOST // // - state entered after an HNP success // - handle user requests (disconnection, suspend, hnp) // - call the "host_task()" for Host level handlers // // ====================================================================================== case B_HOST: if (Is_otg_event(EVT_OTG_DEV_UNSUPPORTED)) { Otg_ack_event(EVT_OTG_DEV_UNSUPPORTED); Clear_all_user_request(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } if (Is_user_requested_disc() || Is_user_requested_suspend() || Is_user_requested_hnp()) { Ack_user_request_disc(); // suspend and hnp requests cleared in B_END_HNP_SUSPEND stage Host_disable_sof(); // go into suspend mode Usb_host_reject_hnp(); otg_b_device_state = B_END_HNP_SUSPEND; Usb_ack_suspend(); Usb_enable_suspend_interrupt(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Usb_freeze_clock(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } usb_host_task(); // call the host task break; //------------------------------------------------------ // B_END_HNP_SUSPEND // // - device enters this state after being B_HOST, on a user request to stop bus activity (suspend, disconnect or hnp request) // - macro is reset to peripheral mode // // ====================================================================================== case B_END_HNP_SUSPEND: if (Is_usb_event(EVT_USB_SUSPEND)) { Usb_ack_event(EVT_USB_SUSPEND); Usb_device_stop_hnp(); Usb_select_device(); device_state = DEVICE_UNATTACHED; if (Is_user_requested_hnp() || Is_user_requested_suspend()) { otg_b_device_state = B_PERIPHERAL; Ack_user_request_suspend(); Ack_user_request_hnp(); } else { otg_b_device_state = B_IDLE; Usb_detach(); Usb_freeze_clock(); } } break; default: otg_b_device_state = B_IDLE; Clear_all_user_request(); device_state = DEVICE_UNATTACHED; break; } #else // Non-OTG exclusives Device operations // VBUS state detection if (Is_usb_vbus_high()&& (usb_connected==FALSE)) { usb_connected = TRUE; remote_wakeup_feature = DISABLED; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); usb_start_device(); } if (Is_usb_vbus_low()&& (usb_connected==TRUE)) { usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_detach(); Usb_freeze_clock(); Usb_vbus_off_action(); } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; } #endif // ======================================= // Common Standard Device Control Requests // ======================================= // - device enumeration process // - device control commands and features Usb_select_endpoint(EP_CONTROL); if (Is_usb_receive_setup()) { usb_process_request(); } }