/** * @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(); } }
// this function should be continuously called void my_uart_usb_send_to_endpoint(void){ static uint8_t zlp=FALSE; /* zero load packet */ static uint8_t local_buffer[TX_EP_SIZE]; uint16_t num_read; bit ret; if(!Is_device_enumerated()) return; // make atomic, this will be fixed by interrupts Usb_select_endpoint(TX_EP); if(Is_usb_write_enabled()==FALSE) // Only if endpoint ready return; if(line_status.DTR == 0){ Usb_ack_in_ready(); return; } // we send in chunks of TX_EP_SIZE num_read = TX_EP_SIZE; ret = circ_buffer_get_nbytes(&my_uart_usb_tx_buffer, local_buffer, &num_read); if(num_read == 0 && zlp == TRUE){ Usb_ack_in_ready(); zlp = FALSE; Usb_disable_in_ready_interrupt(); // Nothing left to send, disable this until next time return; } // if we got exactly TX_EP_SIZE bytes, we should send zlp the next time if we send 0 if(ret == PASS){ zlp = TRUE; //Usb_enable_in_ready_interrupt(); // We don't need to do this since this is inside an interrupt. } else{ // this is the second pass and we didn't get a full TX_EP_SIZE bytes so the buffer is not full zlp = FALSE; } // write to the endpoint uint16_t nb_data = 0; Usb_select_endpoint(TX_EP); while(nb_data < num_read) { Usb_write_byte(local_buffer[nb_data]); nb_data++; } Usb_ack_in_ready(); cdc_update_serial_state(); // I really do not know what this does, it could have been an old artifact from usart usb // if(usb_request_break_generation == TRUE) // usb_request_break_generation = FALSE; }
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; }
//! 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(); }
//! usb_get_configuration. //! //! This function manages the GET CONFIGURATION request. The current //! configuration number is returned. //! //! @warning Code:xx bytes (function code length) //! //! @param none //! //! @return none //! void usb_get_configuration(void) { Usb_ack_receive_setup(); Usb_write_byte(usb_configuration_nb); Usb_ack_in_ready(); while( !Is_usb_receive_out() ); Usb_ack_receive_out(); }
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; }
//! 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(); }