+/*\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
+#define INCLUDE_FROM_SIDESHOWCOMMANDS_H\r
+#include "SideshowCommands.h"\r
+\r
+UNICODE_STRING_t(80) UserSID = {LengthInBytes: sizeof(SECURITY_INTERACTIVE_RID_SID),\r
+ UnicodeString: SECURITY_INTERACTIVE_RID_SID};\r
+\r
+Unicode_String_t DeviceName = {LengthInBytes: sizeof(L"LUFA Sideshow Device"),\r
+ UnicodeString: L"LUFA Sideshow Device"};\r
+\r
+Unicode_String_t Manufacturer = {LengthInBytes: sizeof(L"Dean Camera"),\r
+ UnicodeString: L"Dean Camera"};\r
+\r
+Unicode_String_t SupportedLanguage = {LengthInBytes: sizeof(L"en-US:1"),\r
+ UnicodeString: L"en-US:1"};\r
+ \r
+void Sideshow_ProcessCommandPacket(void)\r
+{\r
+ SideShow_PacketHeader_t PacketHeader;\r
+ \r
+ Endpoint_SelectEndpoint(SIDESHOW_OUT_EPNUM); \r
+ Endpoint_Read_Stream_LE(&PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ \r
+ PacketHeader.Type.Response = true;\r
+\r
+ printf("\r\nCmd: %lX", (PacketHeader.Type.TypeLong & 0x00FFFFFF));\r
+\r
+ switch (PacketHeader.Type.TypeLong & 0x00FFFFFF)\r
+ {\r
+ case SIDESHOW_CMD_PING:\r
+ SideShow_Ping(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_SYNC:\r
+ SideShow_Sync(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_GET_CURRENT_USER:\r
+ SideShow_GetCurrentUser(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_SET_CURRENT_USER:\r
+ SideShow_SetCurrentUser(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_GET_CAPABILITIES:\r
+ SideShow_GetCapabilities(&PacketHeader);\r
+ break; \r
+ case SIDESHOW_CMD_GET_DEVICE_NAME:\r
+ SideShow_GetString(&PacketHeader, &DeviceName);\r
+ break;\r
+ case SIDESHOW_CMD_GET_MANUFACTURER:\r
+ SideShow_GetString(&PacketHeader, &Manufacturer);\r
+ break;\r
+ case SIDESHOW_CMD_GET_APPLICATION_ORDER:\r
+ SideShow_GetApplicationOrder(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_GET_SUPPORTED_ENDPOINTS:\r
+ SideShow_GetSupportedEndpoints(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_ADD_APPLICATION:\r
+ SideShow_AddApplication(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_ADD_CONTENT:\r
+ SideShow_AddContent(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_DELETE_CONTENT:\r
+ SideShow_DeleteContent(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_DELETE_ALL_CONTENT:\r
+ SideShow_DeleteAllContent(&PacketHeader);\r
+ break; \r
+ case SIDESHOW_CMD_DELETE_APPLICATION:\r
+ SideShow_DeleteApplication(&PacketHeader);\r
+ break;\r
+ case SIDESHOW_CMD_DELETE_ALL_APPLICATIONS:\r
+ SideShow_DeleteAllApplications(&PacketHeader);\r
+ break;\r
+ default:\r
+ PacketHeader.Length -= sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_Discard_Stream(PacketHeader.Length);\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader.Length = sizeof(SideShow_PacketHeader_t);\r
+ PacketHeader.Type.NAK = true;\r
+ \r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM); \r
+ Endpoint_Write_Stream_LE(&PacketHeader, sizeof(SideShow_PacketHeader_t)); \r
+ Endpoint_ClearIN();\r
+ \r
+ printf(" UNK");\r
+ }\r
+}\r
+\r
+static void SideShow_Ping(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ Endpoint_ClearOUT();\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM); \r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t)); \r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_Sync(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t ProtocolGUID;\r
+\r
+ Endpoint_Read_Stream_LE(&ProtocolGUID, sizeof(GUID_t));\r
+ Endpoint_ClearOUT();\r
+ \r
+ if (memcmp(&ProtocolGUID, (uint32_t[])STANDARD_PROTOCOL_GUID, sizeof(GUID_t)) != 0)\r
+ PacketHeader->Type.NAK = true;\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t)); \r
+ Endpoint_Write_Stream_LE(&ProtocolGUID, sizeof(GUID_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_GetCurrentUser(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t) + sizeof(uint32_t) + UserSID.LengthInBytes;\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ SideShow_Write_Unicode_String(&UserSID);\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_SetCurrentUser(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ SideShow_Read_Unicode_String(&UserSID, sizeof(UserSID.UnicodeString));\r
+ Endpoint_ClearOUT();\r
+ \r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_GetCapabilities(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ SideShow_PropertyKey_t Property;\r
+ SideShow_PropertyData_t PropertyData;\r
+\r
+ Endpoint_Read_Stream_LE(&Property, sizeof(SideShow_PropertyKey_t));\r
+ Endpoint_ClearOUT();\r
+ \r
+ printf(" ID: %lu", Property.PropertyID);\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ if (memcmp(&Property.PropertyGUID, (uint32_t[])SIDESHOW_PROPERTY_GUID, sizeof(GUID_t)) == 0)\r
+ {\r
+ switch (Property.PropertyID)\r
+ {\r
+ case PROPERTY_SIDESHOW_SCREENTYPE:\r
+ PropertyData.DataType = VT_I4;\r
+ PropertyData.Data.Data32 = ScreenText;\r
+ PacketHeader->Length += sizeof(uint32_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_SCREENWIDTH:\r
+ case PROPERTY_SIDESHOW_CLIENTWIDTH:\r
+ PropertyData.DataType = VT_UI2;\r
+ PropertyData.Data.Data16 = 16;\r
+ PacketHeader->Length += sizeof(uint16_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_SCREENHEIGHT:\r
+ case PROPERTY_SIDESHOW_CLIENTHEIGHT:\r
+ PropertyData.DataType = VT_UI2;\r
+ PropertyData.Data.Data16 = 2;\r
+ PacketHeader->Length += sizeof(uint16_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_COLORDEPTH:\r
+ PropertyData.DataType = VT_UI2;\r
+ PropertyData.Data.Data16 = 1;\r
+ PacketHeader->Length += sizeof(uint16_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_COLORTYPE:\r
+ PropertyData.DataType = VT_UI2;\r
+ PropertyData.Data.Data16 = BlackAndWhiteDisplay;\r
+ PacketHeader->Length += sizeof(uint16_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_DATACACHE:\r
+ PropertyData.DataType = VT_BOOL;\r
+ PropertyData.Data.Data16 = false;\r
+ PacketHeader->Length += sizeof(uint16_t);\r
+ \r
+ break;\r
+ case PROPERTY_SIDESHOW_SUPPORTEDLANGS:\r
+ case PROPERTY_SIDESHOW_CURRENTLANG:\r
+ PropertyData.DataType = VT_LPWSTR;\r
+ PropertyData.Data.DataPointer = &SupportedLanguage;\r
+ PacketHeader->Length += SupportedLanguage.LengthInBytes;\r
+ \r
+ break;\r
+ default:\r
+ PropertyData.DataType = VT_EMPTY;\r
+ break;\r
+ }\r
+ }\r
+ else if (memcmp(&Property.PropertyGUID, (uint32_t[])DEVICE_PROPERTY_GUID, sizeof(GUID_t)) == 0)\r
+ {\r
+ switch (Property.PropertyID)\r
+ {\r
+ case PROPERTY_DEVICE_DEVICETYPE:\r
+ PropertyData.DataType = VT_UI4;\r
+ PropertyData.Data.Data32 = GenericDevice;\r
+ PacketHeader->Length += sizeof(uint32_t);\r
+ \r
+ break;\r
+ }\r
+ } \r
+ else\r
+ {\r
+ PacketHeader->Type.NAK = true; \r
+ \r
+ printf(" WRONG GUID");\r
+ printf(" %lX %lX %lX %lX", Property.PropertyGUID.Chunks[0], Property.PropertyGUID.Chunks[1],\r
+ Property.PropertyGUID.Chunks[2], Property.PropertyGUID.Chunks[3]); \r
+ }\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ \r
+ if (!(PacketHeader->Type.NAK))\r
+ {\r
+ switch (PropertyData.DataType)\r
+ {\r
+ case VT_UI4:\r
+ case VT_I4:\r
+ Endpoint_Write_Stream_LE(&PropertyData.Data.Data32, sizeof(uint32_t));\r
+ break;\r
+ case VT_UI2:\r
+ case VT_I2:\r
+ case VT_BOOL:\r
+ Endpoint_Write_Stream_LE(&PropertyData.Data.Data16, sizeof(uint16_t));\r
+ break;\r
+ case VT_LPWSTR:\r
+ SideShow_Write_Unicode_String((Unicode_String_t*)PropertyData.Data.Data16);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ Endpoint_ClearIN();\r
+ return;\r
+}\r
+\r
+static void SideShow_GetString(SideShow_PacketHeader_t* PacketHeader, void* UnicodeStruct)\r
+{\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t) +\r
+ sizeof(uint32_t) + ((Unicode_String_t*)UnicodeStruct)->LengthInBytes;\r
+ \r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ SideShow_Write_Unicode_String(UnicodeStruct);\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_GetApplicationOrder(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ uint8_t TotalInstalledApplications = SideShow_GetTotalApplications();\r
+ uint16_t GadgetGUIDBytes = (TotalInstalledApplications * sizeof(GUID_t));\r
+\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t) +\r
+ sizeof(uint32_t) + GadgetGUIDBytes;\r
+ \r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_Write_DWord_LE(TotalInstalledApplications);\r
+ \r
+ for (uint8_t App = 0; App < MAX_APPLICATIONS; App++)\r
+ {\r
+ if (InstalledApplications[App].InUse == true)\r
+ Endpoint_Write_Stream_LE(&InstalledApplications[App].ApplicationID, sizeof(GUID_t));\r
+ }\r
+\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_GetSupportedEndpoints(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t SupportedEndpointGUID = (GUID_t){Chunks: SIMPLE_CONTENT_FORMAT_GUID};\r
+\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t) + sizeof(uint32_t) + sizeof(GUID_t);\r
+ \r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_Write_DWord_LE(1);\r
+ Endpoint_Write_Stream_LE(&SupportedEndpointGUID, sizeof(GUID_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_AddApplication(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ SideShow_Application_t* CurrApp;\r
+ GUID_t ApplicationID;\r
+\r
+ Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t));\r
+\r
+ CurrApp = SideShow_GetApplicationFromGUID(&ApplicationID);\r
+\r
+ if (CurrApp == NULL)\r
+ CurrApp = SideShow_GetFreeApplication();\r
+\r
+ if (CurrApp == NULL)\r
+ {\r
+ PacketHeader->Length -= sizeof(SideShow_PacketHeader_t) + sizeof(GUID_t);\r
+\r
+ Endpoint_Discard_Stream(PacketHeader->Length);\r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Type.NAK = true;\r
+ }\r
+ else\r
+ {\r
+ CurrApp->ApplicationID = ApplicationID;\r
+ Endpoint_Read_Stream_LE(&CurrApp->EndpointID, sizeof(GUID_t));\r
+ SideShow_Read_Unicode_String(&CurrApp->ApplicationName, sizeof(CurrApp->ApplicationName.UnicodeString));\r
+ Endpoint_Read_Stream_LE(&CurrApp->CachePolicy, sizeof(uint32_t));\r
+ Endpoint_Read_Stream_LE(&CurrApp->OnlineOnly, sizeof(uint32_t));\r
+ SideShow_Discard_Byte_Stream();\r
+ SideShow_Discard_Byte_Stream();\r
+ SideShow_Discard_Byte_Stream();\r
+ Endpoint_ClearOUT();\r
+ \r
+ CurrApp->InUse = true;\r
+ CurrApp->HaveContent = false;\r
+ CurrApp->CurrentContentID = 1;\r
+ }\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_DeleteApplication(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t ApplicationGUID;\r
+ \r
+ Endpoint_Read_Stream_LE(&ApplicationGUID, sizeof(GUID_t)); \r
+ Endpoint_ClearOUT();\r
+\r
+ SideShow_Application_t* AppToDelete = SideShow_GetApplicationFromGUID(&ApplicationGUID);\r
+\r
+ if (AppToDelete != NULL)\r
+ {\r
+ AppToDelete->InUse = false;\r
+ }\r
+ else\r
+ PacketHeader->Type.NAK = true;\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_DeleteAllApplications(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ Endpoint_ClearOUT();\r
+ \r
+ for (uint8_t App = 0; App < MAX_APPLICATIONS; App++)\r
+ InstalledApplications[App].InUse = false;\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_AddContent(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t ApplicationID;\r
+ GUID_t EndpointID;\r
+ SideShow_Application_t* Application;\r
+ \r
+ Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t));\r
+ Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t));\r
+ \r
+ Application = SideShow_GetApplicationFromGUID(&ApplicationID);\r
+ \r
+ if (Application == NULL)\r
+ {\r
+ SideShow_Discard_Byte_Stream();\r
+ PacketHeader->Type.NAK = true;\r
+ }\r
+ else if (!(SideShow_AddSimpleContent(PacketHeader, Application)))\r
+ {\r
+ PacketHeader->Type.NAK = true;\r
+ }\r
+ \r
+ Endpoint_ClearOUT();\r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_DeleteContent(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t ApplicationID;\r
+ GUID_t EndpointID;\r
+ uint32_t ContentID;\r
+\r
+ Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t));\r
+ Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t));\r
+ Endpoint_Read_Stream_LE(&ContentID, sizeof(uint32_t));\r
+ Endpoint_ClearOUT();\r
+ \r
+ SideShow_Application_t* Application = SideShow_GetApplicationFromGUID(&ApplicationID);\r
+ \r
+ if ((Application != NULL) && (Application->CurrentContentID == ContentID))\r
+ Application->HaveContent = false;\r
+ else\r
+ PacketHeader->Type.NAK = true;\r
+ \r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN();\r
+}\r
+\r
+static void SideShow_DeleteAllContent(SideShow_PacketHeader_t* PacketHeader)\r
+{\r
+ GUID_t ApplicationID;\r
+ GUID_t EndpointID;\r
+\r
+ Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t));\r
+ Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t));\r
+ Endpoint_ClearOUT();\r
+\r
+ SideShow_Application_t* Application = SideShow_GetApplicationFromGUID(&ApplicationID);\r
+ \r
+ if (Application != NULL)\r
+ Application->HaveContent = false;\r
+ else\r
+ PacketHeader->Type.NAK = true; \r
+\r
+ PacketHeader->Length = sizeof(SideShow_PacketHeader_t);\r
+\r
+ Endpoint_SelectEndpoint(SIDESHOW_IN_EPNUM);\r
+ Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t));\r
+ Endpoint_ClearIN(); \r
+}\r