void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo, const int16_t Sample) { Endpoint_Write_Word_LE(Sample); if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize) Endpoint_ClearIN(); }
/** Handler for the XPROG CRC command to read a specific memory space's CRC value for comparison between the * attached device's memory and a data set on the host. */ static void XPROGProtocol_ReadCRC(void) { uint8_t ReturnStatus = XPRG_ERR_OK; struct { uint8_t CRCType; } ReadCRC_XPROG_Params; Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params), NO_STREAM_CALLBACK); Endpoint_ClearOUT(); Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint32_t MemoryCRC; if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI) { uint8_t CRCCommand; /* Determine which NVM command to send to the device depending on the memory to CRC */ switch (ReadCRC_XPROG_Params.CRCType) { case XPRG_CRC_APP: CRCCommand = XMEGA_NVM_CMD_APPCRC; break; case XPRG_CRC_BOOT: CRCCommand = XMEGA_NVM_CMD_BOOTCRC; break; default: CRCCommand = XMEGA_NVM_CMD_FLASHCRC; break; } /* Perform and retrieve the memory CRC, indicate timeout if occurred */ if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC))) ReturnStatus = XPRG_ERR_TIMEOUT; } else { /* TPI does not support memory CRC */ ReturnStatus = XPRG_ERR_FAILED; } Endpoint_Write_Byte(CMD_XPROG); Endpoint_Write_Byte(XPRG_CMD_CRC); Endpoint_Write_Byte(ReturnStatus); if (ReturnStatus == XPRG_ERR_OK) { Endpoint_Write_Byte(MemoryCRC >> 16); Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF); }
/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */ void USB_Audio_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Check to see if the streaming interface is selected, if not the host is not receiving audio */ if (!(StreamingAudioInterfaceSelected)) return; /* Select the audio stream endpoint */ Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM); /* Check if the current endpoint can be written to and that the next sample should be stored */ if (Endpoint_IsINReady() && (TIFR0 & (1 << OCF0A))) { /* Clear the sample reload timer */ TIFR0 |= (1 << OCF0A); /* Audio sample is ADC value scaled to fit the entire range */ int16_t AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult()); #if defined(MICROPHONE_BIASED_TO_HALF_RAIL) /* Microphone is biased to half rail voltage, subtract the bias from the sample value */ AudioSample -= (SAMPLE_MAX_RANGE / 2); #endif /* Write the sample to the buffer */ Endpoint_Write_Word_LE(AudioSample); /* Check to see if the bank is now full */ if (!(Endpoint_IsReadWriteAllowed())) { /* Send the full packet to the host */ Endpoint_ClearIN(); } } }
void EVENT_USB_Device_UnhandledControlRequest(void) { if (port_cur == 5 && USB_ControlRequest.bRequest == REQ_SetInterface) { /* can ignore this */ Endpoint_ClearSETUP(); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); return; } if (port_cur == 0 && USB_ControlRequest.bmRequestType == 0xA0 && USB_ControlRequest.bRequest == 0x00 && // GET HUB STATUS USB_ControlRequest.wValue == 0x00 && USB_ControlRequest.wIndex == 0x00 && USB_ControlRequest.wLength == 0x04) { Endpoint_ClearSETUP(); Endpoint_Write_Word_LE(0x0000); // wHubStatus Endpoint_Write_Word_LE(0x0000); // wHubChange Endpoint_ClearIN(); Endpoint_ClearStatusStage(); return; } if (port_cur == 0 && USB_ControlRequest.bmRequestType == 0xA3 && USB_ControlRequest.bRequest == 0x00 && // GET PORT STATUS USB_ControlRequest.wValue == 0x00 && USB_ControlRequest.wLength == 0x04) { uint8_t p = USB_ControlRequest.wIndex; if (p < 1 || p > 6) return; Endpoint_ClearSETUP(); Endpoint_Write_Word_LE(port_status[p - 1]); // wHubStatus Endpoint_Write_Word_LE(port_change[p - 1]); // wHubChange Endpoint_ClearIN(); Endpoint_ClearStatusStage(); return; } if (port_cur == 0 && USB_ControlRequest.bmRequestType == 0x23 && USB_ControlRequest.bRequest == 0x03 && // SET_FEATURE USB_ControlRequest.wLength == 0x00) { uint8_t p = USB_ControlRequest.wIndex; if (p < 1 || p > 6) return; Endpoint_ClearSETUP(); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); switch(USB_ControlRequest.wValue) { case 0x0008: // PORT_POWER if (p == 6 && state == init) { /* after the 6th port is powered, wait a bit and continue */ state = hub_ready; expire = 15; } break; case 0x0004: // PORT_RESET hub_int_response = (1 << p); port_change[p - 1] |= C_PORT_RESET; break; } return; } if (port_cur == 0 && USB_ControlRequest.bmRequestType == 0x23 && USB_ControlRequest.bRequest == 0x01 && // CLEAR_FEATURE USB_ControlRequest.wLength == 0x00) { uint8_t p = USB_ControlRequest.wIndex; if (p < 1 || p > 6) return; Endpoint_ClearSETUP(); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); switch(USB_ControlRequest.wValue) { case 0x0010: // C_PORT_CONNECTION last_port_conn_clear = p; port_change[p - 1] &= ~C_PORT_CONN; break; case 0x0014: // C_PORT_RESET last_port_reset_clear = p; port_change[p - 1] &= ~C_PORT_RESET; break; } return; } panic(RED, GREEN); }
/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to * the device from the USB host before passing along unhandled control requests to the library for processing * internally. */ void EVENT_USB_Device_ControlRequest(void) { uint8_t TMCRequestStatus = TMC_STATUS_SUCCESS; /* Process TMC specific control requests */ switch (USB_ControlRequest.bRequest) { case Req_InitiateAbortBulkOut: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT)) { /* Check that no split transaction is already in progress and the data transfer tag is valid */ if (RequestInProgress != 0) { TMCRequestStatus = TMC_STATUS_SPLIT_IN_PROGRESS; } else if (USB_ControlRequest.wValue != CurrentTransferTag) { TMCRequestStatus = TMC_STATUS_TRANSFER_NOT_IN_PROGRESS; } else { /* Indicate that all in-progress/pending data OUT requests should be aborted */ IsTMCBulkOUTReset = true; /* Save the split request for later checking when a new request is received */ RequestInProgress = Req_InitiateAbortBulkOut; } Endpoint_ClearSETUP(); /* Write the request response byte */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_CheckAbortBulkOutStatus: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT)) { /* Check that an ABORT BULK OUT transaction has been requested and that the request has completed */ if (RequestInProgress != Req_InitiateAbortBulkOut) TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS; else if (IsTMCBulkOUTReset) TMCRequestStatus = TMC_STATUS_PENDING; else RequestInProgress = 0; Endpoint_ClearSETUP(); /* Write the request response bytes */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_Write_Word_LE(0); Endpoint_Write_DWord_LE(LastTransferLength); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_InitiateAbortBulkIn: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT)) { /* Check that no split transaction is already in progress and the data transfer tag is valid */ if (RequestInProgress != 0) { TMCRequestStatus = TMC_STATUS_SPLIT_IN_PROGRESS; } else if (USB_ControlRequest.wValue != CurrentTransferTag) { TMCRequestStatus = TMC_STATUS_TRANSFER_NOT_IN_PROGRESS; } else { /* Indicate that all in-progress/pending data IN requests should be aborted */ IsTMCBulkINReset = true; /* Save the split request for later checking when a new request is received */ RequestInProgress = Req_InitiateAbortBulkIn; } Endpoint_ClearSETUP(); /* Write the request response bytes */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_Write_Byte(CurrentTransferTag); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_CheckAbortBulkInStatus: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT)) { /* Check that an ABORT BULK IN transaction has been requested and that the request has completed */ if (RequestInProgress != Req_InitiateAbortBulkIn) TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS; else if (IsTMCBulkINReset) TMCRequestStatus = TMC_STATUS_PENDING; else RequestInProgress = 0; Endpoint_ClearSETUP(); /* Write the request response bytes */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_Write_Word_LE(0); Endpoint_Write_DWord_LE(LastTransferLength); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_InitiateClear: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { /* Check that no split transaction is already in progress */ if (RequestInProgress != 0) { Endpoint_Write_Byte(TMC_STATUS_SPLIT_IN_PROGRESS); } else { /* Indicate that all in-progress/pending data IN and OUT requests should be aborted */ IsTMCBulkINReset = true; IsTMCBulkOUTReset = true; /* Save the split request for later checking when a new request is received */ RequestInProgress = Req_InitiateClear; } Endpoint_ClearSETUP(); /* Write the request response byte */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_CheckClearStatus: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { /* Check that a CLEAR transaction has been requested and that the request has completed */ if (RequestInProgress != Req_InitiateClear) TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS; else if (IsTMCBulkINReset || IsTMCBulkOUTReset) TMCRequestStatus = TMC_STATUS_PENDING; else RequestInProgress = 0; Endpoint_ClearSETUP(); /* Write the request response bytes */ Endpoint_Write_Byte(TMCRequestStatus); Endpoint_Write_Byte(0); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } break; case Req_GetCapabilities: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); /* Write the device capabilities to the control endpoint */ Endpoint_Write_Control_Stream_LE(&Capabilities, sizeof(TMC_Capabilities_t)); Endpoint_ClearOUT(); } break; } }