ovr_sdk
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/OVR_SerialFormat.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,451 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_System.cpp 1.7 +Content : General kernel initialization/cleanup, including that 1.8 + of the memory allocator. 1.9 +Created : September 19, 2012 1.10 +Notes : 1.11 + 1.12 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.13 + 1.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.16 +which is provided at the time of installation or download, or which 1.17 +otherwise accompanies this software in either electronic or hard copy form. 1.18 + 1.19 +You may obtain a copy of the License at 1.20 + 1.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.22 + 1.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.24 +distributed under the License is distributed on an "AS IS" BASIS, 1.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.26 +See the License for the specific language governing permissions and 1.27 +limitations under the License. 1.28 + 1.29 +************************************************************************************/ 1.30 + 1.31 +#include "OVR_SerialFormat.h" 1.32 + 1.33 +#ifdef SERIAL_FORMAT_UNIT_TEST 1.34 +#include "Kernel/OVR_Log.h" 1.35 +#endif 1.36 + 1.37 +namespace OVR { 1.38 + 1.39 + 1.40 +//// Serial Format Detection 1.41 + 1.42 +SerialFormatType DetectBufferFormat(uint8_t firstByte, int sizeInBytes) 1.43 +{ 1.44 + switch (firstByte) 1.45 + { 1.46 + case SerialFormatType_DK2: 1.47 + if (sizeInBytes == 12) 1.48 + { 1.49 + return SerialFormatType_DK2; 1.50 + } 1.51 + break; 1.52 + default: 1.53 + break; 1.54 + } 1.55 + 1.56 + return SerialFormatType_Invalid; 1.57 +} 1.58 + 1.59 + 1.60 +//// DK2 Helpers 1.61 + 1.62 +static bool ValidDK2ProductId(int x) 1.63 +{ 1.64 + switch (x) 1.65 + { 1.66 + case DK2ProductId_DK1: 1.67 + case DK2ProductId_DK2: 1.68 + case DK2ProductId_Refurb: 1.69 + return true; 1.70 + default: 1.71 + break; 1.72 + } 1.73 + 1.74 + return false; 1.75 +} 1.76 + 1.77 +static bool ValidDK2PartId(int x) 1.78 +{ 1.79 + switch (x) 1.80 + { 1.81 + case DK2PartId_HMD: 1.82 + case DK2PartId_PTC: 1.83 + case DK2PartId_Carton: 1.84 + return true; 1.85 + default: 1.86 + break; 1.87 + } 1.88 + 1.89 + return false; 1.90 +} 1.91 + 1.92 + 1.93 +//// DK2BinarySerialFormat 1.94 + 1.95 +bool DK2BinarySerialFormat::FromBuffer(const uint8_t buffer[12], bool allowUnknownTypes) 1.96 +{ 1.97 + // Format Type must be 0 1.98 + 1.99 + int formatType = buffer[0]; 1.100 + 1.101 + if (formatType != SerialFormatType_DK2) 1.102 + { 1.103 + return false; 1.104 + } 1.105 + 1.106 + // Product Id 1.107 + 1.108 + int productId = buffer[1] >> 4; 1.109 + 1.110 + if (!allowUnknownTypes && !ValidDK2ProductId(productId)) 1.111 + { 1.112 + return false; 1.113 + } 1.114 + 1.115 + ProductId = (DK2ProductId)productId; 1.116 + 1.117 + // Part Id 1.118 + 1.119 + int partId = buffer[1] & 15; 1.120 + 1.121 + if (!allowUnknownTypes && !ValidDK2PartId(partId)) 1.122 + { 1.123 + return false; 1.124 + } 1.125 + 1.126 + PartId = (DK2PartId)partId; 1.127 + 1.128 + // Minutes Since Epoch (May 1, 2014) 1.129 + 1.130 + MinutesSinceEpoch = buffer[4] | ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16); 1.131 + 1.132 + // Unit number on that day 1.133 + 1.134 + UnitNumber = buffer[6] | ((uint32_t)buffer[5] << 8); 1.135 + 1.136 + // Hash of MAC address 1.137 + 1.138 + MacHash[0] = buffer[7]; 1.139 + MacHash[1] = buffer[8]; 1.140 + MacHash[2] = buffer[9]; 1.141 + MacHash[3] = buffer[10]; 1.142 + MacHash[4] = buffer[11]; 1.143 + 1.144 + return true; 1.145 +} 1.146 + 1.147 +void DK2BinarySerialFormat::ToBuffer(uint8_t buffer[12]) 1.148 +{ 1.149 + // Serialize to buffer 1.150 + buffer[0] = SerialFormatType_DK2; 1.151 + buffer[1] = (uint8_t)((ProductId << 4) | (PartId)); 1.152 + buffer[2] = (uint8_t)(MinutesSinceEpoch >> 16); 1.153 + buffer[3] = (uint8_t)(MinutesSinceEpoch >> 8); 1.154 + buffer[4] = (uint8_t)MinutesSinceEpoch; 1.155 + buffer[5] = (uint8_t)(UnitNumber >> 8); 1.156 + buffer[6] = (uint8_t)UnitNumber; 1.157 + 1.158 + buffer[7] = MacHash[0]; 1.159 + buffer[8] = MacHash[1]; 1.160 + buffer[9] = MacHash[2]; 1.161 + buffer[10] = MacHash[3]; 1.162 + buffer[11] = MacHash[4]; 1.163 +} 1.164 + 1.165 +bool DK2BinarySerialFormat::operator==(const DK2BinarySerialFormat& rhs) 1.166 +{ 1.167 + if (ProductId != rhs.ProductId) 1.168 + return false; 1.169 + if (PartId != rhs.PartId) 1.170 + return false; 1.171 + if (MinutesSinceEpoch != rhs.MinutesSinceEpoch) 1.172 + return false; 1.173 + if (UnitNumber != rhs.UnitNumber) 1.174 + return false; 1.175 + for (int ii = 0; ii < 5; ++ii) 1.176 + { 1.177 + if (MacHash[ii] != rhs.MacHash[ii]) 1.178 + return false; 1.179 + } 1.180 + return true; 1.181 +} 1.182 + 1.183 + 1.184 +//// DK2PrintedSerialFormat 1.185 + 1.186 +// Base-32 Crockford decoding rules: 1.187 +// 0 o O => 0 1.188 +// 1 i | I L l => 1 1.189 +// 2, 3, 4, 5, 6, 7, 8, 9 => 2 - 9 1.190 +// a, b, c, d, e, f, g, h => 10 - 17 1.191 +// j, k => 18, 19 1.192 +// m, n => 20, 21 1.193 +// p, q, r, s, t => 22, 23, 24, 25, 26 1.194 +// v, w, x, y, z => 27, 28, 29, 30, 31 1.195 +static const char Base32FromChar[256] = { 1.196 + // Null - Unit Separator 1.197 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.198 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.199 + // (sp)!"#$%&'()*+,-./ 1.200 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.201 + // 0123456789:;<=>? 1.202 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 1.203 + // @ - _ (upper case) 1.204 + -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0, 1.205 + 22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, 1.206 + // ` - DEL (lower case) 1.207 + -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0, 1.208 + 22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1, 1, -1, -1, -1, 1.209 + 1.210 + // Extended ASCII: 1.211 + -1, -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, 1.213 + 1.214 + -1, -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, 1.216 + 1.217 + -1, -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, 1.219 + 1.220 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.221 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 1.222 +}; 1.223 + 1.224 +// Base-32 Crockford encoding rules: 1.225 +// 0-9 => 0-9 1.226 +// 10 - 17 => a, b, c, d, e, f, g, h 1.227 +// 18, 19 => j, k 1.228 +// 20, 21 => m, n 1.229 +// 22, 23, 24, 25, 26 => p, q, r, s, t 1.230 +// 27, 28, 29, 30, 31 => v, w, x, y, z 1.231 +static const char* CharFromBase32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; 1.232 + 1.233 +bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes) 1.234 +{ 1.235 + // Note: Truncated strings get caught by returning negative values from the table like other invalid characters 1.236 + 1.237 + // Product Id 1.238 + 1.239 + int productId = Base32FromChar[(unsigned char)str[0]]; 1.240 + if (productId < 0 || (!allowUnknownTypes && !ValidDK2ProductId(productId))) 1.241 + { 1.242 + return false; 1.243 + } 1.244 + 1.245 + ProductId = (DK2ProductId)productId; 1.246 + 1.247 + // Label Type 1.248 + 1.249 + int labelType = Base32FromChar[(unsigned char)str[1]]; 1.250 + if (labelType < 0 || (!allowUnknownTypes && !ValidDK2PartId(labelType))) 1.251 + { 1.252 + return false; 1.253 + } 1.254 + 1.255 + LabelType = (DK2LabelType)labelType; 1.256 + 1.257 + uint8_t dataBytes[7]; 1.258 + for (int ii = 0; ii < 7; ++ii) 1.259 + { 1.260 + int c = Base32FromChar[(unsigned char)str[2 + ii]]; 1.261 + if (c < 0) return false; 1.262 + dataBytes[ii] = (uint8_t)c; 1.263 + } 1.264 + 1.265 + // Minutes Since Epoch 1.266 + 1.267 + MinutesSinceEpoch = dataBytes[3] | ((uint32_t)dataBytes[2] << 5) | ((uint32_t)dataBytes[1] << 10) | ((uint32_t)dataBytes[0] << 15); 1.268 + 1.269 + // Unit Number 1.270 + 1.271 + UnitNumber = dataBytes[6] | ((uint32_t)dataBytes[5] << 5) | ((uint32_t)dataBytes[4] << 10); 1.272 + 1.273 + // MAC Hash 1.274 + 1.275 + for (int ii = 0; ii < 3; ++ii) 1.276 + { 1.277 + int c = Base32FromChar[(unsigned char)str[9 + ii]]; 1.278 + if (c < 0) 1.279 + { 1.280 + return false; 1.281 + } 1.282 + 1.283 + MacHashLow[ii] = (uint8_t)c; 1.284 + } 1.285 + 1.286 + // String must be exactly 12 characters 1.287 + if (str[12] != '\0') 1.288 + { 1.289 + return false; 1.290 + } 1.291 + 1.292 + return true; 1.293 +} 1.294 + 1.295 +String DK2PrintedSerialFormat::ToBase32() 1.296 +{ 1.297 + String s; 1.298 + 1.299 + s += CharFromBase32[ProductId]; 1.300 + s += CharFromBase32[LabelType]; 1.301 + s += CharFromBase32[(MinutesSinceEpoch >> 15) & 31]; 1.302 + s += CharFromBase32[(MinutesSinceEpoch >> 10) & 31]; 1.303 + s += CharFromBase32[(MinutesSinceEpoch >> 5) & 31]; 1.304 + s += CharFromBase32[MinutesSinceEpoch & 31]; 1.305 + s += CharFromBase32[(UnitNumber >> 10) & 31]; 1.306 + s += CharFromBase32[(UnitNumber >> 5) & 31]; 1.307 + s += CharFromBase32[UnitNumber & 31]; 1.308 + s += CharFromBase32[MacHashLow[0] & 31]; 1.309 + s += CharFromBase32[MacHashLow[1] & 31]; 1.310 + s += CharFromBase32[MacHashLow[2] & 31]; 1.311 + 1.312 + return s; 1.313 +} 1.314 + 1.315 +bool DK2PrintedSerialFormat::operator==(const DK2PrintedSerialFormat& rhs) 1.316 +{ 1.317 + if (ProductId != rhs.ProductId) 1.318 + return false; 1.319 + if (LabelType != rhs.LabelType) 1.320 + return false; 1.321 + if (MinutesSinceEpoch != rhs.MinutesSinceEpoch) 1.322 + return false; 1.323 + if (UnitNumber != rhs.UnitNumber) 1.324 + return false; 1.325 + for (int ii = 0; ii < 3; ++ii) 1.326 + { 1.327 + if (MacHashLow[ii] != rhs.MacHashLow[ii]) 1.328 + return false; 1.329 + } 1.330 + return true; 1.331 +} 1.332 + 1.333 +bool DK2PrintedSerialFormat::operator==(const DK2BinarySerialFormat& rhs) 1.334 +{ 1.335 + if (ProductId != rhs.ProductId) 1.336 + return false; 1.337 + if (LabelType != rhs.PartId) 1.338 + return false; 1.339 + if (MinutesSinceEpoch != rhs.MinutesSinceEpoch) 1.340 + return false; 1.341 + if (UnitNumber != rhs.UnitNumber) 1.342 + return false; 1.343 + for (int ii = 0; ii < 3; ++ii) 1.344 + { 1.345 + if (MacHashLow[ii] != (rhs.MacHash[ii] & 31)) 1.346 + return false; 1.347 + } 1.348 + return true; 1.349 +} 1.350 + 1.351 +void DK2PrintedSerialFormat::FromBinary(const DK2BinarySerialFormat& bin) 1.352 +{ 1.353 + ProductId = bin.ProductId; 1.354 + LabelType = bin.PartId; 1.355 + MinutesSinceEpoch = bin.MinutesSinceEpoch; 1.356 + UnitNumber = bin.UnitNumber; 1.357 + MacHashLow[0] = bin.MacHash[0] & 31; 1.358 + MacHashLow[1] = bin.MacHash[1] & 31; 1.359 + MacHashLow[2] = bin.MacHash[2] & 31; 1.360 +} 1.361 + 1.362 + 1.363 +//// Unit Tests 1.364 + 1.365 +#ifdef SERIAL_FORMAT_UNIT_TEST 1.366 + 1.367 +int DecodeBase32(char ch) 1.368 +{ 1.369 + if (ch >= '2' && ch <= '9') 1.370 + return 2 + ch - '2'; 1.371 + if (ch >= 'a' && ch <= 'h') 1.372 + return 10 + ch - 'a'; 1.373 + if (ch >= 'A' && ch <= 'H') 1.374 + return 10 + ch - 'A'; 1.375 + if (ch >= 'j' && ch <= 'k') 1.376 + return 18 + ch - 'j'; 1.377 + if (ch >= 'J' && ch <= 'K') 1.378 + return 18 + ch - 'J'; 1.379 + if (ch >= 'm' && ch <= 'n') 1.380 + return 20 + ch - 'm'; 1.381 + if (ch >= 'M' && ch <= 'N') 1.382 + return 20 + ch - 'M'; 1.383 + if (ch >= 'p' && ch <= 't') 1.384 + return 22 + ch - 'p'; 1.385 + if (ch >= 'P' && ch <= 'T') 1.386 + return 22 + ch - 'P'; 1.387 + if (ch >= 'v' && ch <= 'z') 1.388 + return 27 + ch - 'v'; 1.389 + if (ch >= 'V' && ch <= 'Z') 1.390 + return 27 + ch - 'V'; 1.391 + 1.392 + switch (ch) 1.393 + { 1.394 + case '0': 1.395 + case 'o': 1.396 + case 'O': 1.397 + return 0; 1.398 + case '1': 1.399 + case 'i': 1.400 + case '|': 1.401 + case 'I': 1.402 + case 'L': 1.403 + case 'l': 1.404 + return 1; 1.405 + } 1.406 + 1.407 + return -1; 1.408 +} 1.409 + 1.410 +void TestSerialFormatStuff() 1.411 +{ 1.412 + for (int ii = 0; ii < 256; ++ii) 1.413 + { 1.414 + OVR_ASSERT(Base32FromChar[ii] == (char)DecodeBase32((char)ii)); 1.415 + } 1.416 + 1.417 + DK2BinarySerialFormat sa; 1.418 + sa.ProductId = DK2ProductId_DK2; 1.419 + sa.PartId = DK2PartId_HMD; 1.420 + sa.MinutesSinceEpoch = 65000; 1.421 + sa.UnitNumber = 2; 1.422 + sa.MacHash[0] = 0xa1; 1.423 + sa.MacHash[1] = 0xb2; 1.424 + sa.MacHash[2] = 0xc3; 1.425 + sa.MacHash[3] = 0xd4; 1.426 + sa.MacHash[4] = 0xe5; 1.427 + 1.428 + uint8_t buffer[12]; 1.429 + sa.ToBuffer(buffer); 1.430 + 1.431 + DK2BinarySerialFormat sb; 1.432 + bool success = sb.FromBuffer(buffer); 1.433 + OVR_ASSERT(success); 1.434 + OVR_UNUSED(success); 1.435 + 1.436 + OVR_ASSERT(sa == sb); 1.437 + 1.438 + DK2PrintedSerialFormat psn; 1.439 + psn.FromBinary(sb); 1.440 + 1.441 + OVR_ASSERT(psn == sa); 1.442 + 1.443 + String s = psn.ToBase32(); 1.444 + 1.445 + DK2PrintedSerialFormat psn2; 1.446 + psn2.FromBase32(s.ToCStr()); 1.447 + 1.448 + OVR_ASSERT(psn == psn2); 1.449 +} 1.450 + 1.451 +#endif // SERIAL_FORMAT_UNIT_TEST 1.452 + 1.453 + 1.454 +} // OVR