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 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; }
/** 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_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; }
uint8_t USB_Host_SendControlRequest(void* const BufferPtr) { uint8_t* DataStream = (uint8_t*)BufferPtr; uint16_t DataLen = USB_ControlRequest.wLength; if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_HOSTTODEVICE) { Pipe_Write_Stream_LE(BufferPtr, DataLen, NULL); } HcdControlTransfer(PipeInfo[pipeselected].PipeHandle, &USB_ControlRequest, PipeInfo[pipeselected].Buffer); /* TODO Control Transfer Status */ if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) { PipeInfo[pipeselected].ByteTransfered = USB_ControlRequest.wLength; // FIXME assume no errors while(DataLen) { *(DataStream++) = Pipe_Read_8(); DataLen--; } /* Pipe_Read_Stream_LE(BufferPtr, DataLen, NULL); cannot use read stream as it call HcdDataTransfer*/ } PipeInfo[pipeselected].StartIdx = PipeInfo[pipeselected].ByteTransfered = 0; /* Clear Control Pipe */ return HOST_SENDCONTROL_Successful; }
uint8_t USB_Host_SendControlRequest(const uint8_t corenum, void* const BufferPtr) { uint8_t* DataStream = (uint8_t*)BufferPtr; uint16_t DataLen = USB_ControlRequest.wLength; uint8_t ret; if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_HOSTTODEVICE) { Pipe_Write_Stream_LE(corenum, BufferPtr, DataLen, NULL); } ret = (uint8_t)HcdControlTransfer(PipeInfo[corenum][pipeselected[corenum]].PipeHandle, &USB_ControlRequest, PipeInfo[corenum][pipeselected[corenum]].Buffer); if(ret == (uint8_t)HOST_SENDCONTROL_Successful) { if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) { PipeInfo[corenum][pipeselected[corenum]].ByteTransfered = USB_ControlRequest.wLength; while(DataLen) { *(DataStream++) = Pipe_Read_8(corenum); DataLen--; } /* Pipe_Read_Stream_LE(BufferPtr, DataLen, NULL); cannot use read stream as it call HcdDataTransfer*/ } PipeInfo[corenum][pipeselected[corenum]].StartIdx = PipeInfo[corenum][pipeselected[corenum]].ByteTransfered = 0; /* Clear Control Pipe */ return HOST_SENDCONTROL_Successful; } else { return HOST_SENDCONTROL_PipeError; } }
/** 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; }
/** Sends a packet to the remote device on the specified channel. * * \param[in] Data Pointer to a buffer where the data is to be sourced from * \param[in] DataLen Length of the data to send * \param[in] ACLChannel ACL channel information structure containing the destination channel's information, NULL * to send to the remote device's signaling channel * * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum */ uint8_t Bluetooth_SendPacket(void* Data, const uint16_t DataLen, Bluetooth_Channel_t* const ACLChannel) { BT_ACL_Header_t ACLPacketHeader; BT_DataPacket_Header_t DataHeader; /* A remote device must be connected before a packet transmission is attempted */ if (!(Bluetooth_Connection.IsConnected)) return BT_SENDPACKET_NotConnected; /* If the destination channel is not the signaling channel and it is not currently fully open, abort */ if ((ACLChannel != NULL) && (ACLChannel->State != BT_Channel_Open)) return BT_SENDPACKET_ChannelNotOpen; /* Fill out the packet's header from the remote device connection information structure */ ACLPacketHeader.ConnectionHandle = (Bluetooth_Connection.ConnectionHandle | BT_ACL_FIRST_AUTOFLUSH); ACLPacketHeader.DataLength = sizeof(DataHeader) + DataLen; DataHeader.PayloadLength = DataLen; DataHeader.DestinationChannel = (ACLChannel == NULL) ? BT_CHANNEL_SIGNALING : ACLChannel->RemoteNumber; Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE); Pipe_WaitUntilReady(); Pipe_Unfreeze(); /* Write the packet contents to the pipe so that it can be sent to the remote device */ Pipe_Write_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader)); Pipe_Write_Stream_LE(&DataHeader, sizeof(DataHeader)); Pipe_Write_Stream_LE(Data, DataLen); Pipe_ClearOUT(); Pipe_Freeze(); BT_ACL_DEBUG(2, ""); BT_ACL_DEBUG(2, "Packet Sent"); BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF)); BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength); BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel); BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader.PayloadLength); return BT_SENDPACKET_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_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes) { uint8_t ErrorCode; Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK); Pipe_ClearOUT(); Pipe_Freeze(); return ErrorCode; }
/** 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; }
uint8_t MIDI_Host_SendEventPacket(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; uint8_t ErrorCode; Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber); if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError) return ErrorCode; if (!(Pipe_IsReadWriteAllowed())) Pipe_ClearOUT(); return PIPE_RWSTREAM_NoError; }
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; }
uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes) { uint8_t ErrorCode; if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK); Pipe_ClearOUT(); Pipe_Freeze(); return ErrorCode; }
/** Sends the given data directly to the printer via the data endpoints, for the sending of print commands in printer * languages accepted by the attached printer (e.g. PCL). * * \param[in] PrinterCommands Pointer to the data to send to the attached printer * \param[in] CommandSize Size of the data to send to the attached printer * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t Printer_SendData(const void* const PrinterCommands, const uint16_t CommandSize) { uint8_t ErrorCode; Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, CommandSize, NULL)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_ClearOUT(); Pipe_WaitUntilReady(); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Function to send the given data to the device, after a command block has been issued. * * \param[in] Buffer Source data buffer to send to the device * \param[in] Bytes Number of bytes to send * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t SImage_SendData(void* const Buffer, const uint16_t Bytes) { uint8_t ErrorCode; /* Unfreeze the data OUT pipe */ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Write the data contents to the pipe */ ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NULL); /* Send the last packet to the attached device */ Pipe_ClearOUT(); /* Freeze the pipe again after use */ Pipe_Freeze(); return ErrorCode; }
/** Sends the given data directly to the printer via the data endpoints, for the sending of print commands in printer * languages accepted by the attached printer (e.g. PCL). * * \param[in] PrinterCommands Pointer to the data to send to the attached printer * \param[in] CommandSize Size of the data to send to the attached printer * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t Printer_SendData(const void* const PrinterCommands, const uint16_t CommandSize) { uint8_t ErrorCode; Pipe_SelectPipe(PRINTER_DATA_OUT_PIPE); Pipe_Unfreeze(); if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, CommandSize)) != PIPE_RWSTREAM_NoError) return ErrorCode; Pipe_ClearOUT(); while (!(Pipe_IsOUTReady())) { if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** 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; }
void CALLBACK_Bluetooth_SendPacket(BT_StackConfig_t* const StackState, const uint8_t Type, const uint16_t Length) { /* Determine the type of packet being sent, use appropriate pipe */ switch (Type) { case BLUETOOTH_PACKET_HCICommand: USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_DEVICE), .bRequest = 0, .wValue = 0, .wIndex = 0, .wLength = Length }; /* HCI commands must be sent over the Control pipe */ Pipe_SelectPipe(PIPE_CONTROLPIPE); USB_Host_SendControlRequest(StackState->Config.PacketBuffer); break; case BLUETOOTH_PACKET_HCIData: Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE); /* HCI data packets must be sent over the Data OUT pipe */ Pipe_Unfreeze(); Pipe_Write_Stream_LE(StackState->Config.PacketBuffer, Length, NULL); Pipe_ClearOUT(); Pipe_Freeze(); break; } // RGB_SetColour(RGB_ALIAS_Connected); } void EVENT_Bluetooth_InitComplete(BT_StackConfig_t* const StackState) { /* Save the local BDADDR of the connected Bluetooth adapter for later use */ // eeprom_update_block(BluetoothAdapter_Stack.State.HCI.LocalBDADDR, BluetoothAdapter_LastLocalBDADDR, sizeof(BDADDR_t)); }
/** Routine to send the current CBW to the device, and increment the Tag value as needed. * * \param[in] SCSICommandBlock Pointer to a SCSI command block structure to send to the attached device * \param[in,out] BufferPtr Pointer to a buffer for the data to send or receive to/from the device, or NULL if no data * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* const SCSICommandBlock, void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Each transmission should have a unique tag value, increment before use */ SCSICommandBlock->Tag = ++MassStore_Tag; /* Wrap Tag value when invalid - MS class defines tag values of 0 and 0xFFFFFFFF to be invalid */ 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(); /* Wait until command has been sent */ Pipe_WaitUntilReady(); /* Freeze pipe after use */ Pipe_Freeze(); /* Send data if any */ if ((BufferPtr != NULL) && ((ErrorCode = MassStore_SendReceiveData(SCSICommandBlock, BufferPtr)) != PIPE_READYWAIT_NoError)) { Pipe_Freeze(); return ErrorCode; } return ErrorCode; }
/** 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; } }
/** Writes a report to the attached device. * * \param[in] ReportOUTData Buffer containing the report to send to the device * \param[in] ReportIndex Index of the report in the device (zero if the device does not use multiple reports) * \param[in] ReportType Type of report to send, either REPORT_TYPE_OUT or REPORT_TYPE_FEATURE * \param[in] ReportLength Length of the report to send */ void WriteNextReport(uint8_t* ReportOUTData, const uint8_t ReportIndex, const uint8_t ReportType, uint16_t ReportLength) { /* Select the 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() && (ReportType == REPORT_TYPE_OUT)) { Pipe_Unfreeze(); /* Ensure pipe is ready to be written to before continuing */ if (!(Pipe_IsOUTReady())) { /* Refreeze the data OUT pipe */ Pipe_Freeze(); return; } /* If the report index is used, send it before the report data */ if (ReportIndex) Pipe_Write_Byte(ReportIndex); /* Write out HID report data */ Pipe_Write_Stream_LE(ReportOUTData, ReportLength); /* 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 = ((ReportType << 8) | ReportIndex), .wIndex = 0, .wLength = ReportLength, }; /* Select the control pipe for the request transfer */ Pipe_SelectPipe(PIPE_CONTROLPIPE); /* Send the request to the device */ USB_Host_SendControlRequest(ReportOUTData); } } /** Task to set the configuration of the attached device after it has been enumerated, and to read and process * HID reports from the device and to send reports if desired. */ void HID_Host_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 status */ 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 status */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); /* Wait until USB device disconnected */ USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("HID Device Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: ReadNextReport(); break; } }
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); }