/** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or * getting a device parameter's value from the parameter table. * * \param[in] V2Command Issued V2 Protocol command byte from the host */ static void V2Protocol_GetSetParam(const uint8_t V2Command) { uint8_t ParamID = Endpoint_Read_Byte(); uint8_t ParamValue; if (V2Command == CMD_SET_PARAMETER) ParamValue = Endpoint_Read_Byte(); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); Endpoint_Write_Byte(V2Command); uint8_t ParamPrivs = V2Params_GetParameterPrivileges(ParamID); if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE)) { Endpoint_Write_Byte(STATUS_CMD_OK); V2Params_SetParameterValue(ParamID, ParamValue); } else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ)) { Endpoint_Write_Byte(STATUS_CMD_OK); Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID)); } else { Endpoint_Write_Byte(STATUS_CMD_FAILED); } Endpoint_ClearIN(); }
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific * control requests that are not handled internally by the USB library (including the HID commands, which are * all issued via the control endpoint), so that they can be handled appropriately for the application. */ void EVENT_USB_Device_UnhandledControlRequest(void) { uint8_t* ReportData; uint8_t ReportSize; /* Handle HID Class specific requests */ switch (USB_ControlRequest.bRequest) { case REQ_GetReport: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); /* Determine if it is the mouse or the keyboard data that is being requested */ if (!(USB_ControlRequest.wIndex)) { ReportData = (uint8_t*)&KeyboardReportData; ReportSize = sizeof(KeyboardReportData); } else { ReportData = (uint8_t*)&MouseReportData; ReportSize = sizeof(MouseReportData); } /* Write the report data to the control endpoint */ Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); /* Clear the report data afterwards */ memset(ReportData, 0, ReportSize); /* Finalize the stream transfer to send the last packet or clear the host abort */ Endpoint_ClearOUT(); } break; case REQ_SetReport: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); /* Wait until the LED report has been sent by the host */ while (!(Endpoint_IsOUTReceived())) { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } /* Read in and process the LED report from the host */ Keyboard_ProcessLEDReport(Endpoint_Read_Byte()); /* Clear the endpoint data */ Endpoint_ClearOUT(); Endpoint_ClearStatusStage(); } break; } }
uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length #if !defined(NO_STREAM_CALLBACKS) , uint8_t (* const Callback)(void) #endif ) { uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1); uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; while (Length--) { if (!(Endpoint_ReadWriteAllowed())) { Endpoint_ClearCurrentBank(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return ENDPOINT_RWSTREAM_ERROR_CallbackAborted; #endif if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; } *(DataStream--) = Endpoint_Read_Byte(); } return ENDPOINT_RWSTREAM_ERROR_NoError; }
/** Handler for the CMD_XPROG command, which wraps up XPROG commands in a V2 wrapper which need to be * removed and processed so that the underlying XPROG command can be handled. */ void XPROGProtocol_Command(void) { uint8_t XPROGCommand = Endpoint_Read_Byte(); switch (XPROGCommand) { case XPRG_CMD_ENTER_PROGMODE: XPROGProtocol_EnterXPROGMode(); break; case XPRG_CMD_LEAVE_PROGMODE: XPROGProtocol_LeaveXPROGMode(); break; case XPRG_CMD_ERASE: XPROGProtocol_Erase(); break; case XPRG_CMD_WRITE_MEM: XPROGProtocol_WriteMemory(); break; case XPRG_CMD_READ_MEM: XPROGProtocol_ReadMemory(); break; case XPRG_CMD_CRC: XPROGProtocol_ReadCRC(); break; case XPRG_CMD_SET_PARAM: XPROGProtocol_SetParam(); break; } }
void ecmd_lufa_rx(void) { /* Select the Serial Rx Endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); /* Check to see if a packet has been received from the host */ if (Endpoint_IsOUTReceived()) { /* Read the bytes in from the endpoint into the buffer while space is available */ while (Endpoint_BytesInEndpoint() && !must_parse) { /* Store each character from the endpoint */ uint8_t data = Endpoint_Read_Byte(); if (data == '\n' || data == '\r' || recv_len == sizeof(recv_buffer)) { recv_buffer[recv_len] = 0; must_parse = 1; } else { recv_buffer[recv_len++] = data; } } /* Check to see if all bytes in the current packet have been read */ if (!(Endpoint_BytesInEndpoint())) { /* Clear the endpoint buffer */ Endpoint_ClearOUT(); } } }
uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length #if !defined(NO_STREAM_CALLBACKS) , uint8_t (* const Callback)(void) #endif ) { uint8_t* DataStream = (uint8_t*)Buffer; uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; while (Length) { if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearOUT(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return ENDPOINT_RWSTREAM_CallbackAborted; #endif if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; } else { *(DataStream++) = Endpoint_Read_Byte(); Length--; } } return ENDPOINT_RWSTREAM_NoError; }
int8_t usbRecvByte(uint8_t *data) { #ifdef DEBUG if (usbDataDir != ENDPOINT_DIR_OUT) { DEBUGF(DBG_ERROR, "ERR: usbRecvByte when dir was %d\n", usbDataDir); return -1; } #endif /* * Check if the endpoint is currently empty. * If so, clear the endpoint bank to get more data from host and * wait until the host has sent data. */ if (!Endpoint_IsReadWriteAllowed()) { Endpoint_ClearOUT(); while (!Endpoint_IsReadWriteAllowed() && !doDeviceReset) ; } // Check if the current command is being aborted by the host if (doDeviceReset) { DEBUGF(DBG_ERROR, "rcvrst\n"); return -1; } // Read data from the host buffer, received via USB *data = Endpoint_Read_Byte(); usbDataLen--; return 0; }
/** Keyboard task. This generates the next keyboard HID report for the host, and transmits it via the * keyboard IN endpoint when the host is ready for more data. Additionally, it processes host LED status * reports sent to the device via the keyboard OUT reporting endpoint. */ void Keyboard_HID_Task(void) { uint8_t JoyStatus_LCL = Joystick_GetStatus(); /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Check if board button is not pressed, if so mouse mode enabled */ if (!(Buttons_GetStatus() & BUTTONS_BUTTON1)) { /* Make sent key uppercase by indicating that the left shift key is pressed */ KeyboardReportData.Modifier = KEYBOARD_MODIFER_LEFTSHIFT; if (JoyStatus_LCL & JOY_UP) KeyboardReportData.KeyCode[0] = 0x04; // A else if (JoyStatus_LCL & JOY_DOWN) KeyboardReportData.KeyCode[0] = 0x05; // B if (JoyStatus_LCL & JOY_LEFT) KeyboardReportData.KeyCode[0] = 0x06; // C else if (JoyStatus_LCL & JOY_RIGHT) KeyboardReportData.KeyCode[0] = 0x07; // D if (JoyStatus_LCL & JOY_PRESS) KeyboardReportData.KeyCode[0] = 0x08; // E } /* Select the Keyboard Report Endpoint */ Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); /* Check if Keyboard Endpoint Ready for Read/Write */ if (Endpoint_IsReadWriteAllowed()) { /* Write Keyboard Report Data */ Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData)); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); /* Clear the report data afterwards */ memset(&KeyboardReportData, 0, sizeof(KeyboardReportData)); } /* Select the Keyboard LED Report Endpoint */ Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM); /* Check if Keyboard LED Endpoint Ready for Read/Write */ if (Endpoint_IsReadWriteAllowed()) { /* Read in and process the LED report from the host */ Keyboard_ProcessLEDReport(Endpoint_Read_Byte()); /* Handshake the OUT Endpoint - clear endpoint and ready for next report */ Endpoint_ClearOUT(); } }
int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) { int8_t Sample; Sample = Endpoint_Read_Byte(); if (!(Endpoint_BytesInEndpoint())) Endpoint_ClearOUT(); return Sample; }
int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) { int32_t Sample; Sample = (((uint32_t)Endpoint_Read_Byte() << 16) | Endpoint_Read_Word_LE()); if (!(Endpoint_BytesInEndpoint())) Endpoint_ClearOUT(); return Sample; }
/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific * control requests that are not handled internally by the USB library, so that they can be handled appropriately * for the application. */ void EVENT_USB_Device_UnhandledControlRequest(void) { uint8_t* LineCodingData = (uint8_t*)&LineCoding; /* Process CDC specific control requests */ switch (USB_ControlRequest.bRequest) { case REQ_GetLineEncoding: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); for (uint8_t i = 0; i < sizeof(LineCoding); i++) Endpoint_Write_Byte(*(LineCodingData++)); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case REQ_SetLineEncoding: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); while (!(Endpoint_IsOUTReceived())) { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } for (uint8_t i = 0; i < sizeof(LineCoding); i++) *(LineCodingData++) = Endpoint_Read_Byte(); Endpoint_ClearOUT(); Endpoint_ClearStatusStage(); } break; case REQ_SetControlLineState: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); Endpoint_ClearStatusStage(); } break; } }
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo) { if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) return 0; Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); uint8_t DataByte = Endpoint_Read_Byte(); if (!(Endpoint_BytesInEndpoint())) Endpoint_ClearOUT(); return DataByte; }
int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) { if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) return -1; int16_t ReceivedByte = -1; Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); if (Endpoint_IsOUTReceived()) { if (Endpoint_BytesInEndpoint()) ReceivedByte = Endpoint_Read_Byte(); if (!(Endpoint_BytesInEndpoint())) Endpoint_ClearOUT(); } return ReceivedByte; }
uint8_t uart_recv(void) { do { if (usb_rxpacket_leftb) { uint8_t d; Endpoint_SelectEndpoint(CDC_RX_EPNUM); d = Endpoint_Read_Byte(); usb_rxpacket_leftb--; if (!usb_rxpacket_leftb) Endpoint_ClearOUT(); return d; } usb_process(); usb_rxpacket_leftb = CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface); if ((!usb_rxpacket_leftb)&&(usb_txpacket_leftb)) { Endpoint_SelectEndpoint(CDC_TX_EPNUM); Endpoint_ClearIN(); /* Go data, GO. */ usb_txpacket_leftb = 0; } } while (1); }
uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length) { uint8_t* DataStream = (uint8_t*)Buffer; while (Length) { if (Endpoint_IsOUTReceived()) { while (Length && Endpoint_BytesInEndpoint()) { *(DataStream++) = Endpoint_Read_Byte(); Length--; } Endpoint_ClearOUT(); } } while (!(Endpoint_IsINReady())); return ENDPOINT_RWCSTREAM_NoError; }
uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length) { uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1); while (Length) { while (!(Endpoint_IsSetupOUTReceived())); while (Length && Endpoint_BytesInEndpoint()) { *(DataStream--) = Endpoint_Read_Byte(); Length--; } Endpoint_ClearSetupOUT(); } while (!(Endpoint_IsSetupINReady())); return ENDPOINT_RWCSTREAM_ERROR_NoError; }
/** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host. * This routine decodes the issued command and passes off the handling of the command to the * appropriate function. */ void V2Protocol_ProcessCommand(void) { uint8_t V2Command = Endpoint_Read_Byte(); /* Start the timeout management timer */ TimeoutTicksRemaining = COMMAND_TIMEOUT_TICKS; TCCR0B = ((1 << CS02) | (1 << CS00)); switch (V2Command) { case CMD_SIGN_ON: V2Protocol_SignOn(); break; case CMD_SET_PARAMETER: case CMD_GET_PARAMETER: V2Protocol_GetSetParam(V2Command); break; case CMD_LOAD_ADDRESS: V2Protocol_LoadAddress(); break; case CMD_RESET_PROTECTION: V2Protocol_ResetProtection(); break; #if defined(ENABLE_ISP_PROTOCOL) case CMD_ENTER_PROGMODE_ISP: ISPProtocol_EnterISPMode(); break; case CMD_LEAVE_PROGMODE_ISP: ISPProtocol_LeaveISPMode(); break; case CMD_PROGRAM_FLASH_ISP: case CMD_PROGRAM_EEPROM_ISP: ISPProtocol_ProgramMemory(V2Command); break; case CMD_READ_FLASH_ISP: case CMD_READ_EEPROM_ISP: ISPProtocol_ReadMemory(V2Command); break; case CMD_CHIP_ERASE_ISP: ISPProtocol_ChipErase(); break; case CMD_READ_FUSE_ISP: case CMD_READ_LOCK_ISP: case CMD_READ_SIGNATURE_ISP: case CMD_READ_OSCCAL_ISP: ISPProtocol_ReadFuseLockSigOSCCAL(V2Command); break; case CMD_PROGRAM_FUSE_ISP: case CMD_PROGRAM_LOCK_ISP: ISPProtocol_WriteFuseLock(V2Command); break; case CMD_SPI_MULTI: ISPProtocol_SPIMulti(); break; #endif #if defined(ENABLE_XPROG_PROTOCOL) case CMD_XPROG_SETMODE: XPROGProtocol_SetMode(); break; case CMD_XPROG: XPROGProtocol_Command(); break; #endif default: V2Protocol_UnknownCommand(V2Command); break; } /* Disable the timeout management timer */ TCCR0B = 0; Endpoint_WaitUntilReady(); Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); }
void USB_Device_ProcessControlRequest(void) { uint8_t* RequestHeader = (uint8_t*)&USB_ControlRequest; for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++) *(RequestHeader++) = Endpoint_Read_Byte(); EVENT_USB_Device_ControlRequest(); if (Endpoint_IsSETUPReceived()) { uint8_t bmRequestType = USB_ControlRequest.bmRequestType; switch (USB_ControlRequest.bRequest) { case REQ_GetStatus: if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) || (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT))) { USB_Device_GetStatus(); } break; case REQ_ClearFeature: case REQ_SetFeature: if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) || (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT))) { USB_Device_ClearSetFeature(); } break; case REQ_SetAddress: if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) USB_Device_SetAddress(); break; case REQ_GetDescriptor: if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) || (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE))) { USB_Device_GetDescriptor(); } break; case REQ_GetConfiguration: if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) USB_Device_GetConfiguration(); break; case REQ_SetConfiguration: if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) USB_Device_SetConfiguration(); break; } } if (Endpoint_IsSETUPReceived()) { Endpoint_StallTransaction(); Endpoint_ClearSETUP(); } }
/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */ void CDC_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; #if 0 /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232 handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code: */ USB_Notification_Header_t Notification = (USB_Notification_Header_t) { .NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), .Notification = NOTIF_SerialState, .wValue = 0, .wIndex = 0, .wLength = sizeof(uint16_t), }; uint16_t LineStateMask; // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM); Endpoint_Write_Stream_LE(&Notification, sizeof(Notification)); Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask)); Endpoint_ClearIN(); #endif /* Select the Serial Rx Endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); /* Check to see if a packet has been received from the host */ if (Endpoint_IsOUTReceived()) { /* Read the bytes in from the endpoint into the buffer while space is available */ while (Endpoint_BytesInEndpoint() && (Rx_Buffer.Elements != BUFF_STATICSIZE)) { /* Store each character from the endpoint */ Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte()); } /* Check to see if all bytes in the current packet have been read */ if (!(Endpoint_BytesInEndpoint())) { /* Clear the endpoint buffer */ Endpoint_ClearOUT(); } } /* Check if Rx buffer contains data - if so, send it */ if (Rx_Buffer.Elements) Serial_TxByte(Buffer_GetElement(&Rx_Buffer)); /* Select the Serial Tx Endpoint */ Endpoint_SelectEndpoint(CDC_TX_EPNUM); /* Check if the Tx buffer contains anything to be sent to the host */ if ((Tx_Buffer.Elements) && LineEncoding.BaudRateBPS) { /* Wait until Serial Tx Endpoint Ready for Read/Write */ Endpoint_WaitUntilReady(); /* Write the bytes from the buffer to the endpoint while space is available */ while (Tx_Buffer.Elements && Endpoint_IsReadWriteAllowed()) { /* Write each byte retreived from the buffer to the endpoint */ Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer)); } /* Remember if the packet to send completely fills the endpoint */ bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE); /* Send the data */ Endpoint_ClearIN(); /* If no more data to send and the last packet filled the endpoint, send an empty packet to release * the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */ if (IsFull && !(Tx_Buffer.Elements)) { /* Wait until Serial Tx Endpoint Ready for Read/Write */ Endpoint_WaitUntilReady(); /* Send an empty packet to terminate the transfer */ Endpoint_ClearIN(); } } } /** ISR to handle the USART receive complete interrupt, fired each time the USART has received a character. This stores the received * character into the Tx_Buffer circular buffer for later transmission to the host. */ ISR(USART1_RX_vect, ISR_BLOCK) { uint8_t ReceivedByte = UDR1; /* Only store received characters if the USB interface is connected */ if ((USB_DeviceState == DEVICE_STATE_Configured)) {// && LineEncoding.BaudRateBPS Buffer_StoreElement(&Tx_Buffer, ReceivedByte); } }
//////////////////// // Fill data from USB to the RingBuffer and vice-versa void CDC_Task(void) { static char inCDC_TASK = 0; if(!USB_IsConnected) return; #ifdef ARM if(!inCDC_TASK){ // USB -> RingBuffer inCDC_TASK = 1; output_flush_func = CDC_Task; input_handle_func(DISPLAY_USB); inCDC_TASK = 0; } if(TTY_Tx_Buffer.nbytes) { uint16_t i=0; while(TTY_Tx_Buffer.nbytes && i<DATABUFFERSIZEOUT) { usbBufferOut[i++]=rb_get(&TTY_Tx_Buffer); } while (CDCDSerialDriver_Write(usbBufferOut,i, 0, 0) != USBD_STATUS_SUCCESS); } #else Endpoint_SelectEndpoint(CDC_RX_EPNUM); // First data in if(!inCDC_TASK && Endpoint_ReadWriteAllowed()){ // USB -> RingBuffer while (Endpoint_BytesInEndpoint()) { // Discard data on buffer full rb_put(&TTY_Rx_Buffer, Endpoint_Read_Byte()); } Endpoint_ClearCurrentBank(); inCDC_TASK = 1; output_flush_func = CDC_Task; input_handle_func(DISPLAY_USB); inCDC_TASK = 0; } Endpoint_SelectEndpoint(CDC_TX_EPNUM); // Then data out if(TTY_Tx_Buffer.nbytes && Endpoint_ReadWriteAllowed()) { cli(); while(TTY_Tx_Buffer.nbytes && (Endpoint_BytesInEndpoint() < USB_BUFSIZE)) Endpoint_Write_Byte(rb_get(&TTY_Tx_Buffer)); sei(); Endpoint_ClearCurrentBank(); // Send the data } #endif }