/*---------------------------------------------------------------------------- * U S B - K e r n e l *---------------------------------------------------------------------------- * Name: usbcore.c * Purpose: USB Core Module * Version: V1.20 *---------------------------------------------------------------------------- * This software is supplied "AS IS" without any warranties, express, * implied or statutory, including but not limited to the implied * warranties of fitness for purpose, satisfactory quality and * noninfringement. Keil extends you a royalty-free right to reproduce * and distribute executable files created using this software for use * on NXP Semiconductors LPC microcontroller devices only. Nothing else * gives you the right to use this software. * * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. *---------------------------------------------------------------------------- * History: * V1.20 Added vendor specific requests * Changed string descriptor handling * Reworked Endpoint0 * V1.00 Initial Version *----------------------------------------------------------------------------*/ #include "type.h" #include "usb.h" #include "usbcfg.h" #include "usbhw.h" #include "usbcore.h" #include "usbdesc.h" #include "usbuser.h" #if (USB_CLASS) #if (USB_AUDIO) #include "audio.h" #include "adcuser.h" #endif #if (USB_HID) #include "hid.h" #include "hiduser.h" #endif #if (USB_MSC) #include "msc.h" #include "mscuser.h" extern MSC_CSW CSW; #endif #if (USB_CDC) #include "cdc.h" #include "cdcuser.h" #endif #endif #if (USB_VENDOR) #include "vendor.h" #endif uint16_t USB_DeviceStatus; uint8_t USB_DeviceAddress; uint8_t USB_Configuration; uint32_t USB_EndPointMask; uint32_t USB_EndPointHalt; uint32_t USB_EndPointStall; /* EP must stay stalled */ uint8_t USB_NumInterfaces; uint8_t USB_AltSetting[USB_IF_NUM]; uint8_t EP0Buf[USB_MAX_PACKET0]; USB_EP_DATA EP0Data; USB_SETUP_PACKET SetupPacket; /* * Reset USB Core * Parameters: None * Return Value: None */ void USB_ResetCore (void) { USB_DeviceStatus = USB_POWER; USB_DeviceAddress = 0; USB_Configuration = 0; USB_EndPointMask = 0x00010001; USB_EndPointHalt = 0x00000000; USB_EndPointStall = 0x00000000; } /* * USB Request - Setup Stage * Parameters: None (global SetupPacket) * Return Value: None */ void USB_SetupStage (void) { USB_ReadEP (0x00, (uint8_t *) & SetupPacket); } /* * USB Request - Data In Stage * Parameters: None (global EP0Data) * Return Value: None */ void USB_DataInStage (void) { uint32_t cnt; if (EP0Data.Count > USB_MAX_PACKET0) { cnt = USB_MAX_PACKET0; } else { cnt = EP0Data.Count; } cnt = USB_WriteEP (0x80, EP0Data.pData, cnt); EP0Data.pData += cnt; EP0Data.Count -= cnt; } /* * USB Request - Data Out Stage * Parameters: None (global EP0Data) * Return Value: None */ void USB_DataOutStage (void) { uint32_t cnt; cnt = USB_ReadEP (0x00, EP0Data.pData); EP0Data.pData += cnt; EP0Data.Count -= cnt; } /* * USB Request - Status In Stage * Parameters: None * Return Value: None */ void USB_StatusInStage (void) { USB_WriteEP (0x80, NULL, 0); } /* * USB Request - Status Out Stage * Parameters: None * Return Value: None */ void USB_StatusOutStage (void) { USB_ReadEP (0x00, EP0Buf); } /* * Get Status USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqGetStatus (void) { uint32_t n, m; switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: EP0Data.pData = (uint8_t *) & USB_DeviceStatus; break; case REQUEST_TO_INTERFACE: if ((USB_Configuration != 0) && (SetupPacket.wIndex.WB.L < USB_NumInterfaces)) { *((uint16_t __attribute__ ((packed)) *) EP0Buf) = 0; EP0Data.pData = EP0Buf; } else { return (FALSE); } break; case REQUEST_TO_ENDPOINT: n = SetupPacket.wIndex.WB.L & 0x8F; m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); if (((USB_Configuration != 0) || ((n & 0x0F) == 0)) && (USB_EndPointMask & m)) { *((uint16_t __attribute__ ((packed)) *) EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0; EP0Data.pData = EP0Buf; } else { return (FALSE); } break; default: return (FALSE); } return (TRUE); } /* * Set/Clear Feature USB Request * Parameters: sc: 0 - Clear, 1 - Set * (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqSetClrFeature (uint32_t sc) { uint32_t n, m; switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: if (SetupPacket.wValue.W == USB_FEATURE_REMOTE_WAKEUP) { if (sc) { USB_WakeUpCfg (TRUE); USB_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP; } else { USB_WakeUpCfg (FALSE); USB_DeviceStatus &= ~USB_GETSTATUS_REMOTE_WAKEUP; } } else { return (FALSE); } break; case REQUEST_TO_INTERFACE: return (FALSE); case REQUEST_TO_ENDPOINT: n = SetupPacket.wIndex.WB.L & 0x8F; m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); if ((USB_Configuration != 0) && ((n & 0x0F) != 0) && (USB_EndPointMask & m)) { if (SetupPacket.wValue.W == USB_FEATURE_ENDPOINT_STALL) { if (sc) { USB_SetStallEP (n); USB_EndPointHalt |= m; } else { if ((USB_EndPointStall & m) != 0) { return (TRUE); } USB_ClrStallEP (n); #if (USB_MSC) if ((n == MSC_EP_IN) && ((USB_EndPointHalt & m) != 0)) { /* Compliance Test: rewrite CSW after unstall */ if (CSW.dSignature == MSC_CSW_Signature) { USB_WriteEP (MSC_EP_IN, (uint8_t *) & CSW, sizeof (CSW)); } } #endif USB_EndPointHalt &= ~m; } } else { return (FALSE); } } else { return (FALSE); } break; default: return (FALSE); } return (TRUE); } /* * Set Address USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqSetAddress (void) { switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: USB_DeviceAddress = 0x80 | SetupPacket.wValue.WB.L; break; default: return (FALSE); } return (TRUE); } /* * Get Descriptor USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqGetDescriptor (void) { uint8_t *pD; uint32_t len, n; switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: switch (SetupPacket.wValue.WB.H) { case USB_DEVICE_DESCRIPTOR_TYPE: EP0Data.pData = (uint8_t *) USB_DeviceDescriptor; len = USB_DEVICE_DESC_SIZE; break; case USB_CONFIGURATION_DESCRIPTOR_TYPE: pD = (uint8_t *) USB_ConfigDescriptor; for (n = 0; n != SetupPacket.wValue.WB.L; n++) { if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bLength != 0) { pD += ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; } } if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bLength == 0) { return (FALSE); } EP0Data.pData = pD; len = ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; break; case USB_STRING_DESCRIPTOR_TYPE: pD = (uint8_t *) USB_StringDescriptor; for (n = 0; n != SetupPacket.wValue.WB.L; n++) { if (((USB_STRING_DESCRIPTOR *) pD)->bLength != 0) { pD += ((USB_STRING_DESCRIPTOR *) pD)->bLength; } } if (((USB_STRING_DESCRIPTOR *) pD)->bLength == 0) { return (FALSE); } EP0Data.pData = pD; len = ((USB_STRING_DESCRIPTOR *) EP0Data.pData)->bLength; break; default: return (FALSE); } break; case REQUEST_TO_INTERFACE: switch (SetupPacket.wValue.WB.H) { #if USB_HID case HID_HID_DESCRIPTOR_TYPE: if (SetupPacket.wIndex.WB.L != USB_HID_IF_NUM) { return (FALSE); /* Only Single HID Interface is supported */ } EP0Data.pData = (uint8_t *) USB_ConfigDescriptor + HID_DESC_OFFSET; len = HID_DESC_SIZE; break; case HID_REPORT_DESCRIPTOR_TYPE: if (SetupPacket.wIndex.WB.L != USB_HID_IF_NUM) { return (FALSE); /* Only Single HID Interface is supported */ } EP0Data.pData = (uint8_t *) HID_ReportDescriptor; len = HID_ReportDescSize; break; case HID_PHYSICAL_DESCRIPTOR_TYPE: return (FALSE); /* HID Physical Descriptor is not supported */ #endif default: return (FALSE); } break; default: return (FALSE); } if (EP0Data.Count > len) { EP0Data.Count = len; } return (TRUE); } /* * Get Configuration USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqGetConfiguration (void) { switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: EP0Data.pData = &USB_Configuration; break; default: return (FALSE); } return (TRUE); } /* * Add a number of bytes to a pointer's address * Harder than you might think. Some compilers say: * Expected an lvalue -- Assignment expects its first operand to be * an lvalue. Please note that a cast removes the lvaluedness of an * expression. * * vpptr = void pointer to pointer * n = number of bytes to add to pointer * Call looks like: AddPtr((void **)&myPointer, 8); */ __inline void UsbAddPtr (void **vpptr, uint32_t n) { /* Declare a pointer to a pointer to a byte. Only a byte pointer * can be incremented by a number of bytes. Other pointers will * increment by a multiple of what they point to. */ uint8_t **bpptr; /* Convert our void pointer to a pointer to a byte pointer to a pointer */ bpptr = (uint8_t **) vpptr; /* Add 'n' bytes to our pointer value */ (*bpptr) += n; } /* * Set Configuration USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqSetConfiguration (void) { USB_COMMON_DESCRIPTOR *pD; uint32_t alt = 0; uint32_t n, m; switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: if (SetupPacket.wValue.WB.L) { pD = (USB_COMMON_DESCRIPTOR *) USB_ConfigDescriptor; while (pD->bLength) { switch (pD->bDescriptorType) { case USB_CONFIGURATION_DESCRIPTOR_TYPE: if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bConfigurationValue == SetupPacket.wValue.WB.L) { USB_Configuration = SetupPacket.wValue.WB.L; USB_NumInterfaces = ((USB_CONFIGURATION_DESCRIPTOR *) pD)->bNumInterfaces; for (n = 0; n < USB_IF_NUM; n++) { USB_AltSetting[n] = 0; } for (n = 1; n < 16; n++) { if (USB_EndPointMask & (1 << n)) { USB_DisableEP (n); } if (USB_EndPointMask & ((1 << 16) << n)) { USB_DisableEP (n | 0x80); } } USB_EndPointMask = 0x00010001; USB_EndPointHalt = 0x00000000; USB_EndPointStall = 0x00000000; USB_Configure (TRUE); if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bmAttributes & USB_CONFIG_POWERED_MASK) { USB_DeviceStatus |= USB_GETSTATUS_SELF_POWERED; } else { USB_DeviceStatus &= ~USB_GETSTATUS_SELF_POWERED; } } else { UsbAddPtr ((void **) &pD, ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength); continue; } break; case USB_INTERFACE_DESCRIPTOR_TYPE: alt = ((USB_INTERFACE_DESCRIPTOR *) pD)->bAlternateSetting; break; case USB_ENDPOINT_DESCRIPTOR_TYPE: if (alt == 0) { n = ((USB_ENDPOINT_DESCRIPTOR *) pD)->bEndpointAddress & 0x8F; m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); USB_EndPointMask |= m; USB_ConfigEP ((USB_ENDPOINT_DESCRIPTOR *) pD); USB_EnableEP (n); USB_ResetEP (n); } break; } UsbAddPtr ((void **) &pD, pD->bLength); } } else { USB_Configuration = 0; for (n = 1; n < 16; n++) { if (USB_EndPointMask & (1 << n)) { USB_DisableEP (n); } if (USB_EndPointMask & ((1 << 16) << n)) { USB_DisableEP (n | 0x80); } } USB_EndPointMask = 0x00010001; USB_EndPointHalt = 0x00000000; USB_EndPointStall = 0x00000000; USB_Configure (FALSE); } if (USB_Configuration != SetupPacket.wValue.WB.L) { return (FALSE); } break; default: return (FALSE); } return (TRUE); } /* * Get Interface USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqGetInterface (void) { switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_INTERFACE: if ((USB_Configuration != 0) && (SetupPacket.wIndex.WB.L < USB_NumInterfaces)) { EP0Data.pData = USB_AltSetting + SetupPacket.wIndex.WB.L; } else { return (FALSE); } break; default: return (FALSE); } return (TRUE); } /* * Set Interface USB Request * Parameters: None (global SetupPacket) * Return Value: TRUE - Success, FALSE - Error */ __inline uint32_t USB_ReqSetInterface (void) { USB_COMMON_DESCRIPTOR *pD; uint32_t ifn = 0, alt = 0, old = 0, msk = 0; uint32_t n, m; uint32_t set; switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_INTERFACE: if (USB_Configuration == 0) return (FALSE); set = FALSE; pD = (USB_COMMON_DESCRIPTOR *) USB_ConfigDescriptor; while (pD->bLength) { switch (pD->bDescriptorType) { case USB_CONFIGURATION_DESCRIPTOR_TYPE: if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bConfigurationValue != USB_Configuration) { UsbAddPtr ((void **) &pD, ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength); continue; } break; case USB_INTERFACE_DESCRIPTOR_TYPE: ifn = ((USB_INTERFACE_DESCRIPTOR *) pD)->bInterfaceNumber; alt = ((USB_INTERFACE_DESCRIPTOR *) pD)->bAlternateSetting; msk = 0; if ((ifn == SetupPacket.wIndex.WB.L) && (alt == SetupPacket.wValue.WB.L)) { set = TRUE; old = USB_AltSetting[ifn]; USB_AltSetting[ifn] = (uint8_t) alt; } break; case USB_ENDPOINT_DESCRIPTOR_TYPE: if (ifn == SetupPacket.wIndex.WB.L) { n = ((USB_ENDPOINT_DESCRIPTOR *) pD)->bEndpointAddress & 0x8F; m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); if (alt == SetupPacket.wValue.WB.L) { USB_EndPointMask |= m; USB_EndPointHalt &= ~m; USB_ConfigEP ((USB_ENDPOINT_DESCRIPTOR *) pD); USB_EnableEP (n); USB_ResetEP (n); msk |= m; } else if ((alt == old) && ((msk & m) == 0)) { USB_EndPointMask &= ~m; USB_EndPointHalt &= ~m; USB_DisableEP (n); } } break; } UsbAddPtr ((void **) &pD, pD->bLength); } break; default: return (FALSE); } return (set); } /* * USB Endpoint 0 Event Callback * Parameters: event * Return Value: none */ void USB_EndPoint0 (uint32_t event) { switch (event) { case USB_EVT_SETUP: USB_SetupStage (); USB_DirCtrlEP (SetupPacket.bmRequestType.BM.Dir); EP0Data.Count = SetupPacket.wLength; /* Number of bytes to transfer */ switch (SetupPacket.bmRequestType.BM.Type) { case REQUEST_STANDARD: switch (SetupPacket.bRequest) { case USB_REQUEST_GET_STATUS: if (!USB_ReqGetStatus ()) { goto stall_i; } USB_DataInStage (); break; case USB_REQUEST_CLEAR_FEATURE: if (!USB_ReqSetClrFeature (0)) { goto stall_i; } USB_StatusInStage (); #if USB_FEATURE_EVENT USB_Feature_Event (); #endif break; case USB_REQUEST_SET_FEATURE: if (!USB_ReqSetClrFeature (1)) { goto stall_i; } USB_StatusInStage (); #if USB_FEATURE_EVENT USB_Feature_Event (); #endif break; case USB_REQUEST_SET_ADDRESS: if (!USB_ReqSetAddress ()) { goto stall_i; } USB_StatusInStage (); break; case USB_REQUEST_GET_DESCRIPTOR: if (!USB_ReqGetDescriptor ()) { goto stall_i; } USB_DataInStage (); break; case USB_REQUEST_SET_DESCRIPTOR: /*stall_o: */ USB_SetStallEP (0x00); /* not supported */ EP0Data.Count = 0; break; case USB_REQUEST_GET_CONFIGURATION: if (!USB_ReqGetConfiguration ()) { goto stall_i; } USB_DataInStage (); break; case USB_REQUEST_SET_CONFIGURATION: if (!USB_ReqSetConfiguration ()) { goto stall_i; } USB_StatusInStage (); #if USB_CONFIGURE_EVENT USB_Configure_Event (); #endif break; case USB_REQUEST_GET_INTERFACE: if (!USB_ReqGetInterface ()) { goto stall_i; } USB_DataInStage (); break; case USB_REQUEST_SET_INTERFACE: if (!USB_ReqSetInterface ()) { goto stall_i; } USB_StatusInStage (); #if USB_INTERFACE_EVENT USB_Interface_Event (); #endif break; default: goto stall_i; } break; /* end case REQUEST_STANDARD */ #if USB_CLASS case REQUEST_CLASS: switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: goto stall_i; /* not supported */ case REQUEST_TO_INTERFACE: #if USB_HID if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM) { /* IF number correct? */ switch (SetupPacket.bRequest) { case HID_REQUEST_GET_REPORT: if (HID_GetReport ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case HID_REQUEST_SET_REPORT: EP0Data.pData = EP0Buf; /* data to be received */ goto setup_class_ok; case HID_REQUEST_GET_IDLE: if (HID_GetIdle ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case HID_REQUEST_SET_IDLE: if (HID_SetIdle ()) { USB_StatusInStage (); /* send Acknowledge */ goto setup_class_ok; } break; case HID_REQUEST_GET_PROTOCOL: if (HID_GetProtocol ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case HID_REQUEST_SET_PROTOCOL: if (HID_SetProtocol ()) { USB_StatusInStage (); /* send Acknowledge */ goto setup_class_ok; } break; } } #endif /* USB_HID */ #if USB_MSC if (SetupPacket.wIndex.WB.L == USB_MSC_IF_NUM) { /* IF number correct? */ switch (SetupPacket.bRequest) { case MSC_REQUEST_RESET: if ((SetupPacket.wValue.W == 0) && /* RESET with invalid parameters -> STALL */ (SetupPacket.wLength == 0)) { if (MSC_Reset ()) { USB_StatusInStage (); goto setup_class_ok; } } break; case MSC_REQUEST_GET_MAX_LUN: if ((SetupPacket.wValue.W == 0) && /* GET_MAX_LUN with invalid parameters -> STALL */ (SetupPacket.wLength == 1)) { if (MSC_GetMaxLUN ()) { EP0Data.pData = EP0Buf; USB_DataInStage (); goto setup_class_ok; } } break; } } #endif /* USB_MSC */ #if USB_AUDIO if ((SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM) || /* IF number correct? */ (SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM) || (SetupPacket.wIndex.WB.L == USB_ADC_SIF2_NUM)) { switch (SetupPacket.bRequest) { case AUDIO_REQUEST_GET_CUR: case AUDIO_REQUEST_GET_MIN: case AUDIO_REQUEST_GET_MAX: case AUDIO_REQUEST_GET_RES: if (ADC_IF_GetRequest ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case AUDIO_REQUEST_SET_CUR: // case AUDIO_REQUEST_SET_MIN: // case AUDIO_REQUEST_SET_MAX: // case AUDIO_REQUEST_SET_RES: EP0Data.pData = EP0Buf; /* data to be received */ goto setup_class_ok; } } #endif /* USB_AUDIO */ #if USB_CDC if ((SetupPacket.wIndex.WB.L == USB_CDC_CIF_NUM) || /* IF number correct? */ (SetupPacket.wIndex.WB.L == USB_CDC_DIF_NUM)) { switch (SetupPacket.bRequest) { case CDC_SEND_ENCAPSULATED_COMMAND: EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ goto setup_class_ok; case CDC_GET_ENCAPSULATED_RESPONSE: if (CDC_GetEncapsulatedResponse ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case CDC_SET_COMM_FEATURE: EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ goto setup_class_ok; case CDC_GET_COMM_FEATURE: if (CDC_GetCommFeature (SetupPacket.wValue.W)) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case CDC_CLEAR_COMM_FEATURE: if (CDC_ClearCommFeature (SetupPacket.wValue.W)) { USB_StatusInStage (); /* send Acknowledge */ goto setup_class_ok; } break; case CDC_SET_LINE_CODING: EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ goto setup_class_ok; case CDC_GET_LINE_CODING: if (CDC_GetLineCoding ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case CDC_SET_CONTROL_LINE_STATE: if (CDC_SetControlLineState (SetupPacket.wValue.W)) { USB_StatusInStage (); /* send Acknowledge */ goto setup_class_ok; } break; case CDC_SEND_BREAK: if (CDC_SendBreak (SetupPacket.wValue.W)) { USB_StatusInStage (); /* send Acknowledge */ goto setup_class_ok; } break; } } #endif /* USB_CDC */ goto stall_i; /* not supported */ /* end case REQUEST_TO_INTERFACE */ case REQUEST_TO_ENDPOINT: #if USB_AUDIO switch (SetupPacket.bRequest) { case AUDIO_REQUEST_GET_CUR: case AUDIO_REQUEST_GET_MIN: case AUDIO_REQUEST_GET_MAX: case AUDIO_REQUEST_GET_RES: if (ADC_EP_GetRequest ()) { EP0Data.pData = EP0Buf; /* point to data to be sent */ USB_DataInStage (); /* send requested data */ goto setup_class_ok; } break; case AUDIO_REQUEST_SET_CUR: // case AUDIO_REQUEST_SET_MIN: // case AUDIO_REQUEST_SET_MAX: // case AUDIO_REQUEST_SET_RES: EP0Data.pData = EP0Buf; /* data to be received */ goto setup_class_ok; } #endif /* USB_AUDIO */ goto stall_i; /* end case REQUEST_TO_ENDPOINT */ default: goto stall_i; } setup_class_ok: /* request finished successfully */ break; /* end case REQUEST_CLASS */ #endif /* USB_CLASS */ #if USB_VENDOR case REQUEST_VENDOR: switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: if (!USB_ReqVendorDev (TRUE)) { goto stall_i; /* not supported */ } break; case REQUEST_TO_INTERFACE: if (!USB_ReqVendorIF (TRUE)) { goto stall_i; /* not supported */ } break; case REQUEST_TO_ENDPOINT: if (!USB_ReqVendorEP (TRUE)) { goto stall_i; /* not supported */ } break; default: goto stall_i; } if (SetupPacket.wLength) { if (SetupPacket.bmRequestType.BM.Dir == REQUEST_DEVICE_TO_HOST) { USB_DataInStage (); } } else { USB_StatusInStage (); } break; /* end case REQUEST_VENDOR */ #endif /* USB_VENDOR */ default: stall_i:USB_SetStallEP (0x80); EP0Data.Count = 0; break; } break; /* end case USB_EVT_SETUP */ case USB_EVT_OUT: if (SetupPacket.bmRequestType.BM.Dir == REQUEST_HOST_TO_DEVICE) { if (EP0Data.Count) { /* still data to receive ? */ USB_DataOutStage (); /* receive data */ if (EP0Data.Count == 0) { /* data complete ? */ switch (SetupPacket.bmRequestType.BM.Type) { case REQUEST_STANDARD: goto stall_i; /* not supported */ #if (USB_CLASS) case REQUEST_CLASS: switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: goto stall_i; /* not supported */ case REQUEST_TO_INTERFACE: #if USB_HID if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM) { /* IF number correct? */ switch (SetupPacket.bRequest) { case HID_REQUEST_SET_REPORT: if (HID_SetReport ()) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; } } #endif /* USB_HID */ #if USB_AUDIO if ((SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM) || /* IF number correct? */ (SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM) || (SetupPacket.wIndex.WB.L == USB_ADC_SIF2_NUM)) { switch (SetupPacket.bRequest) { case AUDIO_REQUEST_SET_CUR: // case AUDIO_REQUEST_SET_MIN: // case AUDIO_REQUEST_SET_MAX: // case AUDIO_REQUEST_SET_RES: if (ADC_IF_SetRequest ()) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; } } #endif /* USB_AUDIO */ #if USB_CDC if ((SetupPacket.wIndex.WB.L == USB_CDC_CIF_NUM) || /* IF number correct? */ (SetupPacket.wIndex.WB.L == USB_CDC_DIF_NUM)) { switch (SetupPacket.bRequest) { case CDC_SEND_ENCAPSULATED_COMMAND: if (CDC_SendEncapsulatedCommand ()) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; case CDC_SET_COMM_FEATURE: if (CDC_SetCommFeature (SetupPacket.wValue.W)) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; case CDC_SET_LINE_CODING: if (CDC_SetLineCoding ()) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; } } #endif /* USB_CDC */ goto stall_i; /* end case REQUEST_TO_INTERFACE */ case REQUEST_TO_ENDPOINT: #if USB_AUDIO switch (SetupPacket.bRequest) { case AUDIO_REQUEST_SET_CUR: // case AUDIO_REQUEST_SET_MIN: // case AUDIO_REQUEST_SET_MAX: // case AUDIO_REQUEST_SET_RES: if (ADC_EP_SetRequest ()) { USB_StatusInStage (); /* send Acknowledge */ goto out_class_ok; } break; } #endif /* USB_AUDIO */ goto stall_i; /* end case REQUEST_TO_ENDPOINT */ default: goto stall_i; } out_class_ok: /* request finished successfully */ break; /* end case REQUEST_CLASS */ #endif /* USB_CLASS */ #if USB_VENDOR case REQUEST_VENDOR: switch (SetupPacket.bmRequestType.BM.Recipient) { case REQUEST_TO_DEVICE: if (!USB_ReqVendorDev (FALSE)) { goto stall_i; /* not supported */ } break; case REQUEST_TO_INTERFACE: if (!USB_ReqVendorIF (FALSE)) { goto stall_i; /* not supported */ } break; case REQUEST_TO_ENDPOINT: if (!USB_ReqVendorEP (FALSE)) { goto stall_i; /* not supported */ } break; default: goto stall_i; } USB_StatusInStage (); break; /* end case REQUEST_VENDOR */ #endif /* USB_VENDOR */ default: goto stall_i; } } } } else { USB_StatusOutStage (); /* receive Acknowledge */ } break; /* end case USB_EVT_OUT */ case USB_EVT_IN: if (SetupPacket.bmRequestType.BM.Dir == REQUEST_DEVICE_TO_HOST) { USB_DataInStage (); /* send data */ } else { if (USB_DeviceAddress & 0x80) { USB_DeviceAddress &= 0x7F; USB_SetAddress (USB_DeviceAddress); } } break; /* end case USB_EVT_IN */ case USB_EVT_OUT_STALL: USB_ClrStallEP (0x00); break; case USB_EVT_IN_STALL: USB_ClrStallEP (0x80); break; } }