/** 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; }
/** 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 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); }
/** Sends or receives the transaction's data stage to or from the attached device, reading or * writing to the nominated buffer. * * \param[in] SCSICommandBlock Pointer to a SCSI command block structure being sent to the attached device * \param[in,out] BufferPtr Pointer to the data buffer to read from or write to * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_SendReceiveData(CommandBlockWrapper_t* const SCSICommandBlock, void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; uint16_t BytesRem = SCSICommandBlock->DataTransferLength; /* Check the direction of the SCSI command data stage */ if (SCSICommandBlock->Flags & COMMAND_DIRECTION_DATA_IN) { /* Wait until the device has replied with some data */ if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Read in the block data from the pipe */ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Acknowledge the packet */ Pipe_ClearIN(); } else { /* Select the OUT data pipe for data transmission */ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Write the block data to the pipe */ if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Acknowledge the packet */ Pipe_ClearOUT(); while (!(Pipe_IsOUTReady())) { if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } } /* Freeze used pipe after use */ Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
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(); }
/** 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(); }
/** Routine to send the current CBW to the device, and increment the Tag value as needed. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_SendCommand(void) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Each transmission should have a unique tag value, excluding values 0 and 0xFFFFFFFF */ if (++MassStore_Tag == 0xFFFFFFFF) MassStore_Tag = 1; /* Select the OUT data pipe for CBW transmission */ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Write the CBW command to the OUT pipe */ if ((ErrorCode = Pipe_Write_Stream_LE(&SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Send the data in the OUT pipe to the attached device */ Pipe_ClearOUT(); while(!(Pipe_IsOUTReady())); /* Freeze pipe after use */ Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Function to send the PIMA command container to the attached still image device. */ void SImage_SendBlockHeader(void) { /* Unfreeze the data OUT pipe ready for data transmission */ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Write the PIMA block to the data OUT pipe */ Pipe_Write_Stream_LE(&PIMA_SendBlock, PIMA_COMMAND_SIZE(0), NULL); /* If the block type is a command, send its parameters (if any) */ if (PIMA_SendBlock.Type == PIMA_CONTAINER_CommandBlock) { /* Determine the size of the parameters in the block via the data length attribute */ uint8_t ParamBytes = (PIMA_SendBlock.DataLength - PIMA_COMMAND_SIZE(0)); /* Check if any parameters in the command block */ if (ParamBytes) { /* Write the PIMA parameters to the data OUT pipe */ Pipe_Write_Stream_LE(&PIMA_SendBlock.Params, ParamBytes, NULL); } /* Send the PIMA command block to the attached device */ Pipe_ClearOUT(); } /* Freeze pipe after use */ Pipe_Freeze(); }
static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, MS_CommandStatusWrapper_t* const SCSICommandStatus) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t), NULL)) != PIPE_RWSTREAM_NoError) { return ErrorCode; } Pipe_ClearIN(); Pipe_Freeze(); if (SCSICommandStatus->Status != MS_SCSI_COMMAND_Pass) ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED; return ErrorCode; }
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; }
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, MS_CommandBlockWrapper_t* const SCSICommandBlock, const void* const BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; SCSICommandBlock->Signature = MS_CBW_SIGNATURE; SCSICommandBlock->Tag = ++MSInterfaceInfo->State.TransactionTag; if (MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF) MSInterfaceInfo->State.TransactionTag = 1; Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t), NULL)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_ClearOUT(); Pipe_WaitUntilReady(); Pipe_Freeze(); if ((BufferPtr != NULL) && ((ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, SCSICommandBlock, (void*)BufferPtr)) != PIPE_RWSTREAM_NoError)) { Pipe_Freeze(); return ErrorCode; } return ErrorCode; }
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; }
static uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader) { uint8_t ErrorCode; PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++; Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) return ErrorCode; uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); if (ParamBytes) { if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) return ErrorCode; } Pipe_ClearOUT(); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, PIMA_Container_t* const PIMAHeader) { uint8_t ErrorCode; if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; if (SIInterfaceInfo->State.IsSessionOpen) PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++; Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) return ErrorCode; uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); if (ParamBytes) { if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) return ErrorCode; } Pipe_ClearOUT(); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
static uint8_t Bluetooth_SendHCICommand(void* Parameters, uint8_t ParamLength) { uint8_t CommandBuffer[sizeof(HCICommandHeader) + HCICommandHeader.ParameterLength]; USB_HostRequest = (USB_Host_Request_Header_t) { bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_DEVICE), bRequest: 0, wValue: 0, wIndex: 0, wLength: sizeof(CommandBuffer) }; memset(CommandBuffer, 0x00, sizeof(CommandBuffer)); memcpy(CommandBuffer, &HCICommandHeader, sizeof(HCICommandHeader)); if (ParamLength) memcpy(&CommandBuffer[sizeof(HCICommandHeader)], Parameters, ParamLength); return USB_Host_SendControlRequest(CommandBuffer); } static bool Bluetooth_GetNextHCIEventHeader(void) { Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE); Pipe_Unfreeze(); if (!(Pipe_ReadWriteAllowed())) return false; Pipe_Read_Stream_LE(&HCIEventHeader, sizeof(HCIEventHeader)); return true; }
/** Routine to receive the current CSW from the device. * * \param[out] SCSICommandStatus Pointer to a destination where the returned status data should be stored * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ static uint8_t MassStore_GetReturnedStatus(CommandStatusWrapper_t* const SCSICommandStatus) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* If an error in the command occurred, abort */ if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Load in the CSW from the attached device */ if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Clear the data ready for next reception */ Pipe_ClearIN(); /* Freeze the IN pipe after use */ Pipe_Freeze(); /* Check to see if command failed */ if (SCSICommandStatus->Status != Command_Pass) ErrorCode = MASS_STORE_SCSI_COMMAND_FAILED; return ErrorCode; }
/** 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(); }
static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, MS_CommandBlockWrapper_t* const SCSICommandBlock, void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; uint16_t BytesRem = SCSICommandBlock->DataTransferLength; if (SCSICommandBlock->Flags & MS_COMMAND_DIR_DATA_IN) { if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); return ErrorCode; } Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_ClearIN(); } else { Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_ClearOUT(); while (!(Pipe_IsOUTReady())) { if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } } Pipe_Freeze(); return ErrorCode; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a HID interface descriptor containing at least one Interrupt type IN endpoint. * * \return An error code from the MouseHostViaInt_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; /* Get Configuration Descriptor size from the device */ if (USB_Host_GetDeviceConfigDescriptor(&ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) return ControlError; /* Ensure that the Configuration Descriptor isn't too large */ if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE) return DescriptorTooLarge; /* Allocate enough memory for the entire config descriptor */ ConfigDescriptorData = alloca(ConfigDescriptorSize); /* Retrieve the entire configuration descriptor into the allocated buffer */ USB_Host_GetDeviceConfigDescriptor(&ConfigDescriptorSize, ConfigDescriptorData); /* Validate returned data - ensure first entry is a configuration header descriptor */ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return InvalidConfigDataReturned; /* Get the mouse interface from the configuration descriptor */ if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, NextMouseInterface)) { /* Descriptor not found, error out */ return NoHIDInterfaceFound; } /* Get the mouse interface's data endpoint descriptor */ if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, NextInterfaceMouseDataEndpoint)) { /* Descriptor not found, error out */ return NoEndpointFound; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); /* Configure the mouse data pipe */ Pipe_ConfigurePipe(MOUSE_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); Pipe_Unfreeze(); /* Enable the pipe IN interrupt for the data pipe */ USB_INT_Enable(PIPE_INT_IN); /* Valid data found, return success */ return SuccessfulConfigRead; }
/** Sends or receives the transaction's data stage to or from the attached device, reading or * writing to the nominated buffer. * * \param BufferPtr Pointer to the data buffer to read from or write to * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_SendReceiveData(void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; uint16_t BytesRem = SCSICommandBlock.Header.DataTransferLength; /* Check the direction of the SCSI command data stage */ if (SCSICommandBlock.Header.Flags & COMMAND_DIRECTION_DATA_IN) { /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Read in the block data from the pipe */ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Acknowledge the packet */ Pipe_ClearIN(); } else { /* Select the OUT data pipe for data transmission */ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Write the block data to the pipe */ if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Acknowledge the packet */ Pipe_ClearOUT(); while (!(Pipe_IsOUTReady())); } /* Freeze used pipe after use */ Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Writes a report to the attached device. * * \param[in] ReportOUTData Buffer containing the report to send to the device * \param[in] ReportLength Length of the report to send */ void WriteNextReport(uint8_t* const ReportOUTData, const uint16_t ReportLength) { if (USB_HostState != HOST_STATE_Configured) return; /* Select and unfreeze HID data OUT pipe */ Pipe_SelectPipe(HID_DATA_OUT_PIPE); /* Not all HID devices have an OUT endpoint (some require OUT reports to be sent over the * control endpoint instead) - check to see if the OUT endpoint has been initialized */ if (Pipe_IsConfigured()) { Pipe_Unfreeze(); /* Ensure pipe is ready to be written to before continuing */ if (!(Pipe_IsOUTReady())) { /* Refreeze the data OUT pipe */ Pipe_Freeze(); return; } /* Write out HID report data */ Pipe_Write_Stream_LE(ReportOUTData, ReportLength, NULL); /* Clear the OUT endpoint, send last data packet */ Pipe_ClearOUT(); /* Refreeze the data OUT pipe */ Pipe_Freeze(); } else { /* Class specific request to send a HID report to the device */ USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = HID_REQ_SetReport, .wValue = 0x02, .wIndex = 0x01, .wLength = ReportLength, }; /* Select the control pipe for the request transfer */ Pipe_SelectPipe(PIPE_CONTROLPIPE); /* Send the request to the device */ USB_Host_SendControlRequest(ReportOUTData); } }
uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes) { uint8_t ErrorCode; Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK); Pipe_Freeze(); return ErrorCode; }
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; }
uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader) { uint8_t ErrorCode; Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(SI_PIMA_Container_t), NO_STREAM_CALLBACK); Pipe_ClearIN(); Pipe_Freeze(); return ErrorCode; }
/** Function to receive the given data from the device, after a response block has been received. * * \param[out] Buffer Destination data buffer to put read bytes from the device * \param[in] Bytes Number of bytes to receive * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t SImage_ReadData(void* const Buffer, const uint16_t Bytes) { uint8_t ErrorCode; /* Unfreeze the data IN pipe */ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Read in the data into the buffer */ ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NULL); /* Freeze the pipe again after use */ Pipe_Freeze(); return ErrorCode; }
/** Task to read in data received from the attached RNDIS device and print it to the serial port. */ void RNDISHost_Task(void) { if (USB_HostState != HOST_STATE_Configured) return; uint8_t ErrorCode; LEDs_SetAllLEDs(LEDMASK_USB_BUSY); uint16_t PacketLength; if ((ErrorCode = RNDIS_GetPacketLength(&PacketLength)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Packet Reception Error.\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); return; } if (!(PacketLength)) return; Pipe_Unfreeze(); printf_P(PSTR("***PACKET (Size %d)***\r\n"), PacketLength); if (PacketLength > 1024) { puts_P(PSTR(ESC_FG_RED "Packet too large.\r\n" ESC_FG_WHITE)); Pipe_Discard_Stream(PacketLength, NULL); } else { uint8_t PacketBuffer[PacketLength]; Pipe_Read_Stream_LE(&PacketBuffer, PacketLength, NULL); for (uint16_t i = 0; i < PacketLength; i++) printf("0x%02x ", PacketBuffer[i]); } Pipe_ClearIN(); Pipe_Freeze(); printf("\r\n\r\n"); LEDs_SetAllLEDs(LEDMASK_USB_READY); }
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; }
/** 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; }