bool SideShow_AddSimpleContent(SideShow_PacketHeader_t* const PacketHeader, SideShow_Application_t* const Application) { uint32_t ContentSize; uint32_t ContentID; Endpoint_Read_Stream_LE(&ContentID, sizeof(uint32_t)); PacketHeader->Length -= sizeof(uint32_t); if (Application->CurrentContentID != ContentID) { Endpoint_Discard_Stream(PacketHeader->Length); return false; } Endpoint_Read_Stream_LE(&ContentSize, sizeof(uint32_t)); Endpoint_Read_Stream_LE(&Application->CurrentContent, sizeof(XML_START_TAG) - 1); PacketHeader->Length -= sizeof(uint32_t) + (sizeof(XML_START_TAG) - 1); if (!(memcmp(&Application->CurrentContent, XML_START_TAG, (sizeof(XML_START_TAG) - 1)))) { SideShow_ProcessXMLContent(&Application->CurrentContent, (ContentSize - (sizeof(XML_END_TAG) - 1))); Endpoint_Discard_Stream(sizeof(XML_END_TAG) - 1); Application->HaveContent = true; } else { printf(" BINARY"); Endpoint_Discard_Stream(ContentSize); } return true; }
/* This function receives number of bytes from the USB host.*/ status_t USBVC001_ReceiveData(int8_t* DataBuffer, int16_t DataByte) { status_t Status = (uint32_t)DAVEApp_SUCCESS; uint16_t BytesProcessed = 0; uint8_t ret = 0; /* Fix for new read/write */ Endpoint_SelectEndpoint(CDC_RX_EPNUM, ENDPOINT_DIR_OUT); while ((ret=Endpoint_Read_Stream_LE(DataBuffer, DataByte, &BytesProcessed))==ENDPOINT_RWSTREAM_IncompleteTransfer); if (ret!=ENDPOINT_RWSTREAM_NoError) return -1; return Status; }
/* * Read a block from the host's OUT endpoint, handling aborts. */ bool USB_ReadBlock(uint8_t *buf, uint8_t len) { // Get the requested data from the host Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT); Endpoint_Read_Stream_LE(buf, len, AbortOnReset); // Check if the current command is being aborted by the host if (doDeviceReset) return false; Endpoint_ClearOUT(); return true; }
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock, (sizeof(MS_CommandBlockWrapper_t) - 16), StreamCallback_MS_Device_AbortOnMassStoreReset)) { return false; } if ((MSInterfaceInfo->State.CommandBlock.Signature != MS_CBW_SIGNATURE) || (MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) || (MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) || (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) || (MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16)) { Endpoint_StallTransaction(); Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); Endpoint_StallTransaction(); return false; } CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData, MSInterfaceInfo->State.CommandBlock.SCSICommandLength, StreamCallback_MS_Device_AbortOnMassStoreReset)) { return false; } Endpoint_ClearOUT(); return true; }
void usb::poll() { USB_USBTask(); Endpoint_SelectEndpoint(VENDOR_OUT_EPADDR); if (Endpoint_IsOUTReceived()) { led::setState(led::YELLOW, true); timerReset(); usb::InputBuff.length = USB_SETTINGS_HOST_TO_DEVICE_DATAPACKET_SIZE; Endpoint_Read_Stream_LE(usb::InputBuff.data, VENDOR_OUT_EPSIZE, NULL); Endpoint_Read_Stream_LE(usb::InputBuff.data + VENDOR_OUT_EPSIZE, VENDOR_OUT_EPSIZE, NULL); Endpoint_ClearOUT(); usb::executeCommandsFromUSB(); Endpoint_SelectEndpoint(VENDOR_IN_EPADDR); Endpoint_Write_Stream_LE(usb::OutputBuff.data, VENDOR_IN_EPSIZE, NULL); Endpoint_ClearIN(); led::setState(led::YELLOW, false); } }
void HID_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(GENERIC_OUT_EPADDR); /* Check to see if a packet has been sent from the host */ if (Endpoint_IsOUTReceived()) { /* Check to see if the packet contains data */ if (Endpoint_IsReadWriteAllowed()) { /* Create a temporary buffer to hold the read in report from the host */ uint8_t GenericData[GENERIC_REPORT_SIZE]; /* Read Generic Report Data */ Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL); /* Process Generic Report Data */ ProcessGenericHIDReport(GenericData); } /* Finalize the stream transfer to send the last packet */ Endpoint_ClearOUT(); } Endpoint_SelectEndpoint(GENERIC_IN_EPADDR); /* Check to see if the host is ready to accept another packet */ if (Endpoint_IsINReady()) { /* Create a temporary buffer to hold the report to send to the host */ uint8_t GenericData[GENERIC_REPORT_SIZE]; /* Create Generic Report Data */ CreateGenericHIDReport(GenericData); /* Write Generic Report Data */ Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData), NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); } }
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event) { if (USB_DeviceState != DEVICE_STATE_Configured) return false; Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpoint.Address); if (!(Endpoint_IsReadWriteAllowed())) return false; Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); if (!(Endpoint_IsReadWriteAllowed())) Endpoint_ClearOUT(); return true; }
/** Attempts to read in the TMC message header from the TMC interface. * * \param[out] MessageHeader Pointer to a location where the read header (if any) should be stored * * \return Boolean true if a header was read, false otherwise */ bool ReadTMCHeader(TMC_MessageHeader_t* const MessageHeader) { /* Select the Data Out endpoint */ Endpoint_SelectEndpoint(TMC_OUT_EPNUM); /* Abort if no command has been sent from the host */ if (!(Endpoint_IsOUTReceived())) return false; /* Read in the header of the command from the host */ Endpoint_Read_Stream_LE(MessageHeader, sizeof(TMC_MessageHeader_t), StreamCallback_AbortOUTOnRequest); /* Store the new command tag value for later use */ CurrentTransferTag = MessageHeader->Tag; /* Indicate if the command has been aborted or not */ return !(IsTMCBulkOUTReset); }
/** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the * attached device. */ static void XPROGProtocol_ReadMemory(void) { uint8_t ReturnStatus = XPROG_ERR_OK; struct { uint8_t MemoryType; uint32_t Address; uint16_t Length; } ReadMemory_XPROG_Params; Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params), NULL); ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address); ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ReadBuffer[256]; if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI) { /* Read the PDI target's memory, indicate timeout if occurred */ if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) ReturnStatus = XPROG_ERR_TIMEOUT; } else { /* Read the TPI target's memory, indicate timeout if occurred */ if (!(TINYNVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) ReturnStatus = XPROG_ERR_TIMEOUT; } Endpoint_Write_8(CMD_XPROG); Endpoint_Write_8(XPROG_CMD_READ_MEM); Endpoint_Write_8(ReturnStatus); if (ReturnStatus == XPROG_ERR_OK) Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length, NULL); Endpoint_ClearIN(); }
/** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI/TPI * programming. */ void XPROGProtocol_SetMode(void) { struct { uint8_t Protocol; } SetMode_XPROG_Params; Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params), NULL); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); XPROG_SelectedProtocol = SetMode_XPROG_Params.Protocol; Endpoint_Write_8(CMD_XPROG_SETMODE); Endpoint_Write_8((SetMode_XPROG_Params.Protocol != XPROG_PROTOCOL_JTAG) ? STATUS_CMD_OK : STATUS_CMD_FAILED); Endpoint_ClearIN(); }
/** 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(); } }
/** Function to manage CDC data transmission and reception to and from the host for the second CDC interface, which echoes back * all data sent to it from the host. */ void CDC2_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Select the Serial Rx Endpoint */ Endpoint_SelectEndpoint(CDC2_RX_EPNUM); /* Check to see if any data has been received */ if (Endpoint_IsOUTReceived()) { /* Create a temp buffer big enough to hold the incoming endpoint packet */ uint8_t Buffer[Endpoint_BytesInEndpoint()]; /* Remember how large the incoming packet is */ uint16_t DataLength = Endpoint_BytesInEndpoint(); /* Read in the incoming packet into the buffer */ Endpoint_Read_Stream_LE(&Buffer, DataLength); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearOUT(); /* Select the Serial Tx Endpoint */ Endpoint_SelectEndpoint(CDC2_TX_EPNUM); /* Write the received data to the endpoint */ Endpoint_Write_Stream_LE(&Buffer, DataLength); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); /* Wait until the endpoint is ready for the next packet */ Endpoint_WaitUntilReady(); /* Send an empty packet to prevent host buffering */ Endpoint_ClearIN(); } }
void Endpoint_Streaming(uint8_t corenum, uint8_t *buffer, uint16_t packetsize, uint16_t totalpackets, uint16_t dummypackets) { uint8_t PhyEP = endpointhandle(corenum)[endpointselected[corenum]]; uint16_t i; dummypackets = dummypackets; if (PhyEP & 1) { for (i = 0; i < totalpackets; i++) { while (!Endpoint_IsReadWriteAllowed(corenum)) ; Endpoint_Write_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL); Endpoint_ClearIN(corenum); } } else { for (i = 0; i < totalpackets; i++) { DcdDataTransfer(PhyEP, usb_data_buffer_OUT[corenum], packetsize); Endpoint_ClearOUT(corenum); while (!Endpoint_IsReadWriteAllowed(corenum)) ; Endpoint_Read_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL); } } }
void JIG_Task (void) { static int bytes_out = 0, bytes_in = 0; Endpoint_SelectEndpoint(2); if (Endpoint_IsReadWriteAllowed()) { Endpoint_Read_Stream_LE (&jig_challenge_res[bytes_out], 8, NO_STREAM_CALLBACK) ; Endpoint_ClearOUT(); bytes_out += 8; if (bytes_out >= 64) { //prepare the response (by guess?) jig_challenge_res[1]--; jig_challenge_res[3]++; jig_challenge_res[6]++; HMACBlock(&jig_challenge_res[CHALLENGE_INDEX],20); USB_USBTask(); //just in case HMACDone(); jig_challenge_res[7] = jig_id[0]; jig_challenge_res[8] = jig_id[1]; int i; for( i = 0; i < 20; i++) jig_challenge_res[9+i] = hmacdigest[i]; state = p5_challenged; expire = 50; // was 90 } } Endpoint_SelectEndpoint(1); if (Endpoint_IsReadWriteAllowed() && state == p5_challenged && expire == 0) { if ( bytes_in < 64) { Endpoint_Write_PStream_LE(&jig_challenge_res[bytes_in], 8, NO_STREAM_CALLBACK); Endpoint_ClearIN(); bytes_in += 8; if ( bytes_in >= 64) { state = p5_responded; expire = 50; } } } }
/** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */ void ISPProtocol_LeaveISPMode(void) { struct { uint8_t PreDelayMS; uint8_t PostDelayMS; } Leave_ISP_Params; Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params), NULL); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); /* Perform pre-exit delay, release the target /RESET, disable the SPI bus and perform the post-exit delay */ ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS); ISPTarget_ChangeTargetResetLine(false); ISPTarget_DisableTargetISP(); ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS); Endpoint_Write_8(CMD_LEAVE_PROGMODE_ISP); Endpoint_Write_8(STATUS_CMD_OK); Endpoint_ClearIN(); }
/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes, * words or pages of data to the attached device. * * \param[in] V2Command Issued V2 Protocol command byte from the host */ void ISPProtocol_ProgramMemory(uint8_t V2Command) { struct { uint16_t BytesToWrite; uint8_t ProgrammingMode; uint8_t DelayMS; uint8_t ProgrammingCommands[3]; uint8_t PollValue1; uint8_t PollValue2; uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the } Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData)), NO_STREAM_CALLBACK); Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite); if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData)) { Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); Endpoint_Write_Byte(V2Command); Endpoint_Write_Byte(STATUS_CMD_FAILED); Endpoint_ClearIN(); return; } Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NO_STREAM_CALLBACK); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ProgrammingStatus = STATUS_CMD_OK; uint16_t PollAddress = 0; uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 : Write_Memory_Params.PollValue2; uint8_t* NextWriteByte = Write_Memory_Params.ProgData; /* Check the programming mode desired by the host, either Paged or Word memory writes */ if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK) { uint16_t StartAddress = (CurrentAddress & 0xFFFF); /* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */ if (MustLoadExtendedAddress) { ISPTarget_LoadExtendedAddress(); MustLoadExtendedAddress = false; } /* Paged mode memory programming */ for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) { bool IsOddByte = (CurrentByte & 0x01); uint8_t ByteToWrite = *(NextWriteByte++); ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[0]); ISPTarget_SendByte(CurrentAddress >> 8); ISPTarget_SendByte(CurrentAddress & 0xFF); ISPTarget_SendByte(ByteToWrite); /* AVR FLASH addressing requires us to modify the write command based on if we are writing a high * or low byte at the current word address */ if (V2Command == CMD_PROGRAM_FLASH_ISP) Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK; /* Check to see the write completion method, to see if we have a valid polling address */ if (!(PollAddress) && (ByteToWrite != PollValue)) { if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; PollAddress = (CurrentAddress & 0xFFFF); } /* EEPROM increments the address on each byte, flash needs to increment on each word */ if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP)) CurrentAddress++; } /* If the current page must be committed, send the PROGRAM PAGE command to the target */ if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK) { ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[1]); ISPTarget_SendByte(StartAddress >> 8); ISPTarget_SendByte(StartAddress & 0xFF); ISPTarget_SendByte(0x00); /* Check if polling is possible and enabled, if not switch to timed delay mode */ if (!(PollAddress) && (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_VALUE_MASK)) { Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK; Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK; } ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); /* Check to see if the FLASH address has crossed the extended address boundary */ if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF)) MustLoadExtendedAddress = true; }
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */ static void XPROGProtocol_WriteMemory(void) { uint8_t ReturnStatus = XPROG_ERR_OK; struct { uint8_t MemoryType; uint8_t PageMode; uint32_t Address; uint16_t Length; uint8_t ProgData[256]; } WriteMemory_XPROG_Params; Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params).ProgData), NULL); WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address); WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length); Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length, NULL); // The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need // to catch this and discard it before continuing on with packet processing to prevent communication issues if (((sizeof(uint8_t) + sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params.ProgData)) + WriteMemory_XPROG_Params.Length) % AVRISP_DATA_EPSIZE == 0) { Endpoint_ClearOUT(); Endpoint_WaitUntilReady(); } Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI) { /* Assume FLASH page programming by default, as it is the common case */ uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE; uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF; uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF; bool PagedMemory = true; switch (WriteMemory_XPROG_Params.MemoryType) { case XPROG_MEM_TYPE_APPL: WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE; break; case XPROG_MEM_TYPE_BOOT: WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE; break; case XPROG_MEM_TYPE_EEPROM: WriteCommand = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE; WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF; EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF; break; case XPROG_MEM_TYPE_USERSIG: WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG; break; case XPROG_MEM_TYPE_FUSE: WriteCommand = XMEGA_NVM_CMD_WRITEFUSE; PagedMemory = false; break; case XPROG_MEM_TYPE_LOCKBITS: WriteCommand = XMEGA_NVM_CMD_WRITELOCK; PagedMemory = false; break; } /* Send the appropriate memory write commands to the device, indicate timeout if occurred */ if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) || (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData[0])))) { ReturnStatus = XPROG_ERR_TIMEOUT; } } else { /* Send write command to the TPI device, indicate timeout if occurred */ if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) { ReturnStatus = XPROG_ERR_TIMEOUT; } } Endpoint_Write_8(CMD_XPROG); Endpoint_Write_8(XPROG_CMD_WRITE_MEM); Endpoint_Write_8(ReturnStatus); Endpoint_ClearIN(); }
/** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */ static void XPROGProtocol_Erase(void) { uint8_t ReturnStatus = XPROG_ERR_OK; struct { uint8_t MemoryType; uint32_t Address; } Erase_XPROG_Params; Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params), NULL); Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t EraseCommand; if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI) { /* Determine which NVM command to send to the device depending on the memory to erase */ switch (Erase_XPROG_Params.MemoryType) { case XPROG_ERASE_CHIP: EraseCommand = XMEGA_NVM_CMD_CHIPERASE; break; case XPROG_ERASE_APP: EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC; break; case XPROG_ERASE_BOOT: EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC; break; case XPROG_ERASE_EEPROM: EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM; break; case XPROG_ERASE_APP_PAGE: EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE; break; case XPROG_ERASE_BOOT_PAGE: EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE; break; case XPROG_ERASE_EEPROM_PAGE: EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE; break; case XPROG_ERASE_USERSIG: EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG; break; default: EraseCommand = XMEGA_NVM_CMD_NOOP; break; } /* Erase the target memory, indicate timeout if occurred */ if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address))) ReturnStatus = XPROG_ERR_TIMEOUT; } else { if (Erase_XPROG_Params.MemoryType == XPROG_ERASE_CHIP) EraseCommand = TINY_NVM_CMD_CHIPERASE; else EraseCommand = TINY_NVM_CMD_SECTIONERASE; /* Erase the target memory, indicate timeout if occurred */ if (!(TINYNVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address))) ReturnStatus = XPROG_ERR_TIMEOUT; } Endpoint_Write_8(CMD_XPROG); Endpoint_Write_8(XPROG_CMD_ERASE); Endpoint_Write_8(ReturnStatus); Endpoint_ClearIN(); }
/** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on * the attached device, returning success or failure back to the host. */ void ISPProtocol_EnterISPMode(void) { struct { uint8_t TimeoutMS; uint8_t PinStabDelayMS; uint8_t ExecutionDelayMS; uint8_t SynchLoops; uint8_t ByteDelay; uint8_t PollValue; uint8_t PollIndex; uint8_t EnterProgBytes[4]; } Enter_ISP_Params; Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params), NO_STREAM_CALLBACK); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ResponseStatus = STATUS_CMD_FAILED; CurrentAddress = 0; /* Set up the synchronous USART to generate the .5MHz recovery clock on XCK pin */ UBRR1 = (F_CPU / 500000UL); UCSR1B = (1 << TXEN1); UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); DDRD |= (1 << 5); /* Perform execution delay, initialize SPI bus */ ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); ISPTarget_Init(); /* Continuously attempt to synchronize with the target until either the number of attempts specified * by the host has exceeded, or the the device sends back the expected response values */ while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED) && TimeoutTicksRemaining) { uint8_t ResponseBytes[4]; ISPTarget_ChangeTargetResetLine(true); ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) { ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay); ResponseBytes[RByte] = ISPTarget_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]); } /* Check if polling disabled, or if the polled value matches the expected value */ if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue)) { ResponseStatus = STATUS_CMD_OK; } else { ISPTarget_ChangeTargetResetLine(false); ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); } } Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP); Endpoint_Write_Byte(ResponseStatus); Endpoint_ClearIN(); }
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)); } }
/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes, * words or pages of data to the attached device. * * \param[in] V2Command Issued V2 Protocol command byte from the host */ void ISPProtocol_ProgramMemory(uint8_t V2Command) { struct { uint16_t BytesToWrite; uint8_t ProgrammingMode; uint8_t DelayMS; uint8_t ProgrammingCommands[3]; uint8_t PollValue1; uint8_t PollValue2; uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the } Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData)), NULL); Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite); if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData)) { Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); Endpoint_Write_8(V2Command); Endpoint_Write_8(STATUS_CMD_FAILED); Endpoint_ClearIN(); return; } Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NULL); // The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need // to catch this and discard it before continuing on with packet processing to prevent communication issues if (((sizeof(uint8_t) + sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData)) + Write_Memory_Params.BytesToWrite) % AVRISP_DATA_EPSIZE == 0) { Endpoint_ClearOUT(); Endpoint_WaitUntilReady(); } Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ProgrammingStatus = STATUS_CMD_OK; uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 : Write_Memory_Params.PollValue2; uint16_t PollAddress = 0; uint8_t* NextWriteByte = Write_Memory_Params.ProgData; uint16_t PageStartAddress = (CurrentAddress & 0xFFFF); for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) { uint8_t ByteToWrite = *(NextWriteByte++); uint8_t ProgrammingMode = Write_Memory_Params.ProgrammingMode; /* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */ if (MustLoadExtendedAddress) { ISPTarget_LoadExtendedAddress(); MustLoadExtendedAddress = false; } ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[0]); ISPTarget_SendByte(CurrentAddress >> 8); ISPTarget_SendByte(CurrentAddress & 0xFF); ISPTarget_SendByte(ByteToWrite); /* AVR FLASH addressing requires us to modify the write command based on if we are writing a high * or low byte at the current word address */ if (V2Command == CMD_PROGRAM_FLASH_ISP) Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK; /* Check to see if we have a valid polling address */ if (!(PollAddress) && (ByteToWrite != PollValue)) { if ((CurrentByte & 0x01) && (V2Command == CMD_PROGRAM_FLASH_ISP)) Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; else Write_Memory_Params.ProgrammingCommands[2] &= ~READ_WRITE_HIGH_BYTE_MASK; PollAddress = (CurrentAddress & 0xFFFF); } /* If in word programming mode, commit the byte to the target's memory */ if (!(ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK)) { /* If the current polling address is invalid, switch to timed delay write completion mode */ if (!(PollAddress) && !(ProgrammingMode & PROG_MODE_WORD_READYBUSY_MASK)) ProgrammingMode = (ProgrammingMode & ~PROG_MODE_WORD_VALUE_MASK) | PROG_MODE_WORD_TIMEDELAY_MASK; ProgrammingStatus = ISPTarget_WaitForProgComplete(ProgrammingMode, PollAddress, PollValue, Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); /* Abort the programming loop early if the byte/word programming failed */ if (ProgrammingStatus != STATUS_CMD_OK) break; /* Must reset the polling address afterwards, so it is not erroneously used for the next byte */ PollAddress = 0; } /* EEPROM just increments the address each byte, flash needs to increment on each word and * also check to ensure that a LOAD EXTENDED ADDRESS command is issued each time the extended * address boundary has been crossed during FLASH memory programming */ if ((CurrentByte & 0x01) || (V2Command == CMD_PROGRAM_EEPROM_ISP)) { CurrentAddress++; if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF)) MustLoadExtendedAddress = true; } } /* If the current page must be committed, send the PROGRAM PAGE command to the target */ if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK) { ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[1]); ISPTarget_SendByte(PageStartAddress >> 8); ISPTarget_SendByte(PageStartAddress & 0xFF); ISPTarget_SendByte(0x00); /* Check if polling is enabled and possible, if not switch to timed delay mode */ if ((Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_VALUE_MASK) && !(PollAddress)) { Write_Memory_Params.ProgrammingMode = (Write_Memory_Params.ProgrammingMode & ~PROG_MODE_PAGED_VALUE_MASK) | PROG_MODE_PAGED_TIMEDELAY_MASK; } ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); /* Check to see if the FLASH address has crossed the extended address boundary */ if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF)) MustLoadExtendedAddress = true; }
static void SideShow_GetCapabilities(SideShow_PacketHeader_t* PacketHeader) { SideShow_PropertyKey_t Property; SideShow_PropertyData_t PropertyData; Endpoint_Read_Stream_LE(&Property, sizeof(SideShow_PropertyKey_t)); Endpoint_ClearOUT(); printf(" ID: %lu", Property.PropertyID); PacketHeader->Length = sizeof(SideShow_PacketHeader_t); if (GUID_COMPARE(&Property.PropertyGUID, (uint32_t[])SIDESHOW_PROPERTY_GUID)) { switch (Property.PropertyID) { case PROPERTY_SIDESHOW_SCREENTYPE: PropertyData.DataType = VT_I4; PropertyData.Data.Data32 = ScreenText; PacketHeader->Length += sizeof(uint32_t); break; case PROPERTY_SIDESHOW_SCREENWIDTH: case PROPERTY_SIDESHOW_CLIENTWIDTH: PropertyData.DataType = VT_UI2; PropertyData.Data.Data16 = 16; PacketHeader->Length += sizeof(uint16_t); break; case PROPERTY_SIDESHOW_SCREENHEIGHT: case PROPERTY_SIDESHOW_CLIENTHEIGHT: PropertyData.DataType = VT_UI2; PropertyData.Data.Data16 = 2; PacketHeader->Length += sizeof(uint16_t); break; case PROPERTY_SIDESHOW_COLORDEPTH: PropertyData.DataType = VT_UI2; PropertyData.Data.Data16 = 1; PacketHeader->Length += sizeof(uint16_t); break; case PROPERTY_SIDESHOW_COLORTYPE: PropertyData.DataType = VT_UI2; PropertyData.Data.Data16 = BlackAndWhiteDisplay; PacketHeader->Length += sizeof(uint16_t); break; case PROPERTY_SIDESHOW_DATACACHE: PropertyData.DataType = VT_BOOL; PropertyData.Data.Data16 = false; PacketHeader->Length += sizeof(uint16_t); break; case PROPERTY_SIDESHOW_SUPPORTEDLANGS: case PROPERTY_SIDESHOW_CURRENTLANG: PropertyData.DataType = VT_LPWSTR; PropertyData.Data.DataPointer = &SupportedLanguage; PacketHeader->Length += SupportedLanguage.LengthInBytes; break; default: PropertyData.DataType = VT_EMPTY; break; } } else if (GUID_COMPARE(&Property.PropertyGUID, (uint32_t[])DEVICE_PROPERTY_GUID)) { switch (Property.PropertyID) { case PROPERTY_DEVICE_DEVICETYPE: PropertyData.DataType = VT_UI4; PropertyData.Data.Data32 = GenericDevice; PacketHeader->Length += sizeof(uint32_t); break; } } else { PacketHeader->Type.NAK = true; printf(" WRONG GUID"); printf(" %lX %lX %lX %lX", Property.PropertyGUID.Chunks[0], Property.PropertyGUID.Chunks[1], Property.PropertyGUID.Chunks[2], Property.PropertyGUID.Chunks[3]); } Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM); Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t)); if (!(PacketHeader->Type.NAK)) { switch (PropertyData.DataType) { case VT_UI4: case VT_I4: Endpoint_Write_Stream_LE(&PropertyData.Data.Data32, sizeof(uint32_t)); break; case VT_UI2: case VT_I2: case VT_BOOL: Endpoint_Write_Stream_LE(&PropertyData.Data.Data16, sizeof(uint16_t)); break; case VT_LPWSTR: SideShow_Write_Unicode_String((Unicode_String_t*)PropertyData.Data.Data16); break; } } Endpoint_ClearIN(); return; }
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) { if (USB_DeviceState != DEVICE_STATE_Configured) return; RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber); if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) { USB_Request_Header_t Notification = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = NOTIF_ResponseAvailable, .wValue = 0, .wIndex = 0, .wLength = 0, }; Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK); Endpoint_ClearIN(); RNDISInterfaceInfo->State.ResponseReady = false; } if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength)) { RNDIS_Packet_Message_t RNDISPacketHeader; Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber); if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer)) { Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK); if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX) { Endpoint_StallTransaction(); return; } Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK); Endpoint_ClearOUT(); RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength; RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true; } Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber); if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer) { memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t)); RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG; RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength); RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength; Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK); Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK); Endpoint_ClearIN(); RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false; } } }
/** Task to handle the generation of MIDI note change events in response to presses of the board joystick, and send them * to the host. */ void MIDI_Task(void) { static uint8_t PrevJoystickStatus; /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR); if (Endpoint_IsINReady()) { uint8_t MIDICommand = 0; uint8_t MIDIPitch; uint8_t JoystickStatus = Joystick_GetStatus(); uint8_t JoystickChanges = (JoystickStatus ^ PrevJoystickStatus); /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */ uint8_t Channel = ((Buttons_GetStatus() & BUTTONS_BUTTON1) ? MIDI_CHANNEL(10) : MIDI_CHANNEL(1)); if (JoystickChanges & JOY_LEFT) { MIDICommand = ((JoystickStatus & JOY_LEFT)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3C; } if (JoystickChanges & JOY_UP) { MIDICommand = ((JoystickStatus & JOY_UP)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3D; } if (JoystickChanges & JOY_RIGHT) { MIDICommand = ((JoystickStatus & JOY_RIGHT)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3E; } if (JoystickChanges & JOY_DOWN) { MIDICommand = ((JoystickStatus & JOY_DOWN)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3F; } if (JoystickChanges & JOY_PRESS) { MIDICommand = ((JoystickStatus & JOY_PRESS)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3B; } /* Check if a MIDI command is to be sent */ if (MIDICommand) { MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t) { .Event = MIDI_EVENT(0, MIDICommand), .Data1 = MIDICommand | Channel, .Data2 = MIDIPitch, .Data3 = MIDI_STANDARD_VELOCITY, }; /* Write the MIDI event packet to the endpoint */ Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); /* Send the data in the endpoint to the host */ Endpoint_ClearIN(); } /* Save previous joystick value for next joystick change detection */ PrevJoystickStatus = JoystickStatus; } /* Select the MIDI OUT stream */ Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR); /* Check if a MIDI command has been received */ if (Endpoint_IsOUTReceived()) { MIDI_EventPacket_t MIDIEvent; /* Read the MIDI event packet from the endpoint */ Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); /* Check to see if the sent command is a note on message with a non-zero velocity */ if ((MIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_ON)) && (MIDIEvent.Data3 > 0)) { /* Change LEDs depending on the pitch of the sent note */ LEDs_SetAllLEDs(MIDIEvent.Data2 > 64 ? LEDS_LED1 : LEDS_LED2); } else { /* Turn off all LEDs in response to non Note On messages */ LEDs_SetAllLEDs(LEDS_NO_LEDS); } /* If the endpoint is now empty, clear the bank */ if (!(Endpoint_BytesInEndpoint())) { /* Clear the endpoint ready for new packet */ Endpoint_ClearOUT(); } } }
/** Task to manage the sending and receiving of encapsulated RNDIS data and notifications. This removes the RNDIS * wrapper from received Ethernet frames and places them in the FrameIN global buffer, or adds the RNDIS wrapper * to a frame in the FrameOUT global before sending the buffer contents to the host. */ void RNDIS_Task(void) { /* Select the notification endpoint */ Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPADDR); /* Check if a message response is ready for the host */ if (Endpoint_IsINReady() && ResponseReady) { USB_Request_Header_t Notification = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = RNDIS_NOTIF_ResponseAvailable, .wValue = 0, .wIndex = 0, .wLength = 0, }; /* Indicate that a message response is ready for the host */ Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); /* Indicate a response is no longer ready */ ResponseReady = false; } /* Don't process the data endpoints until the system is in the data initialized state, and the buffer is free */ if ((CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength)) { /* Create a new packet header for reading/writing */ RNDIS_Packet_Message_t RNDISPacketHeader; /* Select the data OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPADDR); /* Check if the data OUT endpoint contains data, and that the IN buffer is empty */ if (Endpoint_IsOUTReceived() && !(FrameIN.FrameLength)) { /* Read in the packet message header */ Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); /* Stall the request if the data is too large */ if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX) { Endpoint_StallTransaction(); return; } /* Read in the Ethernet frame into the buffer */ Endpoint_Read_Stream_LE(FrameIN.FrameData, RNDISPacketHeader.DataLength, NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearOUT(); /* Store the size of the Ethernet frame */ FrameIN.FrameLength = RNDISPacketHeader.DataLength; } /* Select the data IN endpoint */ Endpoint_SelectEndpoint(CDC_TX_EPADDR); /* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */ if (Endpoint_IsINReady() && FrameOUT.FrameLength) { /* Clear the packet header with all 0s so that the relevant fields can be filled */ memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t)); /* Construct the required packet header fields in the buffer */ RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG; RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + FrameOUT.FrameLength); RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); RNDISPacketHeader.DataLength = FrameOUT.FrameLength; /* Send the packet header to the host */ Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL); /* Send the Ethernet frame data to the host */ Endpoint_Write_Stream_LE(FrameOUT.FrameData, RNDISPacketHeader.DataLength, NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); /* Indicate Ethernet OUT buffer no longer full */ FrameOUT.FrameLength = 0; } } }
/** ISR for the general Pipe/Endpoint interrupt vector. This ISR fires when an endpoint's status changes (such as * a packet has been received) on an endpoint with its corresponding ISR enabling bits set. This is used to send * HID packets to the host each time the HID interrupt endpoints polling period elapses, as managed by the USB * controller. */ ISR(ENDPOINT_PIPE_vect, ISR_BLOCK) { /* Save previously selected endpoint before selecting a new endpoint */ uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint(); #if defined(INTERRUPT_CONTROL_ENDPOINT) /* Check if the control endpoint has received a request */ if (Endpoint_HasEndpointInterrupted(ENDPOINT_CONTROLEP)) { /* Clear the endpoint interrupt */ Endpoint_ClearEndpointInterrupt(ENDPOINT_CONTROLEP); /* Process the control request */ USB_USBTask(); /* Handshake the endpoint setup interrupt - must be after the call to USB_USBTask() */ USB_INT_Clear(ENDPOINT_INT_SETUP); } #endif #if defined(INTERRUPT_DATA_ENDPOINT) /* Check if Generic IN endpoint has interrupted */ if (Endpoint_HasEndpointInterrupted(GENERIC_IN_EPNUM)) { /* Select the Generic IN Report Endpoint */ Endpoint_SelectEndpoint(GENERIC_IN_EPNUM); /* Clear the endpoint IN interrupt flag */ USB_INT_Clear(ENDPOINT_INT_IN); /* Clear the Generic IN Report endpoint interrupt and select the endpoint */ Endpoint_ClearEndpointInterrupt(GENERIC_IN_EPNUM); /* Create a temporary buffer to hold the report to send to the host */ uint8_t GenericData[GENERIC_REPORT_SIZE]; /* Create Generic Report Data */ CreateGenericHIDReport(GenericData); /* Write Generic Report Data */ Endpoint_Write_Stream_LE(&GenericData, sizeof(GenericData)); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); } /* Check if Generic OUT endpoint has interrupted */ if (Endpoint_HasEndpointInterrupted(GENERIC_OUT_EPNUM)) { /* Select the Generic OUT Report Endpoint */ Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM); /* Clear the endpoint OUT Interrupt flag */ USB_INT_Clear(ENDPOINT_INT_OUT); /* Clear the Generic OUT Report endpoint interrupt and select the endpoint */ Endpoint_ClearEndpointInterrupt(GENERIC_OUT_EPNUM); /* Create a temporary buffer to hold the read in report from the host */ uint8_t GenericData[GENERIC_REPORT_SIZE]; /* Read Generic Report Data */ Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData)); /* Process Generic Report Data */ ProcessGenericHIDReport(GenericData); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearOUT(); } #endif /* Restore previously selected endpoint */ Endpoint_SelectEndpoint(PrevSelectedEndpoint); }
/** 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; }
/** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on * the attached device, returning success or failure back to the host. */ void ISPProtocol_EnterISPMode(void) { struct { uint8_t TimeoutMS; uint8_t PinStabDelayMS; uint8_t ExecutionDelayMS; uint8_t SynchLoops; uint8_t ByteDelay; uint8_t PollValue; uint8_t PollIndex; uint8_t EnterProgBytes[4]; } Enter_ISP_Params; Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params), NULL); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ResponseStatus = STATUS_CMD_FAILED; CurrentAddress = 0; /* Perform execution delay, initialize SPI bus */ ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); ISPTarget_EnableTargetISP(); ISPTarget_ChangeTargetResetLine(true); ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); /* Continuously attempt to synchronize with the target until either the number of attempts specified * by the host has exceeded, or the the device sends back the expected response values */ while (Enter_ISP_Params.SynchLoops-- && TimeoutTicksRemaining) { uint8_t ResponseBytes[4]; for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) { ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay); ResponseBytes[RByte] = ISPTarget_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]); } /* Check if polling disabled, or if the polled value matches the expected value */ if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue)) { ResponseStatus = STATUS_CMD_OK; break; } else { ISPTarget_ChangeTargetResetLine(false); ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); ISPTarget_ChangeTargetResetLine(true); ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); } } Endpoint_Write_8(CMD_ENTER_PROGMODE_ISP); Endpoint_Write_8(ResponseStatus); Endpoint_ClearIN(); }
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */ static void XPROGProtocol_WriteMemory(void) { uint8_t ReturnStatus = XPRG_ERR_OK; struct { uint8_t MemoryType; uint8_t PageMode; uint32_t Address; uint16_t Length; uint8_t ProgData[256]; } WriteMemory_XPROG_Params; Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params).ProgData), NO_STREAM_CALLBACK); WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address); WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length); Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length, NO_STREAM_CALLBACK); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI) { /* Assume FLASH page programming by default, as it is the common case */ uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE; uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF; uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF; bool PagedMemory = true; switch (WriteMemory_XPROG_Params.MemoryType) { case XPRG_MEM_TYPE_APPL: WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE; break; case XPRG_MEM_TYPE_BOOT: WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE; break; case XPRG_MEM_TYPE_EEPROM: WriteCommand = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE; WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF; EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF; break; case XPRG_MEM_TYPE_USERSIG: /* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */ WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE); WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG; break; case XPRG_MEM_TYPE_FUSE: WriteCommand = XMEGA_NVM_CMD_WRITEFUSE; PagedMemory = false; break; case XPRG_MEM_TYPE_LOCKBITS: WriteCommand = XMEGA_NVM_CMD_WRITELOCK; PagedMemory = false; break; } /* Send the appropriate memory write commands to the device, indicate timeout if occurred */ if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) || (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData[0])))) { ReturnStatus = XPRG_ERR_TIMEOUT; } } else { /* Send write command to the TPI device, indicate timeout if occurred */ if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) { ReturnStatus = XPRG_ERR_TIMEOUT; } } Endpoint_Write_Byte(CMD_XPROG); Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM); Endpoint_Write_Byte(ReturnStatus); Endpoint_ClearIN(); }