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; }
/** 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 MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipe.Address); Pipe_Unfreeze(); if (Pipe_BytesInPipe()) { Pipe_ClearOUT(); if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) { Pipe_Freeze(); return ErrorCode; } } Pipe_Freeze(); return PIPE_READYWAIT_NoError; }
/** 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(); }
bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo) { bool IsEventReceived = false; Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber); Pipe_Unfreeze(); if (Pipe_BytesInPipe()) IsEventReceived = true; Pipe_Freeze(); return IsEventReceived; }
/** Function to test if a PIMA event block is waiting to be read in from the attached device. * * \return True if an event is waiting to be read in from the device, false otherwise */ bool SImage_IsEventReceived(void) { bool IsEventReceived = false; /* Unfreeze the Event pipe */ Pipe_SelectPipe(SIMAGE_EVENTS_PIPE); Pipe_Unfreeze(); /* If the pipe contains data, an event has been received */ if (Pipe_BytesInPipe()) IsEventReceived = true; /* Freeze the pipe after use */ Pipe_Freeze(); return IsEventReceived; }
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.EventsPipeNumber); Pipe_Unfreeze(); if (Pipe_BytesInPipe()) IsEventReceived = true; Pipe_Freeze(); return IsEventReceived; }
bool Pipe_IsINReceived(const uint8_t corenum) { if (HCD_STATUS_OK != HcdGetPipeStatus(PipeInfo[corenum][pipeselected[corenum]].PipeHandle)) { return false; } if (Pipe_BytesInPipe(corenum)) { return true; } else { /* Empty Pipe */ HcdDataTransfer(PipeInfo[corenum][pipeselected[corenum]].PipeHandle, PipeInfo[corenum][pipeselected[corenum]].Buffer, HCD_ENDPOINT_MAXPACKET_XFER_LEN, &PipeInfo[corenum][pipeselected[corenum]].ByteTransfered); return false; } }
bool Pipe_IsINReceived(void) { if (HCD_STATUS_OK != HcdGetPipeStatus(PipeInfo[pipeselected].PipeHandle)) { return false; } if (Pipe_BytesInPipe()) { return true; } else /* Empty Pipe */ { HcdDataTransfer(PipeInfo[pipeselected].PipeHandle, PipeInfo[pipeselected].Buffer, HCD_ENDPOINT_MAXPACKET_XFER_LEN, &PipeInfo[pipeselected].ByteTransfered); return false; } }
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) { if (USB_HostState != HOST_STATE_Configured) return PIPE_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber); if (Pipe_BytesInPipe()) { Pipe_ClearOUT(); if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) return ErrorCode; } return PIPE_READYWAIT_NoError; }
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) { uint8_t portnum = MIDIInterfaceInfo->Config.PortNumber; uint8_t ErrorCode; if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; Pipe_SelectPipe(portnum,MIDIInterfaceInfo->Config.DataOUTPipeNumber); if (Pipe_BytesInPipe(portnum)) { Pipe_ClearOUT(portnum); if ((ErrorCode = Pipe_WaitUntilReady(portnum)) != PIPE_READYWAIT_NoError) return ErrorCode; } return PIPE_READYWAIT_NoError; }
/** 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(); }
static int CDC_getchar(FILE *stream) { int c; Pipe_SelectPipe(CDC_DATAPIPE_IN); for (;;) { if (Pipe_WaitUntilReady()) return -1; if (!(Pipe_BytesInPipe())) { Pipe_ClearOUT(); } else { c = Pipe_Read_Byte(); break; } } return c; }
/** 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; } }
/** 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; } }
uint8_t USB_Host_SendControlRequest(void* const BufferPtr) { uint8_t* DataStream = (uint8_t*)BufferPtr; bool BusSuspended = USB_Host_IsBusSuspended(); uint8_t ReturnStatus = HOST_SENDCONTROL_Successful; uint16_t DataLen = USB_ControlRequest.wLength; USB_Host_ResumeBus(); if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) goto End_Of_Control_Send; Pipe_SetPipeToken(PIPE_TOKEN_SETUP); Pipe_ClearError(); Pipe_Unfreeze(); Pipe_Write_8(USB_ControlRequest.bmRequestType); Pipe_Write_8(USB_ControlRequest.bRequest); Pipe_Write_16_LE(USB_ControlRequest.wValue); Pipe_Write_16_LE(USB_ControlRequest.wIndex); Pipe_Write_16_LE(USB_ControlRequest.wLength); Pipe_ClearSETUP(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_SetupSent)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; Pipe_Freeze(); if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) goto End_Of_Control_Send; if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) { Pipe_SetPipeToken(PIPE_TOKEN_IN); if (DataStream != NULL) { while (DataLen) { Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; if (!(Pipe_BytesInPipe())) DataLen = 0; while (Pipe_BytesInPipe() && DataLen) { *(DataStream++) = Pipe_Read_8(); DataLen--; } Pipe_Freeze(); Pipe_ClearIN(); } } Pipe_SetPipeToken(PIPE_TOKEN_OUT); Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; Pipe_ClearOUT(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; } else { if (DataStream != NULL) { Pipe_SetPipeToken(PIPE_TOKEN_OUT); Pipe_Unfreeze(); while (DataLen) { if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; while (DataLen && (Pipe_BytesInPipe() < USB_Host_ControlPipeSize)) { Pipe_Write_8(*(DataStream++)); DataLen--; } Pipe_ClearOUT(); } if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; Pipe_Freeze(); } Pipe_SetPipeToken(PIPE_TOKEN_IN); Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) goto End_Of_Control_Send; Pipe_ClearIN(); } End_Of_Control_Send: Pipe_Freeze(); if (BusSuspended) USB_Host_SuspendBus(); Pipe_ResetPipe(PIPE_CONTROLPIPE); return ReturnStatus; }
static uint8_t USB_Host_SendControlRequest_PRV(void* const BufferPtr) { uint8_t* DataStream = (uint8_t*)BufferPtr; uint8_t ReturnStatus = HOST_SENDCONTROL_Successful; uint16_t DataLen = USB_ControlRequest.wLength; USB_Host_ResumeBus(); if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) return ReturnStatus; Pipe_SetPipeToken(PIPE_TOKEN_SETUP); Pipe_ClearError(); Pipe_Unfreeze(); #if defined(ARCH_BIG_ENDIAN) Pipe_Write_8(USB_ControlRequest.bmRequestType); Pipe_Write_8(USB_ControlRequest.bRequest); Pipe_Write_16_LE(USB_ControlRequest.wValue); Pipe_Write_16_LE(USB_ControlRequest.wIndex); Pipe_Write_16_LE(USB_ControlRequest.wLength); #else uint8_t* HeaderStream = (uint8_t*)&USB_ControlRequest; for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Request_Header_t); HeaderByte++) Pipe_Write_8(*(HeaderStream++)); #endif Pipe_ClearSETUP(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_SetupSent)) != HOST_SENDCONTROL_Successful) return ReturnStatus; Pipe_Freeze(); if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) return ReturnStatus; if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) { Pipe_SetPipeToken(PIPE_TOKEN_IN); if (DataStream != NULL) { while (DataLen) { Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) return ReturnStatus; if (!(Pipe_BytesInPipe())) DataLen = 0; while (Pipe_BytesInPipe() && DataLen) { *(DataStream++) = Pipe_Read_8(); DataLen--; } Pipe_Freeze(); Pipe_ClearIN(); } } Pipe_SetPipeToken(PIPE_TOKEN_OUT); Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) return ReturnStatus; Pipe_ClearOUT(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) return ReturnStatus; } else { if (DataStream != NULL) { Pipe_SetPipeToken(PIPE_TOKEN_OUT); Pipe_Unfreeze(); while (DataLen) { if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) return ReturnStatus; while (DataLen && (Pipe_BytesInPipe() < USB_Host_ControlPipeSize)) { Pipe_Write_8(*(DataStream++)); DataLen--; } Pipe_ClearOUT(); } if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) return ReturnStatus; Pipe_Freeze(); } Pipe_SetPipeToken(PIPE_TOKEN_IN); Pipe_Unfreeze(); if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) return ReturnStatus; Pipe_ClearIN(); } return ReturnStatus; }
/** 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; } }
/** 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; } }
uint8_t Pipe_Discard_Stream(uint16_t Length #if !defined(NO_STREAM_CALLBACKS) , StreamCallbackPtr_t Callback #endif ) { uint8_t ErrorCode; Pipe_SetPipeToken(PIPE_TOKEN_IN); if ((ErrorCode = Pipe_WaitUntilReady())) return ErrorCode; #if defined(FAST_STREAM_TRANSFERS) uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07); if (Length >= 8) { Length -= BytesRemToAlignment; switch (BytesRemToAlignment) { default: do { if (!(Pipe_IsReadWriteAllowed())) { Pipe_ClearIN(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return PIPE_RWSTREAM_CallbackAborted; #endif if ((ErrorCode = Pipe_WaitUntilReady())) return ErrorCode; } Length -= 8; Pipe_Discard_Byte(); case 7: Pipe_Discard_Byte(); case 6: Pipe_Discard_Byte(); case 5: Pipe_Discard_Byte(); case 4: Pipe_Discard_Byte(); case 3: Pipe_Discard_Byte(); case 2: Pipe_Discard_Byte(); case 1: Pipe_Discard_Byte(); } while (Length >= 8); } } #endif while (Length) { if (!(Pipe_IsReadWriteAllowed())) { Pipe_ClearIN(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return PIPE_RWSTREAM_CallbackAborted; #endif if ((ErrorCode = Pipe_WaitUntilReady())) return ErrorCode; } else { Pipe_Discard_Byte(); Length--; } } 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); }