/** 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 display the results onto the board LEDs. */ void Mouse_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 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; } /* HID class request to set the mouse protocol to the Boot Protocol */ USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE), .bRequest = HID_REQ_SetProtocol, .wValue = 0, .wIndex = 0, .wLength = 0, }; /* Select the control pipe for the request transfer */ Pipe_SelectPipe(PIPE_CONTROLPIPE); /* Send the request, display error and wait for device detach if request fails */ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Protocol).\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("Mouse Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* If a report has been received, read and process it */ ReadNextReport(); break; } }
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and * starts the library USB task to begin the enumeration and USB management process. */ void EVENT_USB_Device_Connect(void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
/** Event handler for the library USB Configuration Changed event. */ void EVENT_USB_Device_ConfigurationChanged(void) { LEDs_SetAllLEDs(LEDMASK_USB_READY); if (!MIDI_Device_ConfigureEndpoints(&Keyboard_MIDI_Interface)) LEDs_SetAllLEDs(LEDMASK_USB_ERROR); }
/** Event handler for the USB_DeviceUnattached event. This indicates that a device has been removed from the host, and * stops the library USB task management process. */ void EVENT_USB_Host_DeviceUnattached(void) { puts_P(PSTR("\r\nDevice Unattached.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); }
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via * the status LEDs and stops the USB management task. */ void EVENT_USB_Device_Disconnect(void) { /* Indicate USB not ready */ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); }
/** Event handler for the USB_DeviceEnumerationComplete event. This indicates that a device has been successfully * enumerated by the host and is now ready to be used by the application. */ void EVENT_USB_Host_DeviceEnumerationComplete(void) { LEDs_SetAllLEDs(LEDMASK_USB_READY); }
/** Event handler for the USB_DeviceUnattached event. This indicates that a device has been removed from the host, and * stops the library USB task management process. */ void EVENT_USB_Host_DeviceUnattached(void) { puts_P(PSTR(ESC_FG_GREEN "\r\nDevice Unattached.\r\n" ESC_FG_WHITE)); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); }
/** Main program entry point. This routine configures the hardware required by the application, then * enters a loop to run the application tasks in sequence. */ int main(void) { SetupHardware(); puts_P(PSTR(ESC_FG_CYAN "CDC Host Demo running.\r\n" ESC_FG_WHITE)); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); for (;;) { switch (USB_HostState) { case HOST_STATE_Addressed: LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); uint16_t ConfigDescriptorSize; uint8_t ConfigDescriptorData[512]; if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData, sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful) { puts_P(PSTR("Error Retrieving Configuration Descriptor.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (CDC_Host_ConfigurePipes(&VirtualSerial_CDC_Interface, ConfigDescriptorSize, ConfigDescriptorData) != CDC_ENUMERROR_NoError) { puts_P(PSTR("Attached Device Not a Valid CDC Class Device.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful) { puts_P(PSTR("Error Setting Device Configuration.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("CDC Device Enumerated.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_READY); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: if (CDC_Host_BytesReceived(&VirtualSerial_CDC_Interface)) { /* Echo received bytes from the attached device through the USART */ int16_t ReceivedByte = CDC_Host_ReceiveByte(&VirtualSerial_CDC_Interface); if (!(ReceivedByte < 0)) putchar(ReceivedByte); } break; } CDC_Host_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); } }
/** Main program entry point. This routine configures the hardware required by the application, then * enters a loop to run the application tasks in sequence. */ int main(void) { SetupHardware(); puts_P(PSTR(ESC_FG_CYAN "Still Image Host Demo running.\r\n" ESC_FG_WHITE)); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); for (;;) { switch (USB_HostState) { case HOST_STATE_Addressed: LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); uint16_t ConfigDescriptorSize; uint8_t ConfigDescriptorData[512]; if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData, sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful) { puts_P(PSTR("Error Retrieving Configuration Descriptor.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (SImage_Host_ConfigurePipes(&DigitalCamera_SI_Interface, ConfigDescriptorSize, ConfigDescriptorData) != SI_ENUMERROR_NoError) { puts_P(PSTR("Attached Device Not a Valid Still Image Class Device.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful) { puts_P(PSTR("Error Setting Device Configuration.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Still Image Device Enumerated.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_READY); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: puts_P(PSTR("Opening Session...\r\n")); if (SImage_Host_OpenSession(&DigitalCamera_SI_Interface) != PIPE_RWSTREAM_NoError) { puts_P(PSTR("Could not open PIMA session.\r\n")); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Turning off Device...\r\n")); SImage_Host_SendCommand(&DigitalCamera_SI_Interface, 0x1013, 0, NULL); if (SImage_Host_ReceiveResponse(&DigitalCamera_SI_Interface)) { puts_P(PSTR("Could not turn off device.\r\n")); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Device Off.\r\n")); puts_P(PSTR("Closing Session...\r\n")); if (SImage_Host_CloseSession(&DigitalCamera_SI_Interface) != PIPE_RWSTREAM_NoError) { puts_P(PSTR("Could not close PIMA session.\r\n")); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } LEDs_SetAllLEDs(LEDMASK_USB_READY); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } SImage_Host_USBTask(&DigitalCamera_SI_Interface); USB_USBTask(); } }
/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they * contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command. */ void MassStorage_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Select the Data Out Endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); /* Check to see if a command from the host has been issued */ if (Endpoint_IsReadWriteAllowed()) { /* Indicate busy */ LEDs_SetAllLEDs(LEDMASK_USB_BUSY); /* Process sent command block from the host */ if (ReadInCommandBlock()) { /* Check direction of command, select Data IN endpoint if data is from the device */ if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN) Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); /* Decode the received SCSI command, set returned status code */ CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail; /* Load in the CBW tag into the CSW to link them together */ CommandStatus.Tag = CommandBlock.Tag; /* Load in the data residue counter into the CSW */ CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength; /* Stall the selected data pipe if command failed (if data is still to be transferred) */ if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue)) Endpoint_StallTransaction(); /* Return command status block to the host */ ReturnCommandStatus(); /* Indicate ready */ LEDs_SetAllLEDs(LEDMASK_USB_READY); } else { /* Indicate error reading in the command block from the host */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); } } /* Check if a Mass Storage Reset occurred */ if (IsMassStoreReset) { /* Reset the data endpoint banks */ Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM); Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM); Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); /* Clear the abort transfer flag */ IsMassStoreReset = false; } }
/** Main program entry point. This routine configures the hardware required by the application, then * enters a loop to run the application tasks in sequence. */ int main(void) { SetupHardware(); puts_P(PSTR(ESC_FG_CYAN "Mouse Host Demo running.\r\n" ESC_FG_WHITE)); sei(); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); for (;;) { switch (USB_HostState) { case HOST_STATE_Addressed: LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); uint16_t ConfigDescriptorSize; uint8_t ConfigDescriptorData[512]; if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData, sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful) { puts_P(PSTR("Error Retrieving Configuration Descriptor.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (HID_Host_ConfigurePipes(&Mouse_HID_Interface, ConfigDescriptorSize, ConfigDescriptorData) != HID_ENUMERROR_NoError) { puts_P(PSTR("Attached Device Not a Valid Mouse.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful) { puts_P(PSTR("Error Setting Device Configuration.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } if (HID_Host_SetReportProtocol(&Mouse_HID_Interface) != 0) { puts_P(PSTR("Error Setting Report Protocol Mode or Not a Valid Mouse.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Mouse Enumerated.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_READY); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: if (HID_Host_IsReportReceived(&Mouse_HID_Interface)) { uint8_t MouseReport[Mouse_HID_Interface.State.LargestReportSize]; HID_Host_ReceiveReport(&Mouse_HID_Interface, &MouseReport); uint8_t LEDMask = LEDS_NO_LEDS; for (uint8_t ReportNumber = 0; ReportNumber < HIDReportInfo.TotalReportItems; ReportNumber++) { HID_ReportItem_t* ReportItem = &HIDReportInfo.ReportItems[ReportNumber]; /* Update the report item value if it is contained within the current report */ if (!(USB_GetHIDReportItemInfo(MouseReport, ReportItem))) continue; /* Determine what report item is being tested, process updated value as needed */ if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_BUTTON) && (ReportItem->ItemType == HID_REPORT_ITEM_In)) { if (ReportItem->Value) LEDMask = LEDS_ALL_LEDS; } else if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_GENERIC_DCTRL) && (ReportItem->Attributes.Usage.Usage == USAGE_SCROLL_WHEEL) && (ReportItem->ItemType == HID_REPORT_ITEM_In)) { int16_t WheelDelta = HID_ALIGN_DATA(ReportItem, int16_t); if (WheelDelta) LEDMask = (LEDS_LED1 | LEDS_LED2 | ((WheelDelta > 0) ? LEDS_LED3 : LEDS_LED4)); } else if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_GENERIC_DCTRL) && ((ReportItem->Attributes.Usage.Usage == USAGE_X) || (ReportItem->Attributes.Usage.Usage == USAGE_Y)) && (ReportItem->ItemType == HID_REPORT_ITEM_In)) { int16_t DeltaMovement = HID_ALIGN_DATA(ReportItem, int16_t); if (DeltaMovement) { if (ReportItem->Attributes.Usage.Usage == USAGE_X) LEDMask |= ((DeltaMovement > 0) ? LEDS_LED1 : LEDS_LED2); else LEDMask |= ((DeltaMovement > 0) ? LEDS_LED3 : LEDS_LED4); } } } LEDs_SetAllLEDs(LEDMask); } break; } HID_Host_USBTask(&Mouse_HID_Interface); USB_USBTask(); } }
/** Task to handle the generation of MIDI note change events in response to presses of the board joystick, and send them * to the host. */ void MIDI_Task(void) { static uint8_t PrevJoystickStatus; /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR); if (Endpoint_IsINReady()) { uint8_t MIDICommand = 0; uint8_t MIDIPitch; uint8_t JoystickStatus = Joystick_GetStatus(); uint8_t JoystickChanges = (JoystickStatus ^ PrevJoystickStatus); /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */ uint8_t Channel = ((Buttons_GetStatus() & BUTTONS_BUTTON1) ? MIDI_CHANNEL(10) : MIDI_CHANNEL(1)); if (JoystickChanges & JOY_LEFT) { MIDICommand = ((JoystickStatus & JOY_LEFT)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3C; } if (JoystickChanges & JOY_UP) { MIDICommand = ((JoystickStatus & JOY_UP)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3D; } if (JoystickChanges & JOY_RIGHT) { MIDICommand = ((JoystickStatus & JOY_RIGHT)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3E; } if (JoystickChanges & JOY_DOWN) { MIDICommand = ((JoystickStatus & JOY_DOWN)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3F; } if (JoystickChanges & JOY_PRESS) { MIDICommand = ((JoystickStatus & JOY_PRESS)? MIDI_COMMAND_NOTE_ON : MIDI_COMMAND_NOTE_OFF); MIDIPitch = 0x3B; } /* Check if a MIDI command is to be sent */ if (MIDICommand) { MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t) { .Event = MIDI_EVENT(0, MIDICommand), .Data1 = MIDICommand | Channel, .Data2 = MIDIPitch, .Data3 = MIDI_STANDARD_VELOCITY, }; /* Write the MIDI event packet to the endpoint */ Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); /* Send the data in the endpoint to the host */ Endpoint_ClearIN(); } /* Save previous joystick value for next joystick change detection */ PrevJoystickStatus = JoystickStatus; } /* Select the MIDI OUT stream */ Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR); /* Check if a MIDI command has been received */ if (Endpoint_IsOUTReceived()) { MIDI_EventPacket_t MIDIEvent; /* Read the MIDI event packet from the endpoint */ Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL); /* Check to see if the sent command is a note on message with a non-zero velocity */ if ((MIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_ON)) && (MIDIEvent.Data3 > 0)) { /* Change LEDs depending on the pitch of the sent note */ LEDs_SetAllLEDs(MIDIEvent.Data2 > 64 ? LEDS_LED1 : LEDS_LED2); } else { /* Turn off all LEDs in response to non Note On messages */ LEDs_SetAllLEDs(LEDS_NO_LEDS); } /* If the endpoint is now empty, clear the bank */ if (!(Endpoint_BytesInEndpoint())) { /* Clear the endpoint ready for new packet */ Endpoint_ClearOUT(); } } }
/** Event handler for the USB_DeviceEnumerationFailed event. This indicates that a problem occurred while * enumerating an attached USB device. */ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, const uint8_t SubErrorCode) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); }
/** Main program entry point. This routine contains the overall program flow, including initial * setup of all components and the main program loop. */ int main(void) { MIDI_EventPacket_t midiEvent; struct { uint8_t command; uint8_t channel; uint8_t data2; uint8_t data3; } midiMsg; int ind; int led1_ticks = 0; int led2_ticks = 0; SetupHardware(); RingBuffer_InitBuffer(&USBtoUSART_Buffer); RingBuffer_InitBuffer(&USARTtoUSB_Buffer); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); for (;;) { RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer); /* See if we have a message yet */ if (BufferCount >= 4) { /* Read in the message from the serial buffer */ for (ind=0; ind<4; ind++) { ((uint8_t *)&midiMsg)[ind] = RingBuffer_Remove(&USARTtoUSB_Buffer); } /* Build a midi event to send via USB */ midiEvent.CableNumber = 0; midiEvent.Command = midiMsg.command >> 4; midiEvent.Data1 = (midiMsg.command & 0xF0) | ((midiMsg.channel-1) & 0x0F); midiEvent.Data2 = midiMsg.data2; midiEvent.Data3 = midiMsg.data3; MIDI_Device_SendEventPacket(&Keyboard_MIDI_Interface, &midiEvent); MIDI_Device_Flush(&Keyboard_MIDI_Interface); /* Turn on the TX led and starts its timer */ LEDs_TurnOnLEDs(LEDS_LED1); led1_ticks = LED_ON_TICKS; } /* Turn off the Tx LED when the tick count reaches zero */ if (led1_ticks) { led1_ticks--; if (led1_ticks == 0) { LEDs_TurnOffLEDs(LEDS_LED1); } } if (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &midiEvent)) { RingBuff_Count_t count = RingBuffer_GetCount(&USBtoUSART_Buffer); /* Room to send a message? */ if ((BUFFER_SIZE - count) >= sizeof(midiMsg)) { midiMsg.command = midiEvent.Command << 4; midiMsg.channel = (midiEvent.Data1 & 0x0F) + 1; midiMsg.data2 = midiEvent.Data2; midiMsg.data3 = midiEvent.Data3; for (ind=0; ind<sizeof(midiMsg); ind++) { RingBuffer_Insert(&USBtoUSART_Buffer, ((uint8_t *)&midiMsg)[ind]); } /* Turn on the RX led and start its timer */ LEDs_TurnOnLEDs(LEDS_LED2); led2_ticks = LED_ON_TICKS; } else { /* Turn on the RX led and leave it on to indicate the * buffer is full and the sketch is not reading it * fast enough. */ LEDs_TurnOnLEDs(LEDS_LED2); } /* if there's no room in the serial buffer the message gets dropped */ } /* Turn off the RX LED when the tick count reaches zero */ if (led2_ticks) { led2_ticks--; if (led2_ticks == 0) { LEDs_TurnOffLEDs(LEDS_LED2); } } /* any data to send to main processor? */ if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) { Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer)); } MIDI_Device_USBTask(&Keyboard_MIDI_Interface); USB_USBTask(); } }
/** Event handler for the USB_DeviceEnumerationComplete event. This indicates that a device has been successfully * enumerated by the host and is now ready to be used by the application. */ void EVENT_USB_Host_DeviceEnumerationComplete(void) { puts_P(PSTR("Getting Config Data.\r\n")); uint8_t ErrorCode; /* 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"), ErrorCode); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); return; } /* 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); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); return; } /* Some printers use alternate settings to determine the communication protocol used - if so, send a SetInterface * request to switch to the interface alternate setting with the Bidirectional protocol */ if (PrinterAltSetting) { if ((ErrorCode = USB_Host_SetInterfaceAltSetting(PrinterInterfaceNumber, PrinterAltSetting)) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Set Interface).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_Host_SetDeviceConfiguration(0); return; } } puts_P(PSTR("Retrieving Device ID...\r\n")); char DeviceIDString[300]; if ((ErrorCode = Printer_GetDeviceID(DeviceIDString, sizeof(DeviceIDString))) != HOST_SENDCONTROL_Successful) { printf_P(PSTR(ESC_FG_RED "Control Error (Get Device ID).\r\n" " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_Host_SetDeviceConfiguration(0); return; } printf_P(PSTR("Printer Device ID: %s\r\n"), DeviceIDString); puts_P(PSTR("Printer Enumerated.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_READY); }
/** 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 = 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; } }
/** Task to set the configuration of the attached device after it has been enumerated, and to print device information * through the serial port. */ void StillImage_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("Still Image Device Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; break; case HOST_STATE_Configured: /* Indicate device busy via the status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_BUSY); puts_P(PSTR("Retrieving Device Info...\r\n")); PIMA_SendBlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(0), .Type = CType_CommandBlock, .Code = PIMA_OPERATION_GETDEVICEINFO, .TransactionID = 0x00000000, .Params = {}, }; /* Send the GETDEVICEINFO block */ SImage_SendBlockHeader(); /* Receive the response data block */ if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError) { ShowCommandError(ErrorCode, false); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Calculate the size of the returned device info data structure */ uint16_t DeviceInfoSize = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0)); /* Create a buffer large enough to hold the entire device info */ uint8_t DeviceInfo[DeviceInfoSize]; /* Read in the data block data (containing device info) */ SImage_ReadData(DeviceInfo, DeviceInfoSize); /* Once all the data has been read, the pipe must be cleared before the response can be sent */ Pipe_ClearIN(); /* Create a pointer for walking through the info dataset */ uint8_t* DeviceInfoPos = DeviceInfo; /* Skip over the data before the unicode device information strings */ DeviceInfoPos += 8; // Skip to VendorExtensionDesc String DeviceInfoPos += (1 + UNICODE_STRING_LENGTH(*DeviceInfoPos)); // Skip over VendorExtensionDesc String DeviceInfoPos += 2; // Skip over FunctionalMode DeviceInfoPos += (4 + (*(uint32_t*)DeviceInfoPos << 1)); // Skip over Supported Operations Array DeviceInfoPos += (4 + (*(uint32_t*)DeviceInfoPos << 1)); // Skip over Supported Events Array DeviceInfoPos += (4 + (*(uint32_t*)DeviceInfoPos << 1)); // Skip over Supported Device Properties Array DeviceInfoPos += (4 + (*(uint32_t*)DeviceInfoPos << 1)); // Skip over Capture Formats Array DeviceInfoPos += (4 + (*(uint32_t*)DeviceInfoPos << 1)); // Skip over Image Formats Array /* Extract and convert the Manufacturer Unicode string to ASCII and print it through the USART */ char Manufacturer[*DeviceInfoPos]; UnicodeToASCII(DeviceInfoPos, Manufacturer); printf_P(PSTR(" Manufacturer: %s\r\n"), Manufacturer); DeviceInfoPos += 1 + UNICODE_STRING_LENGTH(*DeviceInfoPos); // Skip over Manufacturer String /* Extract and convert the Model Unicode string to ASCII and print it through the USART */ char Model[*DeviceInfoPos]; UnicodeToASCII(DeviceInfoPos, Model); printf_P(PSTR(" Model: %s\r\n"), Model); DeviceInfoPos += 1 + UNICODE_STRING_LENGTH(*DeviceInfoPos); // Skip over Model String /* Extract and convert the Device Version Unicode string to ASCII and print it through the USART */ char DeviceVersion[*DeviceInfoPos]; UnicodeToASCII(DeviceInfoPos, DeviceVersion); printf_P(PSTR(" Device Version: %s\r\n"), DeviceVersion); /* Receive the final response block from the device */ if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError) { ShowCommandError(ErrorCode, false); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Verify that the command completed successfully */ if ((PIMA_ReceivedBlock.Type != CType_ResponseBlock) || (PIMA_ReceivedBlock.Code != PIMA_RESPONSE_OK)) { ShowCommandError(PIMA_ReceivedBlock.Code, true); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Opening Session...\r\n")); PIMA_SendBlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(1), .Type = CType_CommandBlock, .Code = PIMA_OPERATION_OPENSESSION, .TransactionID = 0x00000000, .Params = {0x00000001}, }; /* Send the OPENSESSION block, open a session with an ID of 0x0001 */ SImage_SendBlockHeader(); /* Receive the response block from the device */ if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError) { ShowCommandError(ErrorCode, false); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Verify that the command completed successfully */ if ((PIMA_ReceivedBlock.Type != CType_ResponseBlock) || (PIMA_ReceivedBlock.Code != PIMA_RESPONSE_OK)) { ShowCommandError(PIMA_ReceivedBlock.Code, true); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Closing Session...\r\n")); PIMA_SendBlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(1), .Type = CType_CommandBlock, .Code = PIMA_OPERATION_CLOSESESSION, .TransactionID = 0x00000001, .Params = {0x00000001}, }; /* Send the CLOSESESSION block, close the session with an ID of 0x0001 */ SImage_SendBlockHeader(); /* Receive the response block from the device */ if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError) { ShowCommandError(ErrorCode, false); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Verify that the command completed successfully */ if ((PIMA_ReceivedBlock.Type != CType_ResponseBlock) || (PIMA_ReceivedBlock.Code != PIMA_RESPONSE_OK)) { ShowCommandError(PIMA_ReceivedBlock.Code, true); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } puts_P(PSTR("Done.\r\n")); /* Indicate device no longer busy */ LEDs_SetAllLEDs(LEDMASK_USB_READY); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } } /** Function to convert a given Unicode encoded string to ASCII. This function will only work correctly on Unicode * strings which contain ASCII printable characters only. * * \param[in] UnicodeString Pointer to a Unicode encoded input string * \param[out] Buffer Pointer to a buffer where the converted ASCII string should be stored */ void UnicodeToASCII(uint8_t* UnicodeString, char* Buffer) { /* Get the number of characters in the string, skip to the start of the string data */ uint8_t CharactersRemaining = *(UnicodeString++); /* Loop through the entire unicode string */ while (CharactersRemaining--) { /* Load in the next unicode character (only the lower byte, as only Unicode coded ASCII is supported) */ *(Buffer++) = *UnicodeString; /* Jump to the next unicode character */ UnicodeString += 2; } /* Null terminate the string */ *Buffer = 0; } /** Displays a PIMA command error via the device's serial port. * * \param[in] ErrorCode Error code of the function which failed to complete successfully * \param[in] ResponseCodeError Indicates if the error is due to a command failed indication from the device, or a communication failure */ void ShowCommandError(uint8_t ErrorCode, bool ResponseCodeError) { char* FailureType = ((ResponseCodeError) ? PSTR("Response Code != OK") : PSTR("Transaction Fail")); printf_P(PSTR(ESC_FG_RED "Command Error (%S).\r\n" " -- Error Code %d\r\n" ESC_FG_WHITE), FailureType, ErrorCode); /* Indicate error via status LEDs */ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); }
/** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { PulseMSRemaining.PingPongLEDPulse = PING_PONG_LED_PULSE_MS; LEDs_SetAllLEDs(LEDMASK_TX); }
/** Event handler for the USB_DeviceAttached event. This indicates that a device has been attached to the host, and * starts the library USB task to begin the enumeration and USB management process. */ void EVENT_USB_Host_DeviceAttached(void) { puts_P(PSTR(ESC_FG_GREEN "Device Attached.\r\n" ESC_FG_WHITE)); LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
/** Event handler for the library USB Disconnection event. */ void EVENT_USB_Device_Disconnect(void) { PulseMSRemaining.PingPongLEDPulse = 0; LEDs_SetAllLEDs(LEDS_NO_LEDS); }
/** Event handler for the USB_DeviceAttached event. This indicates that a device has been attached to the host, and * starts the library USB task to begin the enumeration and USB management process. */ void EVENT_USB_Host_DeviceAttached(void) { puts_P(PSTR("Device Attached.\r\n")); LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
void EVENT_USB_Host_DeviceAttached(void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and * starts the library USB task to begin the enumeration and USB management process. */ void EVENT_USB_Device_Connect(void) { /* Indicate USB enumerating */ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
void EVENT_USB_Host_DeviceUnattached(void) { LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); }
/** Checks for changes in the position of the board joystick, sending MIDI events to the host upon each change. */ void CheckJoystickMovement(void) { static uint8_t PrevJoystickStatus; uint8_t MIDICommand = 0; uint8_t MIDIPitch; /* Get current joystick mask, XOR with previous to detect joystick changes */ 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; } if (MIDICommand) { MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t) { .Event = MIDI_EVENT(0, MIDICommand), .Data1 = MIDICommand | Channel, .Data2 = MIDIPitch, .Data3 = MIDI_STANDARD_VELOCITY, }; MIDI_Device_SendEventPacket(&Keyboard_MIDI_Interface, &MIDIEvent); MIDI_Device_Flush(&Keyboard_MIDI_Interface); } PrevJoystickStatus = JoystickStatus; } /** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }
void DiskHost_USBTask(void) { if (USB_HostState == HOST_STATE_Addressed) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); uint16_t ConfigDescriptorSize; uint8_t ConfigDescriptorData[512]; if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData, sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } if (MS_Host_ConfigurePipes(&DiskHost_MS_Interface, ConfigDescriptorSize, ConfigDescriptorData) != MS_ENUMERROR_NoError) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } uint8_t MaxLUNIndex; if (MS_Host_GetMaxLUN(&DiskHost_MS_Interface, &MaxLUNIndex)) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } if (MS_Host_ResetMSInterface(&DiskHost_MS_Interface)) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } USB_HostState = HOST_STATE_Configured; /* Note: For the RequestSense call to work, the host state machine must be in the * Configured state, or the call will be aborted */ SCSI_Request_Sense_Response_t SenseData; if (MS_Host_RequestSense(&DiskHost_MS_Interface, 0, &SenseData) != 0) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; return; } pf_mount(&DiskFATState); LEDs_SetAllLEDs(LEDMASK_USB_READY); } MS_Host_USBTask(&DiskHost_MS_Interface); }
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via * the status LEDs and stops the USB management and CDC management tasks. */ void EVENT_USB_Device_Disconnect(void) { LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); }
/** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); uIPManagement_Init(); }