--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#include "USBMode.h"\r
+#if defined(USB_CAN_BE_HOST)\r
+\r
+#define INCLUDE_FROM_HOSTCHAPTER9_C\r
+#include "HostChapter9.h"\r
+\r
+USB_Host_Request_Header_t USB_HostRequest;\r
+\r
+uint8_t USB_Host_SendControlRequest(void* BufferPtr)\r
+{\r
+ uint8_t* HeaderStream = (uint8_t*)&USB_HostRequest;\r
+ uint8_t* DataStream = (uint8_t*)BufferPtr;\r
+ bool BusSuspended = USB_Host_IsBusSuspended();\r
+ uint8_t ReturnStatus = HOST_SENDCONTROL_Successful;\r
+ uint16_t DataLen = USB_HostRequest.wLength;\r
+\r
+ USB_Host_ResumeBus();\r
+ \r
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)\r
+ return ReturnStatus;\r
+\r
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+ Pipe_SetToken(PIPE_TOKEN_SETUP);\r
+ Pipe_ClearErrorFlags();\r
+ Pipe_ClearSetupSent();\r
+\r
+ Pipe_Unfreeze();\r
+\r
+ for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Host_Request_Header_t); HeaderByte++)\r
+ Pipe_Write_Byte(*(HeaderStream++));\r
+\r
+ Pipe_ClearSetupOUT();\r
+ \r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_SetupSent)))\r
+ goto End_Of_Control_Send;\r
+\r
+ Pipe_ClearSetupSent();\r
+ Pipe_Freeze();\r
+\r
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)\r
+ goto End_Of_Control_Send;\r
+\r
+ if ((USB_HostRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST)\r
+ {\r
+ Pipe_SetToken(PIPE_TOKEN_IN);\r
+ \r
+ if (DataStream != NULL)\r
+ {\r
+ while (DataLen)\r
+ {\r
+ Pipe_Unfreeze();\r
+\r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_InReceived)))\r
+ goto End_Of_Control_Send;\r
+ \r
+ if (!(Pipe_BytesInPipe()))\r
+ DataLen = 0;\r
+ \r
+ while (Pipe_BytesInPipe() && DataLen)\r
+ {\r
+ *(DataStream++) = Pipe_Read_Byte();\r
+ DataLen--;\r
+ }\r
+\r
+ Pipe_Freeze();\r
+ Pipe_ClearSetupIN();\r
+ }\r
+ }\r
+\r
+ Pipe_SetToken(PIPE_TOKEN_OUT);\r
+ Pipe_Unfreeze();\r
+ \r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))\r
+ goto End_Of_Control_Send;\r
+\r
+ Pipe_ClearSetupOUT();\r
+\r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))\r
+ goto End_Of_Control_Send;\r
+ }\r
+ else\r
+ {\r
+ if (DataStream != NULL)\r
+ {\r
+ Pipe_SetToken(PIPE_TOKEN_OUT);\r
+ Pipe_Unfreeze(); \r
+\r
+ while (DataLen)\r
+ {\r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))\r
+ goto End_Of_Control_Send;\r
+\r
+ while (DataLen && (Pipe_BytesInPipe() < USB_ControlPipeSize))\r
+ { \r
+ Pipe_Write_Byte(*(DataStream++));\r
+ DataLen--;\r
+ }\r
+ \r
+ Pipe_ClearSetupOUT();\r
+ }\r
+\r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))\r
+ goto End_Of_Control_Send;\r
+\r
+ Pipe_Freeze();\r
+ }\r
+ \r
+ Pipe_SetToken(PIPE_TOKEN_IN);\r
+ Pipe_Unfreeze();\r
+\r
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_InReceived)))\r
+ goto End_Of_Control_Send;\r
+\r
+ Pipe_ClearSetupIN();\r
+ }\r
+\r
+End_Of_Control_Send:\r
+ Pipe_Freeze();\r
+ \r
+ if (BusSuspended)\r
+ USB_Host_SuspendBus();\r
+\r
+ Pipe_ResetPipe(PIPE_CONTROLPIPE);\r
+\r
+ return ReturnStatus;\r
+}\r
+\r
+static uint8_t USB_Host_Wait_For_Setup_IOS(const uint8_t WaitType)\r
+{\r
+ uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS;\r
+ \r
+ while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSetupSent()) ||\r
+ ((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsSetupINReceived()) ||\r
+ ((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsSetupOUTReady())))\r
+ {\r
+ uint8_t ErrorCode;\r
+\r
+ if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)\r
+ return ErrorCode;\r
+ \r
+ if (!(TimeoutCounter--))\r
+ return HOST_SENDCONTROL_SoftwareTimeOut;\r
+ }\r
+\r
+ return HOST_SENDCONTROL_Successful;\r
+}\r
+\r
+#endif\r