/** Task to manage an enumerated USB Bluetooth adapter once connected, to display movement data as it is received. */ void BluetoothAdapter_USBTask(void) { if ((USB_HostState != HOST_STATE_Configured) || !(BluetoothAdapter_IsActive)) return; Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { BT_HCIData_Header_t* PacketHeader = (BT_HCIData_Header_t*)BluetoothAdapter_Stack.Config.PacketBuffer; /* Read in the HCI Data packet data from the Data IN pipe */ Pipe_Read_Stream_LE(PacketHeader, sizeof(BT_HCIData_Header_t), NULL); Pipe_Read_Stream_LE(PacketHeader->Data, PacketHeader->DataLength, NULL); Pipe_ClearIN(); Pipe_Freeze(); // RGB_SetColour(RGB_ALIAS_Busy); Bluetooth_ProcessPacket(&BluetoothAdapter_Stack, BLUETOOTH_PACKET_HCIData); // RGB_SetColour(RGB_ALIAS_Connected); } Pipe_Freeze(); Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { BT_HCIEvent_Header_t* EventHeader = (BT_HCIEvent_Header_t*)BluetoothAdapter_Stack.Config.PacketBuffer; /* Read in the HCI Event packet data from the Event IN pipe */ Pipe_Read_Stream_LE(EventHeader, sizeof(BT_HCIEvent_Header_t), NULL); Pipe_Read_Stream_LE(EventHeader->Parameters, EventHeader->ParameterLength, NULL); Pipe_ClearIN(); Pipe_Freeze(); //RGB_SetColour(RGB_ALIAS_Busy); Bluetooth_ProcessPacket(&BluetoothAdapter_Stack, BLUETOOTH_PACKET_HCIEvent); //RGB_SetColour(RGB_ALIAS_Connected); } Pipe_Freeze(); /* Keep on running the management routine until all pending packets have been sent */ while (Bluetooth_ManageConnections(&BluetoothAdapter_Stack)){}; //while (Bluetooth_ManageConnections(&BluetoothAdapter_Stack)) //RGB_SetColour(RGB_ALIAS_Busy); }
/** Task to read in data received from the attached CDC device and print it to the serial port. */ void CDCHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; /* Select the data IN pipe */ Pipe_SelectPipe(CDC_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Re-freeze IN pipe after the packet has been received */ Pipe_Freeze(); /* Check if data is in the pipe */ if (Pipe_IsReadWriteAllowed()) { /* Get the length of the pipe data, and create a new buffer to hold it */ uint16_t BufferLength = Pipe_BytesInPipe(); uint8_t Buffer[BufferLength]; /* Read in the pipe data to the temporary buffer */ Pipe_Read_Stream_LE(Buffer, BufferLength, NULL); /* Print out the buffer contents to the USART */ for (uint16_t BufferByte = 0; BufferByte < BufferLength; BufferByte++) putchar(Buffer[BufferByte]); } /* Clear the pipe after it is read, ready for the next packet */ Pipe_ClearIN(); } /* Re-freeze IN pipe after use */ Pipe_Freeze(); /* Select and unfreeze the notification pipe */ Pipe_SelectPipe(CDC_NOTIFICATION_PIPE); Pipe_Unfreeze(); /* Check if a packet has been received */ if (Pipe_IsINReceived()) { /* Discard the unused event notification */ Pipe_ClearIN(); } /* Freeze notification IN pipe after use */ Pipe_Freeze(); }
/** Task to read and process the HID report descriptor and HID reports from the device and display the * results onto the board LEDs. */ void MouseHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; /* Select and unfreeze mouse data pipe */ Pipe_SelectPipe(MOUSE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Check if data has been received from the attached mouse */ if (Pipe_IsReadWriteAllowed()) { /* Create buffer big enough for the report */ uint8_t MouseReport[Pipe_BytesInPipe()]; /* Load in the mouse report */ Pipe_Read_Stream_LE(MouseReport, Pipe_BytesInPipe(), NULL); /* Process the read in mouse report from the device */ ProcessMouseReport(MouseReport); } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); } /* Freeze mouse data pipe */ Pipe_Freeze(); }
uint8_t Pipe_WaitUntilReady(void) { #if (USB_STREAM_TIMEOUT_MS < 0xFF) uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #else uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #endif for (;;) { if (Pipe_GetPipeToken() == PIPE_TOKEN_IN) { if (Pipe_IsINReceived()) return PIPE_READYWAIT_NoError; } else { if (Pipe_IsOUTReady()) return PIPE_READYWAIT_NoError; } if (Pipe_IsStalled()) return PIPE_READYWAIT_PipeStalled; else if (USB_HostState == HOST_STATE_Unattached) return PIPE_READYWAIT_DeviceDisconnected; if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; } } }
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event) { if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive)) return HOST_SENDCONTROL_DeviceDisconnected; bool DataReady = false; Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipe.Address); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { if (Pipe_BytesInPipe()) { Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); DataReady = true; } if (!(Pipe_BytesInPipe())) Pipe_ClearIN(); } Pipe_Freeze(); return DataReady; }
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive)) return; Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_SetPipeToken(PIPE_TOKEN_IN); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { USB_Request_Header_t Notification; Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK); if ((Notification.bRequest == NOTIF_SerialState) && (Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))) { Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost, sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), NO_STREAM_CALLBACK); } Pipe_ClearIN(); EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo); } Pipe_Freeze(); }
/** Reads in and processes the next report from the attached device, displaying the report * contents on the board LEDs and via the serial port. */ void ReadNextReport(void) { USB_MouseReport_Data_t MouseReport; uint8_t LEDMask = LEDS_NO_LEDS; /* Select mouse data pipe */ Pipe_SelectPipe(MOUSE_DATA_IN_PIPE); /* Unfreeze keyboard data pipe */ Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (!(Pipe_IsINReceived())) { /* No packet received (no movement), turn off LEDs */ LEDs_SetAllLEDs(LEDS_NO_LEDS); /* Refreeze HID data IN pipe */ Pipe_Freeze(); return; } /* Ensure pipe contains data before trying to read from it */ if (Pipe_IsReadWriteAllowed()) { /* Read in mouse report data */ Pipe_Read_Stream_LE(&MouseReport, sizeof(MouseReport)); /* Alter status LEDs according to mouse X movement */ if (MouseReport.X > 0) LEDMask |= LEDS_LED1; else if (MouseReport.X < 0) LEDMask |= LEDS_LED2; /* Alter status LEDs according to mouse Y movement */ if (MouseReport.Y > 0) LEDMask |= LEDS_LED3; else if (MouseReport.Y < 0) LEDMask |= LEDS_LED4; /* Alter status LEDs according to mouse button position */ if (MouseReport.Button) LEDMask = LEDS_ALL_LEDS; LEDs_SetAllLEDs(LEDMask); /* Print mouse report data through the serial port */ printf_P(PSTR("dX:%2d dY:%2d Button:%d\r\n"), MouseReport.X, MouseReport.Y, MouseReport.Button); } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); /* Refreeze mouse data pipe */ Pipe_Freeze(); }
/** Reads in and processes the next report from the attached device, displaying the report * contents on the board LEDs and via the serial port. */ void ReadNextReport(void) { USB_KeyboardReport_Data_t KeyboardReport; /* Select keyboard data pipe */ Pipe_SelectPipe(KEYBOARD_DATAPIPE); /* Unfreeze keyboard data pipe */ Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (!(Pipe_IsINReceived())) { /* Refreeze HID data IN pipe */ Pipe_Freeze(); return; } /* Ensure pipe contains data before trying to read from it */ if (Pipe_IsReadWriteAllowed()) { /* Read in keyboard report data */ Pipe_Read_Stream_LE(&KeyboardReport, sizeof(KeyboardReport)); /* Indicate if the modifier byte is non-zero (special key such as shift is being pressed) */ LEDs_ChangeLEDs(LEDS_LED1, (KeyboardReport.Modifier) ? LEDS_LED1 : 0); /* Check if a key has been pressed */ if (KeyboardReport.KeyCode) { /* Toggle status LED to indicate keypress */ LEDs_ToggleLEDs(LEDS_LED2); char PressedKey = 0; /* Retrieve pressed key character if alphanumeric */ if ((KeyboardReport.KeyCode[0] >= 0x04) && (KeyboardReport.KeyCode[0] <= 0x1D)) PressedKey = (KeyboardReport.KeyCode[0] - 0x04) + 'A'; else if ((KeyboardReport.KeyCode[0] >= 0x1E) && (KeyboardReport.KeyCode[0] <= 0x27)) PressedKey = (KeyboardReport.KeyCode[0] - 0x1E) + '0'; else if (KeyboardReport.KeyCode[0] == 0x2C) PressedKey = ' '; else if (KeyboardReport.KeyCode[0] == 0x28) PressedKey = '\n'; /* Print the pressed key character out through the serial port if valid */ if (PressedKey) putchar(PressedKey); } } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); /* Refreeze keyboard data pipe */ Pipe_Freeze(); }
/** Waits until the attached device is ready to accept data following a CBW, checking * to ensure that the device has not stalled the transaction. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_WaitForDataReceived(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; /* Unfreeze the OUT pipe so that it can be checked */ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received in the IN pipe */ while (!(Pipe_IsINReceived())) { /* Check to see if a new frame has been issued (1ms elapsed) */ if (USB_INT_HasOccurred(USB_INT_HSOFI)) { /* Clear the flag and decrement the timeout period counter */ USB_INT_Clear(USB_INT_HSOFI); TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ MassStore_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); return PIPE_RWSTREAM_PipeStalled; } Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ MassStore_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (!(USB_IsConnected)) return PIPE_RWSTREAM_DeviceDisconnected; }; return PIPE_RWSTREAM_NoError; }
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) { uint16_t TimeoutMSRem = MS_COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(MSInterfaceInfo->Config.DataOUTPipeNumber); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(MSInterfaceInfo->Config.DataINPipeNumber); return PIPE_RWSTREAM_PipeStalled; } if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; }; Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { bool IsEventReceived = false; if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return false; Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address); Pipe_Unfreeze(); if (Pipe_IsINReceived()) IsEventReceived = true; Pipe_Freeze(); return IsEventReceived; }
/** Task to set the configuration of the attached device after it has been enumerated. */ void AndroidHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; /* Select the data IN pipe */ Pipe_SelectPipe(ANDROID_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Re-freeze IN pipe after the packet has been received */ Pipe_Freeze(); /* Check if data is in the pipe */ if (Pipe_IsReadWriteAllowed()) { uint8_t NextReceivedByte = Pipe_Read_8(); uint8_t LEDMask = LEDS_NO_LEDS; if (NextReceivedByte & 0x01) LEDMask |= LEDS_LED1; if (NextReceivedByte & 0x02) LEDMask |= LEDS_LED2; if (NextReceivedByte & 0x04) LEDMask |= LEDS_LED3; if (NextReceivedByte & 0x08) LEDMask |= LEDS_LED4; LEDs_SetAllLEDs(LEDMask); } else { /* Clear the pipe after all data in the packet has been read, ready for the next packet */ Pipe_ClearIN(); } } /* Re-freeze IN pipe after use */ Pipe_Freeze(); }
/** Reads in and discards the next report from the attached device. */ void DiscardNextReport(void) { /* Select and unfreeze HID data IN pipe */ Pipe_SelectPipe(HID_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (!(Pipe_IsINReceived())) { /* Refreeze HID data IN pipe */ Pipe_Freeze(); return; } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); /* Refreeze HID data IN pipe */ Pipe_Freeze(); }
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) { uint8_t portnum = CDCInterfaceInfo->Config.PortNumber; if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive)) return; Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_Unfreeze(); if (Pipe_IsINReceived(portnum)) { USB_Request_Header_t Notification; Pipe_Read_Stream_LE(portnum,&Notification, sizeof(USB_Request_Header_t), NULL); if ((Notification.bRequest == CDC_NOTIF_SerialState) && (Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))) { Pipe_Read_Stream_LE(portnum, &CDCInterfaceInfo->State.ControlLineStates.DeviceToHost, sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), NULL); Pipe_ClearIN(portnum); EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo); } else { Pipe_ClearIN(portnum); } } Pipe_Freeze(); #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) CDC_Host_Flush(CDCInterfaceInfo); #endif }
uint8_t Pipe_WaitUntilReady(void) { #if (USB_STREAM_TIMEOUT_MS < 0xFF) uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #else uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #endif uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); for (;;) { if (Pipe_GetPipeToken() == PIPE_TOKEN_IN) { if (Pipe_IsINReceived()) return PIPE_READYWAIT_NoError; } else { if (Pipe_IsOUTReady()) return PIPE_READYWAIT_NoError; } if (Pipe_IsStalled()) return PIPE_READYWAIT_PipeStalled; else if (USB_HostState == HOST_STATE_Unattached) return PIPE_READYWAIT_DeviceDisconnected; uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; } } }
static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType) { #if (USB_HOST_TIMEOUT_MS < 0xFF) uint8_t TimeoutCounter = USB_HOST_TIMEOUT_MS; #else uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS; #endif while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSETUPSent()) || ((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsINReceived()) || ((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsOUTReady()))) { uint8_t ErrorCode; if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) return ErrorCode; if (!(TimeoutCounter--)) return HOST_SENDCONTROL_SoftwareTimeOut; } return HOST_SENDCONTROL_Successful; }
/** Reads in and processes the next report from the attached device, displaying the report * contents on the board LEDs and via the serial port. */ void ReadNextReport(void) { /* Select and unfreeze HID data IN pipe */ Pipe_SelectPipe(HID_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (!(Pipe_IsINReceived())) { /* Refreeze HID data IN pipe */ Pipe_Freeze(); return; } /* Ensure pipe contains data before trying to read from it */ if (Pipe_IsReadWriteAllowed()) { uint8_t ReportINData[Pipe_BytesInPipe()]; /* Read in HID report data */ Pipe_Read_Stream_LE(&ReportINData, sizeof(ReportINData)); /* Print report data through the serial port */ for (uint16_t CurrByte = 0; CurrByte < sizeof(ReportINData); CurrByte++) printf_P(PSTR("0x%02X "), ReportINData[CurrByte]); puts_P(PSTR("\r\n")); } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); /* Refreeze HID data IN pipe */ Pipe_Freeze(); }
/** Task to set the configuration of the attached device after it has been enumerated, and to read in * data received from the attached CDC device and print it to the serial port. */ void CDC_Host_Task(void) { uint8_t ErrorCode; switch (USB_HostState) { case HOST_STATE_Addressed: puts_P(PSTR("Getting Config Data.\r\n")); /* Get and process the configuration descriptor data */ if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("CDC Device Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* Select and the data IN pipe */ Pipe_SelectPipe(CDC_DATAPIPE_IN); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Re-freeze IN pipe after the packet has been received */ Pipe_Freeze(); /* Check if data is in the pipe */ if (Pipe_IsReadWriteAllowed()) { /* Get the length of the pipe data, and create a new buffer to hold it */ uint16_t BufferLength = Pipe_BytesInPipe(); uint8_t Buffer[BufferLength]; /* Read in the pipe data to the temporary buffer */ Pipe_Read_Stream_LE(Buffer, BufferLength); /* Print out the buffer contents to the USART */ for (uint16_t BufferByte = 0; BufferByte < BufferLength; BufferByte++) putchar(Buffer[BufferByte]); } /* Clear the pipe after it is read, ready for the next packet */ Pipe_ClearIN(); } /* Re-freeze IN pipe after use */ Pipe_Freeze(); /* Select and unfreeze the notification pipe */ Pipe_SelectPipe(CDC_NOTIFICATIONPIPE); Pipe_Unfreeze(); /* Check if a packet has been received */ if (Pipe_IsINReceived()) { /* Discard the unused event notification */ Pipe_ClearIN(); } /* Freeze notification IN pipe after use */ Pipe_Freeze(); break; } }
/** Waits until the attached device is ready to accept data following a CBW, checking * to ensure that the device has not stalled the transaction. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_WaitForDataReceived(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received in the IN pipe */ while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); /* Check to see if a new frame has been issued (1ms elapsed) */ if (CurrentFrameNumber != PreviousFrameNumber) { /* Save the new frame number and decrement the timeout period */ PreviousFrameNumber = CurrentFrameNumber; TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ USB_Host_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ USB_Host_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; }; Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Function to receive a PIMA response container from the attached still image device. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t SImage_ReceiveBlockHeader(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); /* Unfreeze the data IN pipe */ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received on the IN pipe */ while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); /* Check to see if a new frame has been issued (1ms elapsed) */ if (CurrentFrameNumber != PreviousFrameNumber) { /* Save the new frame number and decrement the timeout period */ PreviousFrameNumber = CurrentFrameNumber; TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); /* Return error code and break out of the loop */ return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); /* Return error code */ return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } /* Load in the response from the attached device */ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock, PIMA_COMMAND_SIZE(0), NULL); /* Check if the returned block type is a response block */ if (PIMA_ReceivedBlock.Type == PIMA_CONTAINER_ResponseBlock) { /* Determine the size of the parameters in the block via the data length attribute */ uint8_t ParamBytes = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0)); /* Check if the device has returned any parameters */ if (ParamBytes) { /* Read the PIMA parameters from the data IN pipe */ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock.Params, ParamBytes, NULL); } /* Clear pipe bank after use */ Pipe_ClearIN(); } /* Freeze the IN pipe after use */ Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) { uint8_t ErrorCode; uint16_t AccessoryProtocol; if ((ErrorCode = AOA_Host_GetAccessoryProtocol(&AccessoryProtocol)) != HOST_WAITERROR_Successful) return ErrorCode; if (AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1)) return AOA_ERROR_LOGICAL_CMD_FAILED; for (uint8_t PropertyIndex = 0; PropertyIndex < AOA_STRING_TOTAL_STRINGS; PropertyIndex++) { if ((ErrorCode = AOA_Host_SendPropertyString(AOAInterfaceInfo, PropertyIndex)) != HOST_WAITERROR_Successful) return ErrorCode; } USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE), .bRequest = AOA_REQ_StartAccessoryMode, .wValue = 0, .wIndex = 0, .wLength = 0, }; Pipe_SelectPipe(PIPE_CONTROLPIPE); return USB_Host_SendControlRequest(NULL); } static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol) { USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE), .bRequest = AOA_REQ_GetAccessoryProtocol, .wValue = 0, .wIndex = 0, .wLength = sizeof(uint16_t), }; Pipe_SelectPipe(PIPE_CONTROLPIPE); return USB_Host_SendControlRequest(Protocol); } static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, const uint8_t StringIndex) { const char* String = ((char**)&AOAInterfaceInfo->Config.PropertyStrings)[StringIndex]; if (String == NULL) String = ""; USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE), .bRequest = AOA_REQ_SendString, .wValue = 0, .wIndex = StringIndex, .wLength = (strlen(String) + 1), }; Pipe_SelectPipe(PIPE_CONTROLPIPE); return USB_Host_SendControlRequest((char*)String); } uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, const uint8_t* const Buffer, const uint16_t Length) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return PIPE_READYWAIT_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL); Pipe_Freeze(); return ErrorCode; } uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, const char* const String) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return PIPE_READYWAIT_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL); Pipe_Freeze(); return ErrorCode; } uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, const uint8_t Data) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return PIPE_READYWAIT_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (!(Pipe_IsReadWriteAllowed())) { Pipe_ClearOUT(); if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) return ErrorCode; } Pipe_Write_8(Data); Pipe_Freeze(); return PIPE_READYWAIT_NoError; } uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return 0; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { if (!(Pipe_BytesInPipe())) { Pipe_ClearIN(); Pipe_Freeze(); return 0; } else { Pipe_Freeze(); return Pipe_BytesInPipe(); } } else { Pipe_Freeze(); return 0; } } int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return -1; int16_t ReceivedByte = -1; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { if (Pipe_BytesInPipe()) ReceivedByte = Pipe_Read_8(); if (!(Pipe_BytesInPipe())) Pipe_ClearIN(); } Pipe_Freeze(); return ReceivedByte; } uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive)) return PIPE_READYWAIT_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (!(Pipe_BytesInPipe())) return PIPE_READYWAIT_NoError; bool BankFull = !(Pipe_IsReadWriteAllowed()); Pipe_ClearOUT(); if (BankFull) { if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) return ErrorCode; Pipe_ClearOUT(); } Pipe_Freeze(); return PIPE_READYWAIT_NoError; } #if defined(FDEV_SETUP_STREAM) void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, FILE* const Stream) { *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar, _FDEV_SETUP_RW); fdev_set_udata(Stream, AOAInterfaceInfo); } void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo, FILE* const Stream) { *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar_Blocking, _FDEV_SETUP_RW); fdev_set_udata(Stream, AOAInterfaceInfo); }
/** Task to read in and processes the next report from the attached device, displaying the report * contents on the board LEDs and via the serial port. */ void KeyboardHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; /* Select keyboard data pipe */ Pipe_SelectPipe(KEYBOARD_DATA_IN_PIPE); /* Unfreeze keyboard data pipe */ Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (!(Pipe_IsINReceived())) { /* Refreeze HID data IN pipe */ Pipe_Freeze(); return; } /* Ensure pipe contains data before trying to read from it */ if (Pipe_IsReadWriteAllowed()) { USB_KeyboardReport_Data_t KeyboardReport; /* Read in keyboard report data */ Pipe_Read_Stream_LE(&KeyboardReport, sizeof(KeyboardReport), NULL); /* Indicate if the modifier byte is non-zero (special key such as shift is being pressed) */ LEDs_ChangeLEDs(LEDS_LED1, (KeyboardReport.Modifier) ? LEDS_LED1 : 0); uint8_t KeyCode = KeyboardReport.KeyCode[0]; /* Check if a key has been pressed */ if (KeyCode) { /* Toggle status LED to indicate keypress */ LEDs_ToggleLEDs(LEDS_LED2); char PressedKey = 0; /* Retrieve pressed key character if alphanumeric */ if ((KeyCode >= HID_KEYBOARD_SC_A) && (KeyCode <= HID_KEYBOARD_SC_Z)) { PressedKey = (KeyCode - HID_KEYBOARD_SC_A) + 'A'; } else if ((KeyCode >= HID_KEYBOARD_SC_1_AND_EXCLAMATION) & (KeyCode < HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS)) { PressedKey = (KeyCode - HID_KEYBOARD_SC_1_AND_EXCLAMATION) + '1'; } else if (KeyCode == HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS) { PressedKey = '0'; } else if (KeyCode == HID_KEYBOARD_SC_SPACE) { PressedKey = ' '; } else if (KeyCode == HID_KEYBOARD_SC_ENTER) { PressedKey = '\n'; } /* Print the pressed key character out through the serial port if valid */ if (PressedKey) putchar(PressedKey); } } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); /* Refreeze keyboard data pipe */ Pipe_Freeze(); }
/** Task to set the configuration of the attached device after it has been enumerated, and to read and process * the HID report descriptor and HID reports from the device and display the results onto the board LEDs. */ void Joystick_HID_Task(void) { uint8_t ErrorCode; /* Switch to determine what user-application handled host state the host state machine is in */ switch (USB_HostState) { case HOST_STATE_Addressed: puts_P(PSTR("Getting Config Data.\r\n")); /* Get and process the configuration descriptor data */ if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } printf_P(PSTR("Processing HID Report (Size %d Bytes).\r\n"), HIDReportSize); /* Get and process the device's first HID report descriptor */ if ((ErrorCode = GetHIDReportData()) != ParseSuccessful) { puts_P(PSTR(ESC_FG_RED "Report Parse Error.\r\n")); if (!(HIDReportInfo.TotalReportItems)) puts_P(PSTR("Not a valid Joystick." ESC_FG_WHITE)); else printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Joystick Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* Select and unfreeze joystick data pipe */ Pipe_SelectPipe(JOYSTICK_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Check if data has been received from the attached joystick */ if (Pipe_IsReadWriteAllowed()) { /* Create buffer big enough for the report */ uint8_t JoystickReport[Pipe_BytesInPipe()]; /* Load in the joystick report */ Pipe_Read_Stream_LE(JoystickReport, Pipe_BytesInPipe(), NULL); /* Process the read in joystick report from the device */ ProcessJoystickReport(JoystickReport); } /* Clear the IN endpoint, ready for next data packet */ Pipe_ClearIN(); } /* Freeze joystick data pipe */ Pipe_Freeze(); break; } }
/** Task to set the configuration of the attached device after it has been enumerated. */ void Android_Host_Task(void) { uint8_t ErrorCode; switch (USB_HostState) { case HOST_STATE_Addressed: puts_P(PSTR("Getting Device Data.\r\n")); /* Get and process the configuration descriptor data */ ErrorCode = ProcessDeviceDescriptor(); /* Save whether the Android device needs to be mode-switched later on */ bool RequiresModeSwitch = (ErrorCode == NonAccessoryModeAndroidDevice); /* Error out if the device is not an Android device or an error occurred */ if ((ErrorCode != AccessoryModeAndroidDevice) && !(RequiresModeSwitch)) { if (ErrorCode == DevControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Device).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDS_LED1); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } printf_P(PSTR("Android Device Detected - %sAccessory mode.\r\n"), (RequiresModeSwitch ? "Non-" : "")); /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDS_LED1); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Check if a valid Android device was attached, but it is not current in Accessory mode */ if (RequiresModeSwitch) { USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE), .bRequest = ANDROID_Req_StartAccessoryMode, .wValue = 0, .wIndex = 0, .wLength = 0, }; /* Send the control request for the Android device to switch to accessory mode */ Pipe_SelectPipe(PIPE_CONTROLPIPE); USB_Host_SendControlRequest(NULL); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Getting Config Data.\r\n")); /* Get and process the configuration descriptor data */ if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); else puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDS_LED1); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Accessory Mode Android Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* Select the data IN pipe */ Pipe_SelectPipe(ANDROID_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { /* Re-freeze IN pipe after the packet has been received */ Pipe_Freeze(); /* Check if data is in the pipe */ if (Pipe_IsReadWriteAllowed()) { uint8_t NextReceivedByte = Pipe_BytesInPipe(); uint8_t LEDMask = LEDS_NO_LEDS; if (NextReceivedByte & 0x01) LEDMask |= LEDS_LED1; if (NextReceivedByte & 0x02) LEDMask |= LEDS_LED2; if (NextReceivedByte & 0x04) LEDMask |= LEDS_LED3; if (NextReceivedByte & 0x08) LEDMask |= LEDS_LED4; LEDs_SetAllLEDs(LEDMask); } else { /* Clear the pipe after all data in the packet has been read, ready for the next packet */ Pipe_ClearIN(); } } /* Re-freeze IN pipe after use */ Pipe_Freeze(); break; } }
uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, PIMA_Container_t* const PIMAHeader) { uint16_t TimeoutMSRem = SI_COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber); return PIPE_RWSTREAM_PipeStalled; } if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK); if (PIMAHeader->Type == PIMA_CONTAINER_ResponseBlock) { uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); if (ParamBytes) Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK); Pipe_ClearIN(); } Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Task to read in note on/off messages from the attached MIDI device and print it to the serial port. * When the board joystick or buttons are pressed, note on/off messages are sent to the attached device. */ void MIDIHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; Pipe_SelectPipe(MIDI_DATA_IN_PIPE); Pipe_Unfreeze(); if (Pipe_IsINReceived()) { MIDI_EventPacket_t MIDIEvent; Pipe_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); if (!(Pipe_BytesInPipe())) Pipe_ClearIN(); bool NoteOnEvent = (MIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_ON)); bool NoteOffEvent = (MIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_OFF)); if (NoteOnEvent || NoteOffEvent) { printf_P(PSTR("MIDI Note %s - Channel %d, Pitch %d, Velocity %d\r\n"), NoteOnEvent ? "On" : "Off", ((MIDIEvent.Data1 & 0x0F) + 1), MIDIEvent.Data2, MIDIEvent.Data3); } } Pipe_Freeze(); Pipe_SelectPipe(MIDI_DATA_OUT_PIPE); Pipe_Unfreeze(); if (Pipe_IsOUTReady()) { uint8_t MIDICommand = 0; uint8_t MIDIPitch; static uint8_t PrevJoystickStatus; 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 pipe */ Pipe_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); /* Send the data in the pipe to the device */ Pipe_ClearOUT(); } Pipe_Freeze(); /* Save previous joystick value for next joystick change detection */ PrevJoystickStatus = JoystickStatus; } }