diff --git a/libs/bluetooth/bluetooth.h b/libs/bluetooth/bluetooth.h index 3bb531787b..2042481dcf 100644 --- a/libs/bluetooth/bluetooth.h +++ b/libs/bluetooth/bluetooth.h @@ -316,27 +316,39 @@ void jsble_setup_advdata(ble_advdata_t *advdata); #define TAG_HEADER_LEN 0x0A -#define NDEF_HEADER "\x00\x00\x00\x00" /* | UID/BCC | TT = Tag Type */ \ - "\x00\x00\x00\x00" /* | UID/BCC | ML = NDEF Message Length */ \ - "\x00\x00\xFF\xFF" /* | UID/BCC | LOCK | TF = TNF and Flags */ \ - "\xE1\x11\x7C\x0F" /* | Cap. Container | TL = Type Legnth */ \ - "\x03\x00\xC1\x01" /* | TT | ML | TF | TL | RT = Record Type */ \ - "\x00\x00\x00\x00" /* | Payload Length | IC = URI Identifier Code */ \ - "\x55\x00" /* | RT | IC | Payload | 0x00: No prepending */ - -#define NDEF_FULL_RAW_HEADER_LEN 0x12 /* full header until ML */ -#define NDEF_FULL_URL_HEADER_LEN 0x1A /* full header until IC */ - -#define NDEF_RECORD_HEADER_LEN 0x08 /* record header (TF, TL, PL, RT, IC ) */ -#define NDEF_IC_OFFSET 0x19 +/* +TT = Tag Type +ML = NDEF Message Length +RT = Record Type +TF = TNF and Flags +TL = Type Legnth +IC = URI Identifier Code +*/ + +#define NDEF_HEADER "\x00\x00\x00\x00" /* | UID/BCC | */ \ + "\x00\x00\x00\x00" /* | UID/BCC | */ \ + "\x00\x00\xFF\xFF" /* | UID/BCC | LOCK | */ \ + "\xE1\x11\x7C\x0F" /* | Cap. Container | */ \ + "\x03\x00\x00\x00" /* | TT | ML (1 or 3 bytes)| */ + +#define NDEF_HEADER_LEN_SHORT 0x12 /* with 1 byte length */ +#define NDEF_HEADER_LEN_LONG 0x14 /* with 3 byte length */ +#define NDEF_HEADER_MSG_LEN_OFFSET 0x11 + +#define NDEF_URL_RECORD_HEADER \ + "\xC1\x01" /* | TF | TL | */ \ + "\x00\x00\x00\x00" /* | Payload Length | */ \ + "\x55\x00" /* | RT | IC | 0x00: No prepending */ + +#define NDEF_URL_RECORD_HEADER_LEN 0x08 /* record header (TF, TL, PL, RT, IC ) */ #define NDEF_IC_LEN 0x01 -#define NDEF_MSG_LEN_OFFSET 0x11 -#define NDEF_PL_LEN_LSB_OFFSET 0x17 /* we support pl < 256 */ +#define NDEF_MSG_IC_OFFSET 7 +#define NDEF_MSG_PL_LEN_MSB_OFFSET 4 #define NDEF_TERM_TLV 0xfe /* last TLV block / byte */ #define NDEF_TERM_TLV_LEN 0x01 - +#define NDEF_TAG2_VALUE_MAXLEN (992 - 4 - NDEF_TERM_TLV_LEN) /* max NDEF data size for 0x7C size in cap. container (*8=992)*/ void jsble_nfc_stop(); void jsble_nfc_start(const uint8_t *data, size_t len); void jsble_nfc_get_internal(uint8_t *data, size_t *max_len); diff --git a/libs/bluetooth/jswrap_bluetooth.c b/libs/bluetooth/jswrap_bluetooth.c index 70a5ab9d77..7958758141 100644 --- a/libs/bluetooth/jswrap_bluetooth.c +++ b/libs/bluetooth/jswrap_bluetooth.c @@ -2391,6 +2391,51 @@ void jswrap_ble_setLowPowerConnection(bool lowPower) { } } +#ifdef USE_NFC +static void nfc_raw_data_start(uint8_t *dataPtr, size_t dataLen){ + /* Create a flat string - we need this to store the NFC data so it hangs around. + * Avoid having a static var so we have RAM available if not using NFC. + * NFC data is read by nfc_callback in bluetooth.c */ + bool isLongMsg = dataLen > 254; + size_t nfcDataLen = dataLen + NDEF_TERM_TLV_LEN + (isLongMsg ? NDEF_HEADER_LEN_LONG : NDEF_HEADER_LEN_SHORT); + + + JsVar *flatStr = jsvNewFlatStringOfLength(nfcDataLen); + if (!flatStr) + return jsExceptionHere(JSET_ERROR, "Unable to create string with NFC data in"); + jsvObjectSetChild(execInfo.hiddenRoot, "NfcData", flatStr); + uint8_t *flatStrPtr = (uint8_t*)jsvGetFlatStringPointer(flatStr); + jsvUnLock(flatStr); + +/* assemble NDEF Message */ + memcpy(flatStrPtr, NDEF_HEADER, NDEF_HEADER_LEN_LONG); /* fill header */ + /* inject tag2 message length into header */ + if (isLongMsg){ + flatStrPtr[NDEF_HEADER_MSG_LEN_OFFSET] = 255; + flatStrPtr[NDEF_HEADER_MSG_LEN_OFFSET+1] = dataLen >> 8; + flatStrPtr[NDEF_HEADER_MSG_LEN_OFFSET+2] = dataLen & 255; + } else { + flatStrPtr[NDEF_HEADER_MSG_LEN_OFFSET] = dataLen; + } + + /* add NDEF message record header after NDEF header */ + uint8_t *ndefMsgPtr = flatStrPtr + (isLongMsg ? NDEF_HEADER_LEN_LONG : NDEF_HEADER_LEN_SHORT); + memcpy(ndefMsgPtr, dataPtr, dataLen); /* add payload */ + + + /* write terminator TLV block */ + flatStrPtr[nfcDataLen - NDEF_TERM_TLV_LEN] = NDEF_TERM_TLV; + + /* start nfc peripheral */ + JsVar* uid = jswrap_nfc_start(NULL); + + /* inject UID/BCC */ + size_t len; + char *uidPtr = jsvGetDataPointer(uid, &len); + if(uidPtr) memcpy(flatStrPtr, uidPtr, TAG_HEADER_LEN); + jsvUnLock(uid); +} +#endif /*JSON{ "type" : "staticmethod", @@ -2437,36 +2482,21 @@ void jswrap_nfc_URL(JsVar *url) { uriType = NFC_URI_HTTPS; } - /* Encode NDEF message into a flat string - we need this to store the - * data so it hangs around. Avoid having a static var so we have RAM - * available if not using NFC. NFC data is read by nfc_callback */ - JsVar *flatStr = jsvNewFlatStringOfLength(NDEF_FULL_URL_HEADER_LEN + urlLen + NDEF_TERM_TLV_LEN); - if (!flatStr) - return jsExceptionHere(JSET_ERROR, "Unable to create string with URI data in"); - jsvObjectSetChild(execInfo.hiddenRoot, "NfcData", flatStr); - uint8_t *flatStrPtr = (uint8_t*)jsvGetFlatStringPointer(flatStr); - jsvUnLock(flatStr); + uint16_t msgLen = NDEF_URL_RECORD_HEADER_LEN + urlLen; + if (msgLen>NDEF_TAG2_VALUE_MAXLEN) + return jsExceptionHere(JSET_ERROR, "URL too long"); - /* assemble NDEF Message */ - memcpy(flatStrPtr, NDEF_HEADER, NDEF_FULL_URL_HEADER_LEN); /* fill header */ - flatStrPtr[NDEF_IC_OFFSET] = uriType; /* set URI Identifier Code */ - memcpy(flatStrPtr+NDEF_FULL_URL_HEADER_LEN, urlPtr, urlLen); /* add payload */ + uint8_t *ndefMsgPtr = alloca(urlLen+NDEF_URL_RECORD_HEADER_LEN); + memcpy(ndefMsgPtr, NDEF_URL_RECORD_HEADER, NDEF_URL_RECORD_HEADER_LEN); /* fill header */ - /* inject length fields into header */ - flatStrPtr[NDEF_MSG_LEN_OFFSET] = NDEF_RECORD_HEADER_LEN + urlLen; - flatStrPtr[NDEF_PL_LEN_LSB_OFFSET] = NDEF_IC_LEN + urlLen; + ndefMsgPtr[NDEF_MSG_IC_OFFSET] = uriType; /* set URI Identifier Code */ + memcpy(ndefMsgPtr+NDEF_URL_RECORD_HEADER_LEN, urlPtr, urlLen); /* add payload */ - /* write terminator TLV block */ - flatStrPtr[NDEF_FULL_URL_HEADER_LEN + urlLen] = NDEF_TERM_TLV; - - /* start nfc peripheral */ - JsVar* uid = jswrap_nfc_start(NULL); + /* put 16 bit (big endian) payload length into record header */ + ndefMsgPtr[NDEF_MSG_PL_LEN_MSB_OFFSET] = (NDEF_IC_LEN + urlLen)>>8; + ndefMsgPtr[NDEF_MSG_PL_LEN_MSB_OFFSET+1] = (NDEF_IC_LEN + urlLen)&255; - /* inject UID/BCC */ - size_t len; - char *uidPtr = jsvGetDataPointer(uid, &len); - if(uidPtr) memcpy(flatStrPtr, uidPtr, TAG_HEADER_LEN); - jsvUnLock(uid); + nfc_raw_data_start(ndefMsgPtr, urlLen+NDEF_URL_RECORD_HEADER_LEN); #endif } @@ -2516,18 +2546,8 @@ void jswrap_nfc_pair(JsVar *key) { &ndef_msg_len); if (jsble_check_error(err_code)) return; - /* Encode NDEF message into a flat string - we need this to store the - * data so it hangs around. Avoid having a static var so we have RAM - * available if not using NFC. NFC data is read by nfc_callback */ + nfc_raw_data_start(buf, ndef_msg_len); - JsVar *flatStr = jsvNewFlatStringOfLength(ndef_msg_len); - if (!flatStr) - return jsExceptionHere(JSET_ERROR, "Unable to create string with pairing data in"); - uint8_t *flatStrPtr = (uint8_t*)jsvGetFlatStringPointer(flatStr); - memcpy(flatStrPtr, buf, ndef_msg_len); - - jswrap_nfc_raw(flatStr); - jsvUnLock(flatStr); #endif } @@ -2575,18 +2595,7 @@ void jswrap_nfc_androidApp(JsVar *appName) { &ndef_msg_len); if (jsble_check_error(err_code)) return; - /* Encode NDEF message into a flat string - we need this to store the - * data so it hangs around. Avoid having a static var so we have RAM - * available if not using NFC. NFC data is read by nfc_callback */ - - JsVar *flatStr = jsvNewFlatStringOfLength(ndef_msg_len); - if (!flatStr) - return jsExceptionHere(JSET_ERROR, "Unable to create string with pairing data in"); - uint8_t *flatStrPtr = (uint8_t*)jsvGetFlatStringPointer(flatStr); - memcpy(flatStrPtr, buf, ndef_msg_len); - - jswrap_nfc_raw(flatStr); - jsvUnLock(flatStr); + nfc_raw_data_start(buf, ndef_msg_len); #endif } @@ -2617,41 +2626,13 @@ void jswrap_nfc_raw(JsVar *payload) { } JSV_GET_AS_CHAR_ARRAY(dataPtr, dataLen, payload); - if (!dataPtr || !dataLen) + if (!dataPtr || !dataLen || dataLen>NDEF_TAG2_VALUE_MAXLEN) return jsExceptionHere(JSET_ERROR, "Unable to get NFC data"); - /* Create a flat string - we need this to store the NFC data so it hangs around. - * Avoid having a static var so we have RAM available if not using NFC. - * NFC data is read by nfc_callback in bluetooth.c */ - JsVar *flatStr = jsvNewFlatStringOfLength(NDEF_FULL_RAW_HEADER_LEN + dataLen + NDEF_TERM_TLV_LEN); - if (!flatStr) - return jsExceptionHere(JSET_ERROR, "Unable to create string with NFC data in"); - jsvObjectSetChild(execInfo.hiddenRoot, "NfcData", flatStr); - uint8_t *flatStrPtr = (uint8_t*)jsvGetFlatStringPointer(flatStr); - jsvUnLock(flatStr); - - /* assemble NDEF Message */ - memcpy(flatStrPtr, NDEF_HEADER, NDEF_FULL_RAW_HEADER_LEN); /* fill header */ - memcpy(flatStrPtr+NDEF_FULL_RAW_HEADER_LEN, dataPtr, dataLen); /* add payload */ - - /* inject length fields into header */ - flatStrPtr[NDEF_MSG_LEN_OFFSET] = dataLen; - - /* write terminator TLV block */ - flatStrPtr[NDEF_FULL_RAW_HEADER_LEN + dataLen] = NDEF_TERM_TLV; - - /* start nfc peripheral */ - JsVar* uid = jswrap_nfc_start(NULL); - - /* inject UID/BCC */ - size_t len; - char *uidPtr = jsvGetDataPointer(uid, &len); - if(uidPtr) memcpy(flatStrPtr, uidPtr, TAG_HEADER_LEN); - jsvUnLock(uid); + nfc_raw_data_start((uint8_t*)dataPtr, dataLen); #endif } - /*JSON{ "type" : "staticmethod", "class" : "NRF",