ovr_sdk

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