uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, const MIDI_EventPacket_t* const Event) { if (USB_DeviceState != DEVICE_STATE_Configured) return ENDPOINT_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber); if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != ENDPOINT_RWSTREAM_NoError) return ErrorCode; if (!(Endpoint_IsReadWriteAllowed())) Endpoint_ClearIN(); return ENDPOINT_RWSTREAM_NoError; }
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); if (Endpoint_IsReadWriteAllowed()) { if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) { if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo); MSInterfaceInfo->State.CommandStatus.Status = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail; MSInterfaceInfo->State.CommandStatus.Signature = CPU_TO_LE32(MS_CSW_SIGNATURE); MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag; MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength; if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue))) Endpoint_StallTransaction(); MS_Device_ReturnCommandStatus(MSInterfaceInfo); } } if (MSInterfaceInfo->State.IsMassStoreReset) { Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); MSInterfaceInfo->State.IsMassStoreReset = false; } }
/** Reads data from the host */ void ReceiveDataFromHost(void) { /* Select the OUT Endpoint */ Endpoint_SelectEndpoint(OUT_EP); /* Check if the OUT EP contains a packet */ if (Endpoint_IsOUTReceived()) { /* Check to see if the packet contains data */ if (Endpoint_IsReadWriteAllowed()) { /* Read in data from the host */ Endpoint_Read_Stream_LE(&dataReceived, sizeof(dataReceived)); } /* Handshake the OUT Endpoint - clear endpoint and get ready for next transfer */ Endpoint_ClearOUT(); } }
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data) { if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) return ENDPOINT_RWSTREAM_DeviceDisconnected; Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) return ErrorCode; } Endpoint_Write_Byte(Data); return ENDPOINT_READYWAIT_NoError; }
/** Mouse task. This generates the next mouse HID report for the host, and transmits it via the * mouse IN endpoint when the host is ready for more data. */ void Mouse_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 pressed, if so mouse mode enabled */ if (Buttons_GetStatus() & BUTTONS_BUTTON1) { if (JoyStatus_LCL & JOY_UP) MouseReportData.Y = 1; else if (JoyStatus_LCL & JOY_DOWN) MouseReportData.Y = -1; if (JoyStatus_LCL & JOY_RIGHT) MouseReportData.X = 1; else if (JoyStatus_LCL & JOY_LEFT) MouseReportData.X = -1; if (JoyStatus_LCL & JOY_PRESS) MouseReportData.Button = (1 << 0); } /* Select the Mouse Report Endpoint */ Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); /* Check if Mouse Endpoint Ready for Read/Write */ if (Endpoint_IsReadWriteAllowed()) { /* Write Mouse Report Data */ Endpoint_Write_Stream_LE(&MouseReportData, sizeof(MouseReportData)); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); /* Clear the report data afterwards */ memset(&MouseReportData, 0, sizeof(MouseReportData)); } }
uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo, const uint8_t Data) { if (USB_DeviceState != DEVICE_STATE_Configured) return ENDPOINT_RWSTREAM_DeviceDisconnected; Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address); if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) return ErrorCode; } Endpoint_Write_8(Data); return ENDPOINT_READYWAIT_NoError; }
static void tx_task(void) { if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(OUT_EPADDR); if (Endpoint_IsOUTReceived() && csma_tx_allowed() && spi_tx_prepare()) { if (Endpoint_IsReadWriteAllowed()) { if (!(data[front].flags & FLAG_TX_READY)) { Endpoint_Read_Stream_LE(&data[front], sizeof(data[front]), NULL); data[front].flags |= FLAG_TX_READY; adf_set_tx_mode(); spi_tx_start(); } else { Endpoint_Read_Stream_LE(&data[back], sizeof(data[back]), NULL); data[back].flags |= FLAG_TX_READY; } Endpoint_ClearOUT(); } } }
void USBSerial::flush() { uint8_t prevEndpoint = Endpoint_GetCurrentEndpoint(); Endpoint_SelectEndpoint(CDC_TX_EPADDR); bool IsFull = !Endpoint_IsReadWriteAllowed(); Endpoint_ClearIN(); /* Send an empty packet to ensure that the host does not buffer data sent to it */ if (IsFull) { while (!Endpoint_IsINReady() && USB_DeviceState == DEVICE_STATE_Configured) { USB_USBTask(); } Endpoint_ClearIN(); } //Endpoint_WaitUntilReady(); while (!Endpoint_IsINReady() && USB_DeviceState == DEVICE_STATE_Configured) { USB_USBTask(); } Endpoint_SelectEndpoint(prevEndpoint); }
void usb_keyboard_press(uint8_t key, uint8_t modifier) { USB_KeyboardReport_Data_t KeyboardReportData; // setup keyboard report data memset(&KeyboardReportData, 0, sizeof(USB_KeyboardReport_Data_t)); // modifier KeyboardReportData.Modifier = modifier; KeyboardReportData.KeyCode[0] = key; Endpoint_SelectEndpoint(KEYBOARD_IN_EPADDR); if ( Endpoint_IsReadWriteAllowed() ) { Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(KeyboardReportData), NULL); Endpoint_ClearIN(); } _delay_ms(200); }
uint8_t Endpoint_Null_Stream(uint16_t Length, uint16_t* const BytesProcessed) { uint8_t ErrorCode; uint16_t BytesInTransfer = 0; if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; if (BytesProcessed != NULL) Length -= *BytesProcessed; while (Length) { if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); if (BytesProcessed != NULL) { *BytesProcessed += BytesInTransfer; return ENDPOINT_RWSTREAM_IncompleteTransfer; } if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; } else { Endpoint_Write_8(0); Length--; BytesInTransfer++; } } return ENDPOINT_RWSTREAM_NoError; }
/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */ void USB_Audio_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Check to see if the streaming interface is selected, if not the host is not receiving audio */ if (!(StreamingAudioInterfaceSelected)) return; /* Select the audio stream endpoint */ Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM); /* Check if the current endpoint can be written to and that the next sample should be stored */ if (Endpoint_IsINReady() && (TIFR0 & (1 << OCF0A))) { /* Clear the sample reload timer */ TIFR0 |= (1 << OCF0A); /* Audio sample is ADC value scaled to fit the entire range */ int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult()); #if defined(MICROPHONE_BIASED_TO_HALF_RAIL) /* Microphone is biased to half rail voltage, subtract the bias from the sample value */ AudioSample -= (SAMPLE_MAX_RANGE / 2); #endif /* Write the sample to the buffer */ Endpoint_Write_Word_LE(AudioSample); /* Check to see if the bank is now full */ if (!(Endpoint_IsReadWriteAllowed())) { /* Send the full packet to the host */ Endpoint_ClearIN(); } } }
uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer, uint16_t Length __CALLBACK_PARAM) { uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; #if defined(FAST_STREAM_TRANSFERS) uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07); if (Length >= 8) { Length -= BytesRemToAlignment; switch (BytesRemToAlignment) { default: do { if (!(Endpoint_IsReadWriteAllowed())) { TEMPLATE_CLEAR_ENDPOINT(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return ENDPOINT_RWSTREAM_CallbackAborted; #endif if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; } Length -= 8; TEMPLATE_TRANSFER_BYTE(DataStream); case 7: TEMPLATE_TRANSFER_BYTE(DataStream); case 6: TEMPLATE_TRANSFER_BYTE(DataStream); case 5: TEMPLATE_TRANSFER_BYTE(DataStream); case 4: TEMPLATE_TRANSFER_BYTE(DataStream); case 3: TEMPLATE_TRANSFER_BYTE(DataStream); case 2: TEMPLATE_TRANSFER_BYTE(DataStream); case 1: TEMPLATE_TRANSFER_BYTE(DataStream); } while (Length >= 8); } } #endif while (Length) { if (!(Endpoint_IsReadWriteAllowed())) { TEMPLATE_CLEAR_ENDPOINT(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return ENDPOINT_RWSTREAM_CallbackAborted; #endif if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; } else { TEMPLATE_TRANSFER_BYTE(DataStream); Length--; } } return ENDPOINT_RWSTREAM_NoError; }
void OnyxWalker_Task(void) { unsigned short now = MY_GetTicks(); if (now < lastTicks) { ++numWraps; LCD_DrawUint(numWraps, WIDTH-7, 3); } if (now - lastVolts > 15000) { lastVolts = now; ++voltBlink; if ((power_cvolts > 1320 && !power_failure) || (voltBlink & 1)) { LCD_DrawFrac(power_cvolts, 2, 0, 3); LCD_DrawChar(' ', 6, 3); LCD_DrawChar('V', 7, 3); PORTC &= ~(1 << 6); } else { LCD_DrawChar(' ', 0, 3); for (unsigned char i = 1; i != 8; ++i) { LCD_DrawChar('-', i, 3); } if (!(voltBlink & 15) && power_cvolts > 0) { PORTC |= (1 << 6); } else { PORTC &= ~(1 << 6); } } } lastTicks = now; LCD_Flush(); if (lastTicks - last_cvolts > 10000) { power_tick(); last_cvolts = lastTicks; } if (USB_DeviceState != DEVICE_STATE_Configured) { return; } /* see if host has requested data */ Endpoint_SelectEndpoint(DATA_RX_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); epic = Endpoint_IsConfigured(); epiir = epic && Endpoint_IsINReady(); epirwa = epiir && Endpoint_IsReadWriteAllowed(); if (epirwa && (in_packet_ptr || (now - last_flush > FLUSH_TICK_INTERVAL))) { last_flush = now; if (in_packet_ptr == 0) { in_packet_ptr = 1; // repeat the last received serial } // send packet in for (unsigned char ch = 0; ch < in_packet_ptr; ++ch) { Endpoint_Write_8(in_packet[ch]); } Endpoint_ClearIN(); in_packet_ptr = 0; } /* see if there's data from the host */ Endpoint_SelectEndpoint(DATA_TX_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); MY_SetLed(LED_act, false); if (Endpoint_IsConfigured() && Endpoint_IsOUTReceived() && Endpoint_IsReadWriteAllowed()) { uint8_t n = Endpoint_BytesInEndpoint(); if (n > sizeof(out_packet)) { MY_Failure("OUT too big", n, sizeof(out_packet)); } out_packet_ptr = 0; MY_SetLed(LED_act, true); while (n > 0) { epic = Endpoint_Read_8(); out_packet[out_packet_ptr++] = epic; --n; } Endpoint_ClearOUT(); dispatch_out(); } }
static bool USB_BulkWorker() { uint8_t cmdBuf[XUM_CMDBUF_SIZE], statusBuf[XUM_STATUSBUF_SIZE]; int8_t status; /* * If we are not connected to the host or a command has not yet * been sent, no more processing is required. */ if (USB_DeviceState != DEVICE_STATE_Configured) return false; Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT); if (!Endpoint_IsReadWriteAllowed()) return false; #ifdef DEBUG // Dump the status of both endpoints before getting the command Endpoint_SelectEndpoint(XUM_BULK_IN_ENDPOINT); DEBUGF(DBG_INFO, "bsti %x %x %x %x %x %x %x %x\n", Endpoint_GetCurrentEndpoint(), Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(), Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(), Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled()); Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT); DEBUGF(DBG_INFO, "bsto %x %x %x %x %x %x %x %x\n", Endpoint_GetCurrentEndpoint(), Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(), Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(), Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled()); #endif // Read in the command from the host now that one is ready. if (!USB_ReadBlock(cmdBuf, sizeof(cmdBuf))) { board_set_status(STATUS_ERROR); return false; } // Allow commands to leave the extended status untouched memset(statusBuf, 0, sizeof(statusBuf)); /* * Decode and process the command. * usbHandleBulk() stores its extended result in the output buffer, * up to XUM_STATUSBUF_SIZE. * * Return values: * >0: completed ok, send the return value and extended status * 0: completed ok, don't send any status * -1: error, no status */ status = usbHandleBulk(cmdBuf, statusBuf); if (status > 0) { statusBuf[0] = status; USB_WriteBlock(statusBuf, sizeof(statusBuf)); } else if (status < 0) { DEBUGF(DBG_ERROR, "usbblk err\n"); board_set_status(STATUS_ERROR); Endpoint_StallTransaction(); return false; } return true; }
uint8_t Endpoint_Discard_Stream(uint16_t Length #if !defined(NO_STREAM_CALLBACKS) , StreamCallbackPtr_t Callback #endif ) { uint8_t ErrorCode; if ((ErrorCode = Endpoint_WaitUntilReady())) return ErrorCode; #if defined(FAST_STREAM_TRANSFERS) uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07); if (Length >= 8) { Length -= BytesRemToAlignment; switch (BytesRemToAlignment) { default: do { 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; } Length -= 8; Endpoint_Discard_Byte(); case 7: Endpoint_Discard_Byte(); case 6: Endpoint_Discard_Byte(); case 5: Endpoint_Discard_Byte(); case 4: Endpoint_Discard_Byte(); case 3: Endpoint_Discard_Byte(); case 2: Endpoint_Discard_Byte(); case 1: Endpoint_Discard_Byte(); } while (Length >= 8); } } #endif 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 { Endpoint_Discard_Byte(); Length--; } } return ENDPOINT_RWSTREAM_NoError; }
void hidTask(void) { // Only process HID tasks if the device is configured and ready if (USB_DeviceState != DEVICE_STATE_Configured) return; // GenericHID ------------------------------------------------------------- // Select the OUT end-point Endpoint_SelectEndpoint(GENERIC_OUT_EPADDR); // Check to see if a packet has been sent from the host and we have nothing waiting to send if (Endpoint_IsOUTReceived() && waitingToSend == 0) { #ifdef USART_DEBUG printf("Packet received on OUT End-point\r\n"); #endif // Check to see if the end-point is ready for reading if (Endpoint_IsReadWriteAllowed()) { // Read the report data from the control end-point Endpoint_Read_Stream_LE(&hidReceiveBuffer, sizeof(hidReceiveBuffer), NULL); #ifdef USART_DEBUG uint8_t counter; printf("Dumping hex from OUT End-point (from host)\r\n"); for (counter = 0; counter < GENERIC_EPSIZE; counter++) { printf("%02x ", hidReceiveBuffer[counter]); if (!((counter+1) % 8)) printf("\r\n"); } printf("\r\n"); #endif // Process GenericHID packet header switch(hidReceiveBuffer[0]) { // Command group 0x01: System command group case RPF_COMMANDGROUP_SYSTEM: #ifdef USART_DEBUG printf("Command group 0x01: System command group\r\n"); #endif waitingToSend = systemCommandGroup(hidReceiveBuffer, hidSendBuffer); break; // Command group 0x02: Input/output command group case RPF_COMMANDGROUP_IO: #ifdef USART_DEBUG printf("Command group 0x02: Input/output command group\r\n"); #endif break; // Command group 0x03: ADC command group case RPF_COMMANDGROUP_ADC: #ifdef USART_DEBUG printf("Command group 0x03: ADC command group\r\n"); #endif break; // Command group 0x04: User defined command group case RPF_COMMANDGROUP_USER: #ifdef USART_DEBUG printf("Command group 0x04: User defined command group\r\n"); #endif break; // Command group 0x05: PWM command group case RPF_COMMANDGROUP_PWM: #ifdef USART_DEBUG printf("Command group 0x05: PWM command group\r\n"); #endif break; // Command group 0x06: SPI command group case RPF_COMMANDGROUP_SPI: #ifdef USART_DEBUG printf("Command group 0x06: SPI command group\r\n"); #endif break; // Command group 0x07: I2C command group case RPF_COMMANDGROUP_I2C: #ifdef USART_DEBUG printf("Command group 0x07: I2C command group\r\n"); #endif break; // Command group 0x08: USART command group case RPF_COMMANDGROUP_USART: #ifdef USART_DEBUG printf("Command group 0x08: USART command group\r\n"); #endif break; default: #ifdef USART_DEBUG printf("Host requested non-existent command group %d\r\n", hidReceiveBuffer[0]); #endif break; } } // Finalize the stream transfer to send the last packet Endpoint_ClearOUT(); } // Select the IN end-point Endpoint_SelectEndpoint(GENERIC_IN_EPADDR); // Check to see if the host is ready to accept another packet and that we have one to send if (Endpoint_IsINReady() && waitingToSend == 1) { #ifdef USART_DEBUG printf("Sending packet on IN End-point\r\n"); #endif // Write Generic Report Data Endpoint_Write_Stream_LE(&hidSendBuffer, sizeof(hidSendBuffer), NULL); // Finalize the stream transfer to send the last packet Endpoint_ClearIN(); // Clear the waiting to send flag waitingToSend = 0; // Turn on the Tx activity indicator activityIndicatorTx = 1; #ifdef USART_DEBUG uint8_t counter; printf("Dumping hex from IN End-point (to host)\r\n"); for (counter = 0; counter < GENERIC_EPSIZE; counter++) { printf("%02x ", hidSendBuffer[counter]); if (!((counter+1) % 8)) printf("\r\n"); } printf("\r\n"); #endif } // Joystick --------------------------------------------------------------- // Select the Joystick Report End-point Endpoint_SelectEndpoint(JOYSTICK_EPADDR); // Check to see if the host is ready for another joystick packet if (Endpoint_IsINReady()) { USB_JoystickReport_Data_t joystickReportData; // Create the next HID report to send to the host generateJoystickReport(&joystickReportData); // Write Joystick Report Data Endpoint_Write_Stream_LE(&joystickReportData, sizeof(joystickReportData), NULL); // Finalize the stream transfer to send the last packet Endpoint_ClearIN(); // Clear the report data afterwards */ memset(&joystickReportData, 0, sizeof(joystickReportData)); } }
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address * and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual * reading and writing of the data. * * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with * \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE) * * \return Boolean true if the command completed successfully, false otherwise. */ static bool SCSI_Command_ReadWrite_10 (USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead) { uint32_t BlockAddress; uint16_t TotalBlocks; //uint8_t buffer[VIRTUAL_MEMORY_BLOCK_SIZE]; /* Check if the disk is write protected or not */ if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY) { /* Block address is invalid, update SENSE key and return command fail */ SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT, SCSI_ASENSE_WRITE_PROTECTED, SCSI_ASENSEQ_NO_QUALIFIER); return false; } /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ //BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = (MSInterfaceInfo->State.CommandBlock.SCSICommandData[2] << 24) + (MSInterfaceInfo->State.CommandBlock.SCSICommandData[3] << 16) + (MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] << 8) + MSInterfaceInfo->State.CommandBlock.SCSICommandData[5]; /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */ //TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]); TotalBlocks = (MSInterfaceInfo->State.CommandBlock.SCSICommandData[7] << 8) + MSInterfaceInfo->State.CommandBlock.SCSICommandData[8]; /* Check if the block address is outside the maximum allowable value for the LUN */ if (BlockAddress >= LUN_MEDIA_BLOCKS) { /* Block address is invalid, update SENSE key and return command fail */ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); return false; } #if (TOTAL_LUNS > 1) /* Adjust the given block address to the real media address based on the selected LUN */ BlockAddress += ((uint32_t)MSInterfaceInfo->State.CommandBlock.LUN * LUN_MEDIA_BLOCKS); #endif /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ #if 0 if (IsDataRead == DATA_READ) { int i; for(i=0;i<TotalBlocks;i++) { while(!Endpoint_IsReadWriteAllowed()); MassStorage_Read(((BlockAddress+i)*VIRTUAL_MEMORY_BLOCK_SIZE), buffer, VIRTUAL_MEMORY_BLOCK_SIZE); Endpoint_Write_Stream_LE(buffer, VIRTUAL_MEMORY_BLOCK_SIZE,NULL); Endpoint_ClearIN(); } } else { int i; for(i=0;i<TotalBlocks;i++) { while(!Endpoint_IsReadWriteAllowed()); Endpoint_Read_Stream_LE(buffer,VIRTUAL_MEMORY_BLOCK_SIZE,NULL); Endpoint_ClearOUT(); MassStorage_Write((BlockAddress+i)*VIRTUAL_MEMORY_BLOCK_SIZE,buffer, VIRTUAL_MEMORY_BLOCK_SIZE); } } #else uint32_t startaddr; uint16_t blocks, dummyblocks; startaddr = MassStorage_GetAddressInImage(BlockAddress, TotalBlocks, &blocks); if (blocks == 0) dummyblocks = TotalBlocks; else if (blocks < TotalBlocks) dummyblocks = TotalBlocks - blocks; else dummyblocks = 0; Endpoint_Streaming((uint8_t*) startaddr, VIRTUAL_MEMORY_BLOCK_SIZE, blocks, dummyblocks); #endif /* Update the bytes transferred counter and succeed the command */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t) TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); return true; }
/** 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); } }
/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they * contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command. */ void MassStorage_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Select the Data Out Endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); /* Check to see if a command from the host has been issued */ if (Endpoint_IsReadWriteAllowed()) { /* Indicate busy */ LEDs_SetAllLEDs(LEDMASK_USB_BUSY); /* Process sent command block from the host */ if (ReadInCommandBlock()) { /* Check direction of command, select Data IN endpoint if data is from the device */ if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN) Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); /* Decode the received SCSI command, set returned status code */ CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail; /* Load in the CBW tag into the CSW to link them together */ CommandStatus.Tag = CommandBlock.Tag; /* Load in the data residue counter into the CSW */ CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength; /* Stall the selected data pipe if command failed (if data is still to be transferred) */ if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue)) Endpoint_StallTransaction(); /* Return command status block to the host */ ReturnCommandStatus(); /* Indicate ready */ LEDs_SetAllLEDs(LEDMASK_USB_READY); } else { /* Indicate error reading in the command block from the host */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); } } /* Check if a Mass Storage Reset occurred */ if (IsMassStoreReset) { /* Reset the data endpoint banks */ Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM); Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM); Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); /* Clear the abort transfer flag */ IsMassStoreReset = false; } }