Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,435 @@
/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright © 2013, Deutsche Telekom, Inc. */
/* globals MozNDEFRecord, NDEF, NfcUtils, NfcBuffer */
/* exported NDEFUtils */
'use strict';
/*******************************************************************************
* NDEFUtils offers a set of utility functions to handle NDEF messages
* according to NFCForum-TS-NDEF_1.0. It exports the following functions:
*
* - parseHandoverNDEF: parse a NDEF message that represents a handover request
* or a handover select message
* - searchForBluetoothAC: search for a Bluetooth Alternate Carrier in a
* handover NDEF message
* - parseBluetoothSSP: Parses a Carrier Data Record that contains a
* Bluetooth Secure Simple Pairing record
* - encodeHandoverRequest: returns a NDEF message that contains a handover
* request message
* - encodeHandoverSelect: returns a NDEF message that contains a handover
* select message
*/
var NDEFUtils = {
DEBUG: false,
/*****************************************************************************
*****************************************************************************
* Utility functions/classes
*****************************************************************************
****************************************************************************/
/**
* Debug method
*/
_debug: function _debug(msg, optObject) {
if (this.DEBUG) {
this._logVisibly(msg, optObject);
}
},
_logVisibly: function _logVisibly(msg, optObject) {
var output = '[NDEFUtils]: ' + msg;
if (optObject) {
output += JSON.stringify(optObject);
}
console.log(output);
},
/**
* Parse Handover Request NDEF message. Only 'Hr' and 'Hs' records
* are supported (NFCForum-TS-ConnectionHandover_1_2.doc).
*
* Returns handover object similar to:
* {
* majorVersion: 1,
* minorVersion: 2,
* type: 'Hr' // or 'Hs'
* cr: 123 // 'Hr' only
* ac: [ // Array of BT OOB records
* {
* cps: 1,
* cdr: ... // MozNDEFRecord with details, i.e.
* }, // Bluetooth MAC address.
* ...
* ]
* }
*
* @param {Array} ndefMsg NDEF message (array of MozNDEFRecords)
* @return {Object} Parsed handover request or null if ndefMsg
* was not valid or well formatted.
*/
parseHandoverNDEF: function parseHandoverNDEF(ndefMsg) {
try {
return this._doParseHandoverNDEF(ndefMsg);
} catch (err) {
this._logVisibly(err);
return null;
}
},
_doParseHandoverNDEF: function doParseHandoverNDEF(msg) {
var nfcUtils = new NfcUtils();
var hRecordBuffer = new NfcBuffer(msg[0].payload);
var version = hRecordBuffer.getOctet();
var h = {
majorVersion: version >>> 4,
minorVersion: version & 0x0f,
type: nfcUtils.toUTF8(msg[0].type),
ac: []
};
if (msg[0].tnf !== NDEF.TNF_WELL_KNOWN) {
throw Error('Expected Well Known TNF in Hs/Hr record');
}
if (['Hs', 'Hr'].indexOf(h.type) < 0) {
throw Error('Record "' + h.type + '" not supported.');
}
var hRecord = nfcUtils.parseNDEF(hRecordBuffer);
if (!hRecord) {
throw Error('Could not parse embedded NDEF in Hr/Hs record');
}
if (hRecordBuffer.offset < msg[0].payload.length) {
throw Error('Embedded NDEF payload contains extraneous bytes');
}
for (var i = 0; i < hRecord.length; i += 1) {
var type = nfcUtils.toUTF8(hRecord[i].type);
if ('ac' === type) {
h.ac.push(this._parseAlternativeCarrier(hRecord[i].payload, msg));
} else if ('cr' === type) {
h.cr = this._parseCollisionResolution(hRecord[i].payload);
}
}
// Make sure collision resolution record is present
// in Hr message.
if ('Hr' === h.type && !h.cr) {
throw Error('Collision resolution record missing');
}
return h;
},
_parseAlternativeCarrier: function _parseAlternativeCarrier(bytes, msg) {
var nfcUtils = new NfcUtils();
var b = new NfcBuffer(bytes);
var ac = {
cps: b.getOctet() & 0x03
};
var recordId = b.getOctetArray(b.getOctet());
ac.cdr = msg.filter(function(record) {
return nfcUtils.equalArrays(record.id, recordId);
}.bind(this))[0];
if (!ac.cdr) {
throw Error('Could not find record with given id');
}
return ac;
},
_parseCollisionResolution: function _parseCollisionResolution(bytes) {
if (bytes.length !== 2) {
throw Error('Expected random number in Collision Resolution Record');
}
return (bytes[0] << 8) | bytes[1];
},
/**
* Returns first record from handover message which
* contains Bluetooth OOB (Out of Band) data.
*
* @param {Array} h Handover message (array of records).
* @return {Object} MozNDEFRecord with Bluetooth OOB.
*/
searchForBluetoothAC: function searchForBluetoothAC(h) {
var nfcUtils = new NfcUtils();
for (var i = 0; i < h.ac.length; i++) {
var cdr = h.ac[i].cdr;
if (cdr.tnf === NDEF.TNF_MIME_MEDIA) {
if (nfcUtils.equalArrays(cdr.type, NDEF.MIME_BLUETOOTH_OOB)) {
return cdr;
}
}
}
return null;
},
/**
* Parses a Carrier Data Record according to NFCForum-AD-BTSSP_1.0.
* This method will parse MAC address. In addition to that, it will
* parse, if found in EIR data, Bluetooth Local Name. Other EIR fields
* are currently unsupported.
*
* @param {Object} cdr Carrier Data Record. It's payload field should
* contain Bluetooth OOB data.
* @returns {Object} Parsed record. Will always contain 'mac' property.
* If BT local name was present in cdr, will also have
* 'localName' property. Null if cdr was invalid.
*/
parseBluetoothSSP: function parseBluetoothSSP(cdr) {
var nfcUtils = new NfcUtils();
if (!cdr || !cdr.payload || cdr.payload.length < 8) {
return null;
}
var btssp = {};
var buf = new NfcBuffer(cdr.payload);
var btsspLen = buf.getOctet() | (buf.getOctet() << 8);
if (cdr.payload.length !== btsspLen) {
this._debug('Invalid BT SSP record. Length indicated:' +
btsspLen + ', actual length: ' + cdr.payload.length);
return null;
}
btssp.mac = this.formatMAC(buf.getOctetArray(6));
while (buf.offset != cdr.payload.length) {
// Read OOB value
var len = buf.getOctet() - 1 /* 'len' */;
var type = buf.getOctet();
if (buf.offset + len > buf.uint8array.length) {
this._debug('EIR field ' + type + ' indicated length=' +
len + ', but only ' + (buf.uint8array.length - buf.offset) +
' characters left in buffer.');
return null;
}
switch (type) {
case 0x08:
case 0x09:
// Local name
var n = buf.getOctetArray(len);
btssp.localName = nfcUtils.toUTF8(n);
break;
default:
// Ignore OOB value
buf.skip(len);
break;
}
}
return btssp;
},
/**
* Formats MAC address as a MAC-48 string (colon-separated).
*
* @param {Array} Array of six numbers representing MAC.
* @returns {String} MAC address.
*/
formatMAC: function formatMAC(mac) {
if (!mac || mac.length !== 6) {
return null;
}
var res = [];
for (var i = 0; i < 6; i += 1) {
var m = mac[i].toString(16);
res.unshift(m.length === 1 ? '0' + m : m);
}
return res.join(':').toUpperCase();
},
/**
* Parses Bluetooth MAC-48 address.
*
* @param {String} MAC address.
* @returns {Array} Array of six numbers representing MAC or null
* if it was not valid.
*/
parseMAC: function parseMAC(mac) {
if (!mac || !/^([0-9A-F]{2}:){6}$/i.test(mac + ':')) {
return null;
}
var macVals = mac.split(':');
var m = [];
for (var i = 5; i >= 0; i -= 1) {
m.push(parseInt(macVals[i], 16));
}
return m;
},
/**
* According to [CH] (Connection Handover Technical Specification),
* CPS can be one of the following:
* - 0 - Inactive
* - 1 - Active
* - 2 - Activating
* - 3 - Unknown
*
* @params {Integer} cps Carrier Power State
* @returns {Boolean} True when cps valid. False otherwise.
*/
validateCPS: function validateCPS(cps) {
var allowedValues = [NDEF.CPS_INACTIVE, NDEF.CPS_ACTIVE,
NDEF.CPS_ACTIVATING, NDEF.CPS_UNKNOWN];
return (allowedValues.indexOf(cps) >= 0);
},
/**
* Returns a Bluetooth Handover Request message. This method DOES
* NOT implement a full set of arguments as defined in
* NFCForum-AD-BTSSP_1.0.1.
*
* First record is a Handover Request Record (type="Hr"). It
* contains CPS and 2-byte random value used for collision detection
* (autogenerated).
*
* Second record contains Bluetooth OOB data. For explanation,
* @see encodeHandoverSelect() and specification.
*
* @param {String} mac MAC address, ie.: "01:23:45:67:89:AB".
* @param {Integer} cps Carrier Power State.
* @returns {Array} NDEF records for handover select message.
*
*/
encodeHandoverRequest: function encodeHandoverRequest(mac, cps) {
var nfcUtils = new NfcUtils();
var m = this.parseMAC(mac);
if (!m) {
this._debug('Invalid BT MAC address: ' + mac);
return null;
}
if (!this.validateCPS(cps)) {
this._debug('Invalid CPS: ' + cps);
return null;
}
var rndMSB = Math.floor(Math.random() * 0xff) & 0xff;
var rndLSB = Math.floor(Math.random() * 0xff) & 0xff;
var OOBLength = 2 + m.length;
var OOB = [OOBLength, 0].concat(m);
// Payload ID
var pid = nfcUtils.fromUTF8('0');
var hr = [
new MozNDEFRecord({tnf: NDEF.TNF_WELL_KNOWN,
type: NDEF.RTD_HANDOVER_REQUEST,
payload: new Uint8Array([0x12, 0x91, 0x02, 0x02, 0x63,
0x72, rndMSB, rndLSB, 0x51, 0x02, 0x04, 0x61, 0x63,
cps, 0x01, pid[0], 0x00])}),
new MozNDEFRecord({tnf: NDEF.TNF_MIME_MEDIA,
type: NDEF.MIME_BLUETOOTH_OOB,
id: pid,
payload: new Uint8Array(OOB)})];
return hr;
},
/**
* Returns a Bluetooth Handover Select message. This method
* DOES NOT implement the full spec as defined in
* NFCForum-AD-BTSSP_1.0.1. In particular, this method supports
* only Bluetooth device MAC address and Local Name in the Bluetooth
* Carrier Configuration Record.
*
* First record is Handover Select Record (type="Hs"). It contains,
* among other things, the CPS (Carrier Power State).
*
* Second record of this message contains Bluetooth Out of Band (OOB) data.
* It contains following fields:
* - [2 octets] OOB Data Length - Mandatory. Total length of OOB data,
* including this field itself.
* - [6 octets] BT Device Address - Mandatory. BT device address (MAC).
* - [N octets] OOB Optional Data - The remaining data in EIR format.
* This method supports only device name
* here.
*
* EIR data, as of this implementation, is optional. It will be ommited
* if you do not pass btDeviceName parameter. If you do, OOB Optional
* Data will be in a form:
* - [1 octet] EIR Data Length - Does not include this field.
* - [1 octet] EIR Data Type - only 0x09 (BT Local Name) supported.
* - [N octets] Contents - BT Local Name
*
* @param {String} mac MAC address, ie.: "01:23:45:67:89:AB".
* @param {Integer} cps Carrier Power State.
* @param {UInt8Array} btDeviceName Optional, user-friendly name
* of Bluetooth device.
* @returns {Array} NDEF records for handover select message.
*
*/
encodeHandoverSelect: function encodeHandoverSelect(mac, cps, btDeviceName) {
var nfcUtils = new NfcUtils();
var m = this.parseMAC(mac);
if (!m) {
this._debug('Invalid BT MAC address: ' + mac);
return null;
}
if (!this.validateCPS(cps)) {
this._debug('Invalid CPS: ' + cps);
return null;
}
// OOB Data Length
var OOBLength = 2 + m.length;
// OOB = [Data Length | BT Device Address]
var OOB = [OOBLength, 0].concat(m);
// If btDeviceName supplied, attach EIR with it as OOB Optional Data
// and update OOB Data Length accordingly.
if (btDeviceName) {
var EIRLength = 1 + btDeviceName.length;
OOB[0] += EIRLength + 1;
OOB = OOB.concat(EIRLength, 0x09, Array.apply([], btDeviceName));
}
// Payload ID
var pid = nfcUtils.fromUTF8('0');
var hs = [new MozNDEFRecord({tnf: NDEF.TNF_WELL_KNOWN,
type: NDEF.RTD_HANDOVER_SELECT,
payload: new Uint8Array(
[0x12, 0xD1, 0x02, 0x04, 0x61, 0x63, cps,
0x01, pid[0], 0x00])}),
new MozNDEFRecord({tnf: NDEF.TNF_MIME_MEDIA,
type: NDEF.MIME_BLUETOOTH_OOB,
id: pid,
payload: new Uint8Array(OOB)})];
return hs;
},
/**
* Returns an empty Handover Select NDEF message (i.e., a Hs message with no
* AC).
* @returns {Array} NDEF records for an empty handover select message.
*/
encodeEmptyHandoverSelect: function encodeEmptyHandoverSelect() {
var hs = [new MozNDEFRecord({tnf: NDEF.TNF_WELL_KNOWN,
type: NDEF.RTD_HANDOVER_SELECT,
payload: new Uint8Array([0x12])})];
return hs;
}
};