ovr_sdk

view LibOVR/Src/OVR_SerialFormat.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line source
1 /************************************************************************************
3 Filename : OVR_System.cpp
4 Content : General kernel initialization/cleanup, including that
5 of the memory allocator.
6 Created : September 19, 2012
7 Notes :
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
16 You may obtain a copy of the License at
18 http://www.oculusvr.com/licenses/LICENSE-3.2
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
26 ************************************************************************************/
28 #include "OVR_SerialFormat.h"
30 #ifdef SERIAL_FORMAT_UNIT_TEST
31 #include "Kernel/OVR_Log.h"
32 #endif
34 namespace OVR {
37 //// Serial Format Detection
39 SerialFormatType DetectBufferFormat(uint8_t firstByte, int sizeInBytes)
40 {
41 switch (firstByte)
42 {
43 case SerialFormatType_DK2:
44 if (sizeInBytes == 12)
45 {
46 return SerialFormatType_DK2;
47 }
48 break;
49 default:
50 break;
51 }
53 return SerialFormatType_Invalid;
54 }
57 //// DK2 Helpers
59 static bool ValidDK2ProductId(int x)
60 {
61 switch (x)
62 {
63 case DK2ProductId_DK1:
64 case DK2ProductId_DK2:
65 case DK2ProductId_Refurb:
66 return true;
67 default:
68 break;
69 }
71 return false;
72 }
74 static bool ValidDK2PartId(int x)
75 {
76 switch (x)
77 {
78 case DK2PartId_HMD:
79 case DK2PartId_PTC:
80 case DK2PartId_Carton:
81 return true;
82 default:
83 break;
84 }
86 return false;
87 }
90 //// DK2BinarySerialFormat
92 bool DK2BinarySerialFormat::FromBuffer(const uint8_t buffer[12], bool allowUnknownTypes)
93 {
94 // Format Type must be 0
96 int formatType = buffer[0];
98 if (formatType != SerialFormatType_DK2)
99 {
100 return false;
101 }
103 // Product Id
105 int productId = buffer[1] >> 4;
107 if (!allowUnknownTypes && !ValidDK2ProductId(productId))
108 {
109 return false;
110 }
112 ProductId = (DK2ProductId)productId;
114 // Part Id
116 int partId = buffer[1] & 15;
118 if (!allowUnknownTypes && !ValidDK2PartId(partId))
119 {
120 return false;
121 }
123 PartId = (DK2PartId)partId;
125 // Minutes Since Epoch (May 1, 2014)
127 MinutesSinceEpoch = buffer[4] | ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16);
129 // Unit number on that day
131 UnitNumber = buffer[6] | ((uint32_t)buffer[5] << 8);
133 // Hash of MAC address
135 MacHash[0] = buffer[7];
136 MacHash[1] = buffer[8];
137 MacHash[2] = buffer[9];
138 MacHash[3] = buffer[10];
139 MacHash[4] = buffer[11];
141 return true;
142 }
144 void DK2BinarySerialFormat::ToBuffer(uint8_t buffer[12])
145 {
146 // Serialize to buffer
147 buffer[0] = SerialFormatType_DK2;
148 buffer[1] = (uint8_t)((ProductId << 4) | (PartId));
149 buffer[2] = (uint8_t)(MinutesSinceEpoch >> 16);
150 buffer[3] = (uint8_t)(MinutesSinceEpoch >> 8);
151 buffer[4] = (uint8_t)MinutesSinceEpoch;
152 buffer[5] = (uint8_t)(UnitNumber >> 8);
153 buffer[6] = (uint8_t)UnitNumber;
155 buffer[7] = MacHash[0];
156 buffer[8] = MacHash[1];
157 buffer[9] = MacHash[2];
158 buffer[10] = MacHash[3];
159 buffer[11] = MacHash[4];
160 }
162 bool DK2BinarySerialFormat::operator==(const DK2BinarySerialFormat& rhs)
163 {
164 if (ProductId != rhs.ProductId)
165 return false;
166 if (PartId != rhs.PartId)
167 return false;
168 if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
169 return false;
170 if (UnitNumber != rhs.UnitNumber)
171 return false;
172 for (int ii = 0; ii < 5; ++ii)
173 {
174 if (MacHash[ii] != rhs.MacHash[ii])
175 return false;
176 }
177 return true;
178 }
181 //// DK2PrintedSerialFormat
183 // Base-32 Crockford decoding rules:
184 // 0 o O => 0
185 // 1 i | I L l => 1
186 // 2, 3, 4, 5, 6, 7, 8, 9 => 2 - 9
187 // a, b, c, d, e, f, g, h => 10 - 17
188 // j, k => 18, 19
189 // m, n => 20, 21
190 // p, q, r, s, t => 22, 23, 24, 25, 26
191 // v, w, x, y, z => 27, 28, 29, 30, 31
192 static const char Base32FromChar[256] = {
193 // Null - Unit Separator
194 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
196 // (sp)!"#$%&'()*+,-./
197 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
198 // 0123456789:;<=>?
199 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
200 // @ - _ (upper case)
201 -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0,
202 22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1,
203 // ` - DEL (lower case)
204 -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0,
205 22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1, 1, -1, -1, -1,
207 // Extended ASCII:
208 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
209 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
211 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
212 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
214 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
215 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
217 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
219 };
221 // Base-32 Crockford encoding rules:
222 // 0-9 => 0-9
223 // 10 - 17 => a, b, c, d, e, f, g, h
224 // 18, 19 => j, k
225 // 20, 21 => m, n
226 // 22, 23, 24, 25, 26 => p, q, r, s, t
227 // 27, 28, 29, 30, 31 => v, w, x, y, z
228 static const char* CharFromBase32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
230 bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes)
231 {
232 // Note: Truncated strings get caught by returning negative values from the table like other invalid characters
234 // Product Id
236 int productId = Base32FromChar[(unsigned char)str[0]];
237 if (productId < 0 || (!allowUnknownTypes && !ValidDK2ProductId(productId)))
238 {
239 return false;
240 }
242 ProductId = (DK2ProductId)productId;
244 // Label Type
246 int labelType = Base32FromChar[(unsigned char)str[1]];
247 if (labelType < 0 || (!allowUnknownTypes && !ValidDK2PartId(labelType)))
248 {
249 return false;
250 }
252 LabelType = (DK2LabelType)labelType;
254 uint8_t dataBytes[7];
255 for (int ii = 0; ii < 7; ++ii)
256 {
257 int c = Base32FromChar[(unsigned char)str[2 + ii]];
258 if (c < 0) return false;
259 dataBytes[ii] = (uint8_t)c;
260 }
262 // Minutes Since Epoch
264 MinutesSinceEpoch = dataBytes[3] | ((uint32_t)dataBytes[2] << 5) | ((uint32_t)dataBytes[1] << 10) | ((uint32_t)dataBytes[0] << 15);
266 // Unit Number
268 UnitNumber = dataBytes[6] | ((uint32_t)dataBytes[5] << 5) | ((uint32_t)dataBytes[4] << 10);
270 // MAC Hash
272 for (int ii = 0; ii < 3; ++ii)
273 {
274 int c = Base32FromChar[(unsigned char)str[9 + ii]];
275 if (c < 0)
276 {
277 return false;
278 }
280 MacHashLow[ii] = (uint8_t)c;
281 }
283 // String must be exactly 12 characters
284 if (str[12] != '\0')
285 {
286 return false;
287 }
289 return true;
290 }
292 String DK2PrintedSerialFormat::ToBase32()
293 {
294 String s;
296 s += CharFromBase32[ProductId];
297 s += CharFromBase32[LabelType];
298 s += CharFromBase32[(MinutesSinceEpoch >> 15) & 31];
299 s += CharFromBase32[(MinutesSinceEpoch >> 10) & 31];
300 s += CharFromBase32[(MinutesSinceEpoch >> 5) & 31];
301 s += CharFromBase32[MinutesSinceEpoch & 31];
302 s += CharFromBase32[(UnitNumber >> 10) & 31];
303 s += CharFromBase32[(UnitNumber >> 5) & 31];
304 s += CharFromBase32[UnitNumber & 31];
305 s += CharFromBase32[MacHashLow[0] & 31];
306 s += CharFromBase32[MacHashLow[1] & 31];
307 s += CharFromBase32[MacHashLow[2] & 31];
309 return s;
310 }
312 bool DK2PrintedSerialFormat::operator==(const DK2PrintedSerialFormat& rhs)
313 {
314 if (ProductId != rhs.ProductId)
315 return false;
316 if (LabelType != rhs.LabelType)
317 return false;
318 if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
319 return false;
320 if (UnitNumber != rhs.UnitNumber)
321 return false;
322 for (int ii = 0; ii < 3; ++ii)
323 {
324 if (MacHashLow[ii] != rhs.MacHashLow[ii])
325 return false;
326 }
327 return true;
328 }
330 bool DK2PrintedSerialFormat::operator==(const DK2BinarySerialFormat& rhs)
331 {
332 if (ProductId != rhs.ProductId)
333 return false;
334 if (LabelType != rhs.PartId)
335 return false;
336 if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
337 return false;
338 if (UnitNumber != rhs.UnitNumber)
339 return false;
340 for (int ii = 0; ii < 3; ++ii)
341 {
342 if (MacHashLow[ii] != (rhs.MacHash[ii] & 31))
343 return false;
344 }
345 return true;
346 }
348 void DK2PrintedSerialFormat::FromBinary(const DK2BinarySerialFormat& bin)
349 {
350 ProductId = bin.ProductId;
351 LabelType = bin.PartId;
352 MinutesSinceEpoch = bin.MinutesSinceEpoch;
353 UnitNumber = bin.UnitNumber;
354 MacHashLow[0] = bin.MacHash[0] & 31;
355 MacHashLow[1] = bin.MacHash[1] & 31;
356 MacHashLow[2] = bin.MacHash[2] & 31;
357 }
360 //// Unit Tests
362 #ifdef SERIAL_FORMAT_UNIT_TEST
364 int DecodeBase32(char ch)
365 {
366 if (ch >= '2' && ch <= '9')
367 return 2 + ch - '2';
368 if (ch >= 'a' && ch <= 'h')
369 return 10 + ch - 'a';
370 if (ch >= 'A' && ch <= 'H')
371 return 10 + ch - 'A';
372 if (ch >= 'j' && ch <= 'k')
373 return 18 + ch - 'j';
374 if (ch >= 'J' && ch <= 'K')
375 return 18 + ch - 'J';
376 if (ch >= 'm' && ch <= 'n')
377 return 20 + ch - 'm';
378 if (ch >= 'M' && ch <= 'N')
379 return 20 + ch - 'M';
380 if (ch >= 'p' && ch <= 't')
381 return 22 + ch - 'p';
382 if (ch >= 'P' && ch <= 'T')
383 return 22 + ch - 'P';
384 if (ch >= 'v' && ch <= 'z')
385 return 27 + ch - 'v';
386 if (ch >= 'V' && ch <= 'Z')
387 return 27 + ch - 'V';
389 switch (ch)
390 {
391 case '0':
392 case 'o':
393 case 'O':
394 return 0;
395 case '1':
396 case 'i':
397 case '|':
398 case 'I':
399 case 'L':
400 case 'l':
401 return 1;
402 }
404 return -1;
405 }
407 void TestSerialFormatStuff()
408 {
409 for (int ii = 0; ii < 256; ++ii)
410 {
411 OVR_ASSERT(Base32FromChar[ii] == (char)DecodeBase32((char)ii));
412 }
414 DK2BinarySerialFormat sa;
415 sa.ProductId = DK2ProductId_DK2;
416 sa.PartId = DK2PartId_HMD;
417 sa.MinutesSinceEpoch = 65000;
418 sa.UnitNumber = 2;
419 sa.MacHash[0] = 0xa1;
420 sa.MacHash[1] = 0xb2;
421 sa.MacHash[2] = 0xc3;
422 sa.MacHash[3] = 0xd4;
423 sa.MacHash[4] = 0xe5;
425 uint8_t buffer[12];
426 sa.ToBuffer(buffer);
428 DK2BinarySerialFormat sb;
429 bool success = sb.FromBuffer(buffer);
430 OVR_ASSERT(success);
431 OVR_UNUSED(success);
433 OVR_ASSERT(sa == sb);
435 DK2PrintedSerialFormat psn;
436 psn.FromBinary(sb);
438 OVR_ASSERT(psn == sa);
440 String s = psn.ToBase32();
442 DK2PrintedSerialFormat psn2;
443 psn2.FromBase32(s.ToCStr());
445 OVR_ASSERT(psn == psn2);
446 }
448 #endif // SERIAL_FORMAT_UNIT_TEST
451 } // OVR