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