Add branch for the conversion of demos to use standard C header files for configurati...
[pub/lufa.git] / Demos / Device / Incomplete / Sideshow / Lib / SideshowCommands.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
21 The author disclaim 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
28 this software.
29 */
30
31 #define INCLUDE_FROM_SIDESHOWCOMMANDS_H
32 #include "SideshowCommands.h"
33
34 UNICODE_STRING_t(80) UserSID = {LengthInBytes: sizeof(SECURITY_INTERACTIVE_RID_SID),
35 UnicodeString: SECURITY_INTERACTIVE_RID_SID};
36
37 Unicode_String_t DeviceName = {LengthInBytes: sizeof(L"LUFA Sideshow Device"),
38 UnicodeString: L"LUFA Sideshow Device"};
39
40 Unicode_String_t Manufacturer = {LengthInBytes: sizeof(L"Dean Camera"),
41 UnicodeString: L"Dean Camera"};
42
43 Unicode_String_t SupportedLanguage = {LengthInBytes: sizeof(L"en-US:1"),
44 UnicodeString: L"en-US:1"};
45
46 void Sideshow_ProcessCommandPacket(void)
47 {
48 SideShow_PacketHeader_t PacketHeader;
49
50 Endpoint_SelectEndpoint(SIDESHOW_OUT_EPADDR);
51 Endpoint_Read_Stream_LE(&PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
52
53 PacketHeader.Type.TypeFields.Response = true;
54
55 printf("\r\nCmd: %lX", (PacketHeader.Type.TypeLong & 0x00FFFFFF));
56
57 switch (PacketHeader.Type.TypeLong & 0x00FFFFFF)
58 {
59 case SIDESHOW_CMD_PING:
60 SideShow_Ping(&PacketHeader);
61 break;
62 case SIDESHOW_CMD_SYNC:
63 SideShow_Sync(&PacketHeader);
64 break;
65 case SIDESHOW_CMD_GET_CURRENT_USER:
66 SideShow_GetCurrentUser(&PacketHeader);
67 break;
68 case SIDESHOW_CMD_SET_CURRENT_USER:
69 SideShow_SetCurrentUser(&PacketHeader);
70 break;
71 case SIDESHOW_CMD_GET_CAPABILITIES:
72 SideShow_GetCapabilities(&PacketHeader);
73 break;
74 case SIDESHOW_CMD_GET_DEVICE_NAME:
75 SideShow_GetString(&PacketHeader, &DeviceName);
76 break;
77 case SIDESHOW_CMD_GET_MANUFACTURER:
78 SideShow_GetString(&PacketHeader, &Manufacturer);
79 break;
80 case SIDESHOW_CMD_GET_APPLICATION_ORDER:
81 SideShow_GetApplicationOrder(&PacketHeader);
82 break;
83 case SIDESHOW_CMD_GET_SUPPORTED_ENDPOINTS:
84 SideShow_GetSupportedEndpoints(&PacketHeader);
85 break;
86 case SIDESHOW_CMD_ADD_APPLICATION:
87 SideShow_AddApplication(&PacketHeader);
88 break;
89 case SIDESHOW_CMD_ADD_CONTENT:
90 SideShow_AddContent(&PacketHeader);
91 break;
92 case SIDESHOW_CMD_DELETE_CONTENT:
93 SideShow_DeleteContent(&PacketHeader);
94 break;
95 case SIDESHOW_CMD_DELETE_ALL_CONTENT:
96 SideShow_DeleteAllContent(&PacketHeader);
97 break;
98 case SIDESHOW_CMD_DELETE_APPLICATION:
99 SideShow_DeleteApplication(&PacketHeader);
100 break;
101 case SIDESHOW_CMD_DELETE_ALL_APPLICATIONS:
102 SideShow_DeleteAllApplications(&PacketHeader);
103 break;
104 default:
105 PacketHeader.Length -= sizeof(SideShow_PacketHeader_t);
106
107 Endpoint_Discard_Stream(PacketHeader.Length, NULL);
108 Endpoint_ClearOUT();
109
110 PacketHeader.Length = sizeof(SideShow_PacketHeader_t);
111 PacketHeader.Type.TypeFields.NAK = true;
112
113 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
114 Endpoint_Write_Stream_LE(&PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
115 Endpoint_ClearIN();
116
117 printf(" UNK");
118 }
119 }
120
121 static void SideShow_Ping(SideShow_PacketHeader_t* const PacketHeader)
122 {
123 Endpoint_ClearOUT();
124
125 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
126 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
127 Endpoint_ClearIN();
128 }
129
130 static void SideShow_Sync(SideShow_PacketHeader_t* const PacketHeader)
131 {
132 GUID_t ProtocolGUID;
133
134 Endpoint_Read_Stream_LE(&ProtocolGUID, sizeof(GUID_t), NULL);
135 Endpoint_ClearOUT();
136
137 if (!(GUID_COMPARE(&ProtocolGUID, (uint32_t[])STANDARD_PROTOCOL_GUID)))
138 PacketHeader->Type.TypeFields.NAK = true;
139
140 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
141 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
142 Endpoint_Write_Stream_LE(&ProtocolGUID, sizeof(GUID_t), NULL);
143 Endpoint_ClearIN();
144 }
145
146 static void SideShow_GetCurrentUser(SideShow_PacketHeader_t* const PacketHeader)
147 {
148 Endpoint_ClearOUT();
149
150 PacketHeader->Length = sizeof(SideShow_PacketHeader_t) + sizeof(uint32_t) + UserSID.LengthInBytes;
151
152 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
153 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
154 SideShow_Write_Unicode_String(&UserSID);
155 Endpoint_ClearIN();
156 }
157
158 static void SideShow_SetCurrentUser(SideShow_PacketHeader_t* const PacketHeader)
159 {
160 SideShow_Read_Unicode_String(&UserSID, sizeof(UserSID.UnicodeString));
161 Endpoint_ClearOUT();
162
163 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
164
165 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
166 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
167 Endpoint_ClearIN();
168 }
169
170 static void SideShow_GetCapabilities(SideShow_PacketHeader_t* const PacketHeader)
171 {
172 SideShow_PropertyKey_t Property;
173 SideShow_PropertyData_t PropertyData;
174
175 Endpoint_Read_Stream_LE(&Property, sizeof(SideShow_PropertyKey_t), NULL);
176 Endpoint_ClearOUT();
177
178 printf(" ID: %lu", Property.PropertyID);
179
180 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
181
182 if (GUID_COMPARE(&Property.PropertyGUID, (uint32_t[])SIDESHOW_PROPERTY_GUID))
183 {
184 switch (Property.PropertyID)
185 {
186 case PROPERTY_SIDESHOW_SCREENTYPE:
187 PropertyData.DataType = VT_I4;
188 PropertyData.Data.Data32 = ScreenText;
189 PacketHeader->Length += sizeof(uint32_t);
190
191 break;
192 case PROPERTY_SIDESHOW_SCREENWIDTH:
193 case PROPERTY_SIDESHOW_CLIENTWIDTH:
194 PropertyData.DataType = VT_UI2;
195 PropertyData.Data.Data16 = 16;
196 PacketHeader->Length += sizeof(uint16_t);
197
198 break;
199 case PROPERTY_SIDESHOW_SCREENHEIGHT:
200 case PROPERTY_SIDESHOW_CLIENTHEIGHT:
201 PropertyData.DataType = VT_UI2;
202 PropertyData.Data.Data16 = 2;
203 PacketHeader->Length += sizeof(uint16_t);
204
205 break;
206 case PROPERTY_SIDESHOW_COLORDEPTH:
207 PropertyData.DataType = VT_UI2;
208 PropertyData.Data.Data16 = 1;
209 PacketHeader->Length += sizeof(uint16_t);
210
211 break;
212 case PROPERTY_SIDESHOW_COLORTYPE:
213 PropertyData.DataType = VT_UI2;
214 PropertyData.Data.Data16 = BlackAndWhiteDisplay;
215 PacketHeader->Length += sizeof(uint16_t);
216
217 break;
218 case PROPERTY_SIDESHOW_DATACACHE:
219 PropertyData.DataType = VT_BOOL;
220 PropertyData.Data.Data16 = false;
221 PacketHeader->Length += sizeof(uint16_t);
222
223 break;
224 case PROPERTY_SIDESHOW_SUPPORTEDLANGS:
225 case PROPERTY_SIDESHOW_CURRENTLANG:
226 PropertyData.DataType = VT_LPWSTR;
227 PropertyData.Data.DataPointer = &SupportedLanguage;
228 PacketHeader->Length += SupportedLanguage.LengthInBytes;
229
230 break;
231 default:
232 PropertyData.DataType = VT_EMPTY;
233 break;
234 }
235 }
236 else if (GUID_COMPARE(&Property.PropertyGUID, (uint32_t[])DEVICE_PROPERTY_GUID))
237 {
238 switch (Property.PropertyID)
239 {
240 case PROPERTY_DEVICE_DEVICETYPE:
241 PropertyData.DataType = VT_UI4;
242 PropertyData.Data.Data32 = GenericDevice;
243 PacketHeader->Length += sizeof(uint32_t);
244
245 break;
246 }
247 }
248 else
249 {
250 PacketHeader->Type.TypeFields.NAK = true;
251
252 printf(" WRONG GUID");
253 printf(" %lX %lX %lX %lX", Property.PropertyGUID.Chunks[0], Property.PropertyGUID.Chunks[1],
254 Property.PropertyGUID.Chunks[2], Property.PropertyGUID.Chunks[3]);
255 }
256
257 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
258 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
259
260 if (!(PacketHeader->Type.TypeFields.NAK))
261 {
262 switch (PropertyData.DataType)
263 {
264 case VT_UI4:
265 case VT_I4:
266 Endpoint_Write_Stream_LE(&PropertyData.Data.Data32, sizeof(uint32_t), NULL);
267 break;
268 case VT_UI2:
269 case VT_I2:
270 case VT_BOOL:
271 Endpoint_Write_Stream_LE(&PropertyData.Data.Data16, sizeof(uint16_t), NULL);
272 break;
273 case VT_LPWSTR:
274 SideShow_Write_Unicode_String((Unicode_String_t*)PropertyData.Data.Data16);
275 break;
276 }
277 }
278
279 Endpoint_ClearIN();
280 return;
281 }
282
283 static void SideShow_GetString(SideShow_PacketHeader_t* const PacketHeader,
284 void* const UnicodeStruct)
285 {
286 Endpoint_ClearOUT();
287
288 PacketHeader->Length = sizeof(SideShow_PacketHeader_t) +
289 sizeof(uint32_t) + ((Unicode_String_t*)UnicodeStruct)->LengthInBytes;
290
291 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
292 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
293 SideShow_Write_Unicode_String(UnicodeStruct);
294 Endpoint_ClearIN();
295 }
296
297 static void SideShow_GetApplicationOrder(SideShow_PacketHeader_t* const PacketHeader)
298 {
299 uint8_t TotalApplications = 0;
300
301 Endpoint_ClearOUT();
302
303 for (uint8_t App = 0; App < MAX_APPLICATIONS; App++)
304 {
305 if (InstalledApplications[App].InUse)
306 TotalApplications++;
307 }
308
309 PacketHeader->Length = sizeof(SideShow_PacketHeader_t) +
310 sizeof(uint32_t) + (TotalApplications * sizeof(GUID_t));
311
312 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
313 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
314 Endpoint_Write_32_LE(TotalApplications);
315
316 for (uint8_t App = 0; App < MAX_APPLICATIONS; App++)
317 {
318 if (InstalledApplications[App].InUse)
319 Endpoint_Write_Stream_LE(&InstalledApplications[App].ApplicationID, sizeof(GUID_t), NULL);
320 }
321
322 Endpoint_ClearIN();
323 }
324
325 static void SideShow_GetSupportedEndpoints(SideShow_PacketHeader_t* const PacketHeader)
326 {
327 GUID_t SupportedEndpointGUID = (GUID_t){Chunks: SIMPLE_CONTENT_FORMAT_GUID};
328
329 Endpoint_ClearOUT();
330
331 PacketHeader->Length = sizeof(SideShow_PacketHeader_t) + sizeof(uint32_t) + sizeof(GUID_t);
332
333 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
334 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
335 Endpoint_Write_32_LE(1);
336 Endpoint_Write_Stream_LE(&SupportedEndpointGUID, sizeof(GUID_t), NULL);
337 Endpoint_ClearIN();
338 }
339
340 static void SideShow_AddApplication(SideShow_PacketHeader_t* const PacketHeader)
341 {
342 SideShow_Application_t* CurrApp;
343 GUID_t ApplicationID;
344
345 Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t), NULL);
346
347 CurrApp = SideShow_GetApplicationFromGUID(&ApplicationID);
348
349 if (CurrApp == NULL)
350 CurrApp = SideShow_GetFreeApplication();
351
352 if (CurrApp == NULL)
353 {
354 PacketHeader->Length -= sizeof(SideShow_PacketHeader_t) + sizeof(GUID_t);
355
356 Endpoint_Discard_Stream(PacketHeader->Length, NULL);
357 Endpoint_ClearOUT();
358
359 PacketHeader->Type.TypeFields.NAK = true;
360 }
361 else
362 {
363 CurrApp->ApplicationID = ApplicationID;
364 Endpoint_Read_Stream_LE(&CurrApp->EndpointID, sizeof(GUID_t), NULL);
365 SideShow_Read_Unicode_String(&CurrApp->ApplicationName, sizeof(CurrApp->ApplicationName.UnicodeString));
366 Endpoint_Read_Stream_LE(&CurrApp->CachePolicy, sizeof(uint32_t), NULL);
367 Endpoint_Read_Stream_LE(&CurrApp->OnlineOnly, sizeof(uint32_t), NULL);
368 SideShow_Discard_Byte_Stream();
369 SideShow_Discard_Byte_Stream();
370 SideShow_Discard_Byte_Stream();
371 Endpoint_ClearOUT();
372
373 CurrApp->InUse = true;
374 CurrApp->HaveContent = false;
375 CurrApp->CurrentContentID = 1;
376 }
377
378 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
379
380 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
381 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
382 Endpoint_ClearIN();
383 }
384
385 static void SideShow_DeleteApplication(SideShow_PacketHeader_t* const PacketHeader)
386 {
387 GUID_t ApplicationGUID;
388
389 Endpoint_Read_Stream_LE(&ApplicationGUID, sizeof(GUID_t), NULL);
390 Endpoint_ClearOUT();
391
392 SideShow_Application_t* AppToDelete = SideShow_GetApplicationFromGUID(&ApplicationGUID);
393
394 if (AppToDelete != NULL)
395 AppToDelete->InUse = false;
396 else
397 PacketHeader->Type.TypeFields.NAK = true;
398
399 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
400
401 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
402 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
403 Endpoint_ClearIN();
404 }
405
406 static void SideShow_DeleteAllApplications(SideShow_PacketHeader_t* const PacketHeader)
407 {
408 Endpoint_ClearOUT();
409
410 for (uint8_t App = 0; App < MAX_APPLICATIONS; App++)
411 InstalledApplications[App].InUse = false;
412
413 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
414 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
415 Endpoint_ClearIN();
416 }
417
418 static void SideShow_AddContent(SideShow_PacketHeader_t* const PacketHeader)
419 {
420 GUID_t ApplicationID;
421 GUID_t EndpointID;
422 SideShow_Application_t* Application;
423
424 Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t), NULL);
425 Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t), NULL);
426
427 Application = SideShow_GetApplicationFromGUID(&ApplicationID);
428
429 if (Application == NULL)
430 {
431 SideShow_Discard_Byte_Stream();
432 PacketHeader->Type.TypeFields.NAK = true;
433 }
434 else if (!(SideShow_AddSimpleContent(PacketHeader, Application)))
435 {
436 PacketHeader->Type.TypeFields.NAK = true;
437 }
438
439 Endpoint_ClearOUT();
440
441 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
442
443 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
444 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
445 Endpoint_ClearIN();
446 }
447
448 static void SideShow_DeleteContent(SideShow_PacketHeader_t* const PacketHeader)
449 {
450 GUID_t ApplicationID;
451 GUID_t EndpointID;
452 uint32_t ContentID;
453
454 Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t), NULL);
455 Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t), NULL);
456 Endpoint_Read_Stream_LE(&ContentID, sizeof(uint32_t), NULL);
457 Endpoint_ClearOUT();
458
459 SideShow_Application_t* Application = SideShow_GetApplicationFromGUID(&ApplicationID);
460
461 if ((Application != NULL) && (Application->CurrentContentID == ContentID))
462 Application->HaveContent = false;
463 else
464 PacketHeader->Type.TypeFields.NAK = true;
465
466 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
467
468 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
469 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
470 Endpoint_ClearIN();
471 }
472
473 static void SideShow_DeleteAllContent(SideShow_PacketHeader_t* const PacketHeader)
474 {
475 GUID_t ApplicationID;
476 GUID_t EndpointID;
477
478 Endpoint_Read_Stream_LE(&ApplicationID, sizeof(GUID_t), NULL);
479 Endpoint_Read_Stream_LE(&EndpointID, sizeof(GUID_t), NULL);
480 Endpoint_ClearOUT();
481
482 SideShow_Application_t* Application = SideShow_GetApplicationFromGUID(&ApplicationID);
483
484 if (Application != NULL)
485 Application->HaveContent = false;
486 else
487 PacketHeader->Type.TypeFields.NAK = true;
488
489 PacketHeader->Length = sizeof(SideShow_PacketHeader_t);
490
491 Endpoint_SelectEndpoint(SIDESHOW_IN_EPADDR);
492 Endpoint_Write_Stream_LE(PacketHeader, sizeof(SideShow_PacketHeader_t), NULL);
493 Endpoint_ClearIN();
494 }
495