3      Copyright (C) Dean Camera, 2015. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2015  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this 
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in 
  15   all copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaims all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  31 #include "../../../../Common/Common.h" 
  32 #if (ARCH == ARCH_XMEGA) 
  34 #define  __INCLUDE_FROM_USB_DRIVER 
  35 #include "../USBMode.h" 
  37 #if defined(USB_CAN_BE_DEVICE) 
  39 #include "../Endpoint.h" 
  41 #if !defined(FIXED_CONTROL_ENDPOINT_SIZE) 
  42 uint8_t USB_Device_ControlEndpointSize 
= ENDPOINT_CONTROLEP_DEFAULT_SIZE
; 
  45 Endpoint_FIFOPair_t       USB_Endpoint_FIFOs
[ENDPOINT_TOTAL_ENDPOINTS
]; 
  47 volatile uint8_t          USB_Endpoint_SelectedEndpoint
; 
  48 volatile USB_EP_t
*        USB_Endpoint_SelectedHandle
; 
  49 volatile Endpoint_FIFO_t
* USB_Endpoint_SelectedFIFO
; 
  51 bool Endpoint_IsINReady(void) 
  53         Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
| ENDPOINT_DIR_IN
); 
  55         return ((USB_Endpoint_SelectedHandle
->STATUS 
& USB_EP_BUSNACK0_bm
) ? 
true : false); 
  58 bool Endpoint_IsOUTReceived(void) 
  60         Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
& ~ENDPOINT_DIR_IN
); 
  62         if (USB_Endpoint_SelectedHandle
->STATUS 
& USB_EP_TRNCOMPL0_bm
) 
  64                 USB_Endpoint_SelectedFIFO
->Length 
= USB_Endpoint_SelectedHandle
->CNT
; 
  71 bool Endpoint_IsSETUPReceived(void) 
  73         Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
& ~ENDPOINT_DIR_IN
); 
  75         if (USB_Endpoint_SelectedHandle
->STATUS 
& USB_EP_SETUP_bm
) 
  77                 USB_Endpoint_SelectedFIFO
->Length 
= USB_Endpoint_SelectedHandle
->CNT
; 
  84 void Endpoint_ClearSETUP(void) 
  86         Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
& ~ENDPOINT_DIR_IN
); 
  87         USB_Endpoint_SelectedHandle
->STATUS 
&= ~(USB_EP_SETUP_bm 
| USB_EP_TRNCOMPL0_bm 
| USB_EP_BUSNACK0_bm 
| USB_EP_OVF_bm
); 
  88         USB_Endpoint_SelectedHandle
->STATUS 
|= USB_EP_TOGGLE_bm
; 
  89         USB_Endpoint_SelectedFIFO
->Position  
= 0; 
  91         Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
| ENDPOINT_DIR_IN
); 
  92         USB_Endpoint_SelectedHandle
->STATUS 
|= USB_EP_TOGGLE_bm
; 
  93         USB_Endpoint_SelectedFIFO
->Position  
= 0; 
  96 void Endpoint_ClearIN(void) 
  98         USB_Endpoint_SelectedHandle
->CNT     
= USB_Endpoint_SelectedFIFO
->Position
; 
  99         USB_Endpoint_SelectedHandle
->STATUS 
&= ~(USB_EP_TRNCOMPL0_bm 
| USB_EP_BUSNACK0_bm 
| USB_EP_OVF_bm
); 
 100         USB_Endpoint_SelectedFIFO
->Position  
= 0; 
 103 void Endpoint_ClearOUT(void) 
 105         USB_Endpoint_SelectedHandle
->STATUS 
&= ~(USB_EP_TRNCOMPL0_bm 
| USB_EP_BUSNACK0_bm 
| USB_EP_OVF_bm
); 
 106         USB_Endpoint_SelectedFIFO
->Position  
= 0; 
 109 void Endpoint_StallTransaction(void) 
 111         USB_Endpoint_SelectedHandle
->CTRL 
|= USB_EP_STALL_bm
; 
 113         if ((USB_Endpoint_SelectedHandle
->CTRL 
& USB_EP_TYPE_gm
) == USB_EP_TYPE_CONTROL_gc
) 
 115                 Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint 
^ ENDPOINT_DIR_IN
); 
 116                 USB_Endpoint_SelectedHandle
->CTRL 
|= USB_EP_STALL_bm
; 
 120 uint8_t Endpoint_Read_8(void) 
 122         return USB_Endpoint_SelectedFIFO
->Data
[USB_Endpoint_SelectedFIFO
->Position
++]; 
 125 void Endpoint_Write_8(const uint8_t Data
) 
 127         USB_Endpoint_SelectedFIFO
->Data
[USB_Endpoint_SelectedFIFO
->Position
++] = Data
; 
 130 void Endpoint_SelectEndpoint(const uint8_t Address
) 
 132         uint8_t EndpointNumber 
= (Address 
& ENDPOINT_EPNUM_MASK
); 
 134         USB_Endpoint_SelectedEndpoint 
= Address
; 
 136         Endpoint_FIFOPair_t
* EndpointFIFOPair 
= &USB_Endpoint_FIFOs
[EndpointNumber
]; 
 137         USB_EndpointTable_t
* EndpointTable    
= (USB_EndpointTable_t
*)USB
.EPPTR
; 
 139         if (Address 
& ENDPOINT_DIR_IN
) 
 141                 USB_Endpoint_SelectedFIFO   
= &EndpointFIFOPair
->IN
; 
 142                 USB_Endpoint_SelectedHandle 
= &EndpointTable
->Endpoints
[EndpointNumber
].IN
; 
 146                 USB_Endpoint_SelectedFIFO   
= &EndpointFIFOPair
->OUT
; 
 147                 USB_Endpoint_SelectedHandle 
= &EndpointTable
->Endpoints
[EndpointNumber
].OUT
; 
 151 bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t
* const Table
, 
 152                                      const uint8_t Entries
) 
 154         for (uint8_t i 
= 0; i 
< Entries
; i
++) 
 156                 if (!(Table
[i
].Address
)) 
 159                 if (!(Endpoint_ConfigureEndpoint(Table
[i
].Address
, Table
[i
].Type
, Table
[i
].Size
, Table
[i
].Banks
))) 
 168 bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address
, 
 169                                     const uint8_t Config
, 
 172         Endpoint_SelectEndpoint(Address
); 
 174         USB_Endpoint_SelectedHandle
->CTRL    
= 0; 
 175         USB_Endpoint_SelectedHandle
->STATUS  
= (Address 
& ENDPOINT_DIR_IN
) ? USB_EP_BUSNACK0_bm 
: 0; 
 176         USB_Endpoint_SelectedHandle
->CTRL    
= Config
; 
 177         USB_Endpoint_SelectedHandle
->CNT     
= 0; 
 178         USB_Endpoint_SelectedHandle
->DATAPTR 
= (intptr_t)USB_Endpoint_SelectedFIFO
->Data
; 
 180         USB_Endpoint_SelectedFIFO
->Length    
= (Address 
& ENDPOINT_DIR_IN
) ? Size 
: 0; 
 181         USB_Endpoint_SelectedFIFO
->Position  
= 0; 
 186 void Endpoint_ClearEndpoints(void) 
 188         for (uint8_t EPNum 
= 0; EPNum 
< ENDPOINT_TOTAL_ENDPOINTS
; EPNum
++) 
 190                 ((USB_EndpointTable_t
*)USB
.EPPTR
)->Endpoints
[EPNum
].IN
.CTRL  
= 0; 
 191                 ((USB_EndpointTable_t
*)USB
.EPPTR
)->Endpoints
[EPNum
].OUT
.CTRL 
= 0; 
 195 void Endpoint_ClearStatusStage(void) 
 197         if (USB_ControlRequest
.bmRequestType 
& REQDIR_DEVICETOHOST
) 
 199                 while (!(Endpoint_IsOUTReceived())) 
 201                         if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 209                 while (!(Endpoint_IsINReady())) 
 211                         if (USB_DeviceState 
== DEVICE_STATE_Unattached
) 
 219 #if !defined(CONTROL_ONLY_DEVICE) 
 220 uint8_t Endpoint_WaitUntilReady(void) 
 222         #if (USB_STREAM_TIMEOUT_MS < 0xFF) 
 223         uint8_t  TimeoutMSRem 
= USB_STREAM_TIMEOUT_MS
; 
 225         uint16_t TimeoutMSRem 
= USB_STREAM_TIMEOUT_MS
; 
 228         uint16_t PreviousFrameNumber 
= USB_Device_GetFrameNumber(); 
 232                 if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN
) 
 234                         if (Endpoint_IsINReady()) 
 235                           return ENDPOINT_READYWAIT_NoError
; 
 239                         if (Endpoint_IsOUTReceived()) 
 240                           return ENDPOINT_READYWAIT_NoError
; 
 243                 uint8_t USB_DeviceState_LCL 
= USB_DeviceState
; 
 245                 if (USB_DeviceState_LCL 
== DEVICE_STATE_Unattached
) 
 246                   return ENDPOINT_READYWAIT_DeviceDisconnected
; 
 247                 else if (USB_DeviceState_LCL 
== DEVICE_STATE_Suspended
) 
 248                   return ENDPOINT_READYWAIT_BusSuspended
; 
 249                 else if (Endpoint_IsStalled()) 
 250                   return ENDPOINT_READYWAIT_EndpointStalled
; 
 252                 uint16_t CurrentFrameNumber 
= USB_Device_GetFrameNumber(); 
 254                 if (CurrentFrameNumber 
!= PreviousFrameNumber
) 
 256                         PreviousFrameNumber 
= CurrentFrameNumber
; 
 258                         if (!(TimeoutMSRem
--)) 
 259                           return ENDPOINT_READYWAIT_Timeout
;