From 6e9e6262c65ad64c87bc67700af3522a3f47cfcb Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Wed, 12 Jul 2023 01:53:27 +0200 Subject: [PATCH] Refactor NFC Maker with proper NDEF logic Also fixes wifi not working in some cases --- .../nfc_maker/scenes/nfc_maker_scene_result.c | 324 +++++++++--------- 1 file changed, 157 insertions(+), 167 deletions(-) diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c index 38ad1e634..70cb664ba 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c @@ -61,221 +61,168 @@ void nfc_maker_scene_result_on_enter(void* context) { buf[i++] = 0x48; // Internal buf[i++] = 0x00; // Lock bytes buf[i++] = 0x00; // ... + buf[i++] = 0xE1; // Capability container buf[i++] = 0x10; // ... buf[i++] = 0x3E; // ... buf[i++] = 0x00; // ... - buf[i++] = 0x03; // Message flags - size_t start = i++; + buf[i++] = 0x03; // Container flags + + // NDEF Docs: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/nfc/index.html#nfc-data-exchange-format-ndef + uint8_t tnf = 0x00; + const char* type = ""; + uint8_t* payload = NULL; + size_t payload_len = 0; + + size_t data_len = 0; + size_t j = 0; switch(scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneMenu)) { case NfcMakerSceneBluetooth: { - buf[i++] = 0xD2; - buf[i++] = 0x20; - buf[i++] = 0x08; - buf[i++] = 0x61; - buf[i++] = 0x70; + tnf = 0x02; // Media-type [RFC 2046] + type = "application/vnd.bluetooth.ep.oob"; - buf[i++] = 0x70; - buf[i++] = 0x6C; - buf[i++] = 0x69; - buf[i++] = 0x63; + data_len = GAP_MAC_ADDR_SIZE; + payload_len = data_len + 2; + payload = malloc(payload_len); - buf[i++] = 0x61; - buf[i++] = 0x74; - buf[i++] = 0x69; - buf[i++] = 0x6F; - - buf[i++] = 0x6E; - buf[i++] = 0x2F; - buf[i++] = 0x76; - buf[i++] = 0x6E; - - buf[i++] = 0x64; - buf[i++] = 0x2E; - buf[i++] = 0x62; - buf[i++] = 0x6C; - - buf[i++] = 0x75; - buf[i++] = 0x65; - buf[i++] = 0x74; - buf[i++] = 0x6F; - - buf[i++] = 0x6F; - buf[i++] = 0x74; - buf[i++] = 0x68; - buf[i++] = 0x2E; - - buf[i++] = 0x65; - buf[i++] = 0x70; - buf[i++] = 0x2E; - buf[i++] = 0x6F; - - buf[i++] = 0x6F; - buf[i++] = 0x62; - buf[i++] = 0x08; - buf[i++] = 0x00; - - memcpy(&buf[i], app->mac_buf, GAP_MAC_ADDR_SIZE); - i += GAP_MAC_ADDR_SIZE; + payload[j++] = 0x08; + payload[j++] = 0x00; + memcpy(&payload[j], app->mac_buf, data_len); + j += data_len; break; } case NfcMakerSceneHttps: { - uint8_t data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + tnf = 0x01; // NFC Forum well-known type [NFC RTD] + type = "\x55"; - buf[i++] = 0xD1; - buf[i++] = 0x01; - buf[i++] = data_len + 1; - buf[i++] = 0x55; + data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + payload_len = data_len + 1; + payload = malloc(payload_len); - buf[i++] = 0x04; // Prepend "https://" - memcpy(&buf[i], app->text_buf, data_len); - i += data_len; + payload[j++] = 0x04; // Prepend "https://" + memcpy(&payload[j], app->text_buf, data_len); + j += data_len; break; } case NfcMakerSceneMail: { - uint8_t data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + tnf = 0x01; // NFC Forum well-known type [NFC RTD] + type = "\x55"; - buf[i++] = 0xD1; - buf[i++] = 0x01; - buf[i++] = data_len + 1; - buf[i++] = 0x55; + data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + payload_len = data_len + 1; + payload = malloc(payload_len); - buf[i++] = 0x06; // Prepend "mailto:" - memcpy(&buf[i], app->text_buf, data_len); - i += data_len; + payload[j++] = 0x06; // Prepend "mailto:" + memcpy(&payload[j], app->text_buf, data_len); + j += data_len; break; } case NfcMakerScenePhone: { - uint8_t data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + tnf = 0x01; // NFC Forum well-known type [NFC RTD] + type = "\x55"; - buf[i++] = 0xD1; - buf[i++] = 0x01; - buf[i++] = data_len + 1; - buf[i++] = 0x55; + data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + payload_len = data_len + 1; + payload = malloc(payload_len); - buf[i++] = 0x05; // Prepend "tel:" - memcpy(&buf[i], app->text_buf, data_len); - i += data_len; + payload[j++] = 0x05; // Prepend "tel:" + memcpy(&payload[j], app->text_buf, data_len); + j += data_len; break; } case NfcMakerSceneText: { - uint8_t data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + tnf = 0x01; // NFC Forum well-known type [NFC RTD] + type = "\x54"; - buf[i++] = 0xD1; - buf[i++] = 0x01; - buf[i++] = data_len + 3; - buf[i++] = 0x54; + data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + payload_len = data_len + 3; + payload = malloc(payload_len); - buf[i++] = 0x02; - buf[i++] = 0x65; // e - buf[i++] = 0x6E; // n - memcpy(&buf[i], app->text_buf, data_len); - i += data_len; + payload[j++] = 0x02; + payload[j++] = 0x65; // e + payload[j++] = 0x6E; // n + memcpy(&payload[j], app->text_buf, data_len); + j += data_len; break; } case NfcMakerSceneUrl: { - uint8_t data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + tnf = 0x01; // NFC Forum well-known type [NFC RTD] + type = "\x55"; - buf[i++] = 0xD1; - buf[i++] = 0x01; - buf[i++] = data_len + 1; - buf[i++] = 0x55; + data_len = strnlen(app->text_buf, TEXT_INPUT_LEN); + payload_len = data_len + 1; + payload = malloc(payload_len); - buf[i++] = 0x00; // No prepend - memcpy(&buf[i], app->text_buf, data_len); - i += data_len; + payload[j++] = 0x00; // No prepend + memcpy(&payload[j], app->text_buf, data_len); + j += data_len; break; } case NfcMakerSceneWifi: { + tnf = 0x02; // Media-type [RFC 2046] + type = "application/vnd.wfa.wsc"; + uint8_t ssid_len = strnlen(app->text_buf, WIFI_INPUT_LEN); uint8_t pass_len = strnlen(app->pass_buf, WIFI_INPUT_LEN); uint8_t data_len = ssid_len + pass_len; + payload_len = data_len + 39; + payload = malloc(payload_len); - buf[i++] = 0xD2; - buf[i++] = 0x17; - buf[i++] = data_len + 47; - buf[i++] = 0x61; - buf[i++] = 0x70; + payload[j++] = 0x10; + payload[j++] = 0x0E; + payload[j++] = 0x00; - buf[i++] = 0x70; - buf[i++] = 0x6C; - buf[i++] = 0x69; - buf[i++] = 0x63; + payload[j++] = data_len + 43; + payload[j++] = 0x10; + payload[j++] = 0x26; + payload[j++] = 0x00; - buf[i++] = 0x61; - buf[i++] = 0x74; - buf[i++] = 0x69; - buf[i++] = 0x6F; + payload[j++] = 0x01; + payload[j++] = 0x01; + payload[j++] = 0x10; + payload[j++] = 0x45; - buf[i++] = 0x6E; - buf[i++] = 0x2F; - buf[i++] = 0x76; - buf[i++] = 0x6E; + payload[j++] = 0x00; + payload[j++] = ssid_len; + memcpy(&payload[j], app->text_buf, ssid_len); + j += ssid_len; + payload[j++] = 0x10; + payload[j++] = 0x03; - buf[i++] = 0x64; - buf[i++] = 0x2E; - buf[i++] = 0x77; - buf[i++] = 0x66; + payload[j++] = 0x00; + payload[j++] = 0x02; + payload[j++] = 0x00; + payload[j++] = + scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiAuth); - buf[i++] = 0x61; - buf[i++] = 0x2E; - buf[i++] = 0x77; - buf[i++] = 0x73; + payload[j++] = 0x10; + payload[j++] = 0x0F; + payload[j++] = 0x00; + payload[j++] = 0x02; - buf[i++] = 0x63; - buf[i++] = 0x10; - buf[i++] = 0x0E; - buf[i++] = 0x00; + payload[j++] = 0x00; + payload[j++] = + scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiEncr); + payload[j++] = 0x10; + payload[j++] = 0x27; - buf[i++] = data_len + 43; - buf[i++] = 0x10; - buf[i++] = 0x26; - buf[i++] = 0x00; + payload[j++] = 0x00; + payload[j++] = pass_len; + memcpy(&payload[j], app->pass_buf, pass_len); + j += pass_len; + payload[j++] = 0x10; + payload[j++] = 0x20; - buf[i++] = 0x01; - buf[i++] = 0x01; - buf[i++] = 0x10; - buf[i++] = 0x45; + payload[j++] = 0x00; + payload[j++] = 0x06; + payload[j++] = 0xFF; + payload[j++] = 0xFF; - buf[i++] = 0x00; - buf[i++] = ssid_len; - memcpy(&buf[i], app->text_buf, ssid_len); - i += ssid_len; - buf[i++] = 0x10; - buf[i++] = 0x03; - - buf[i++] = 0x00; - buf[i++] = 0x02; - buf[i++] = 0x00; - buf[i++] = scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiAuth); - - buf[i++] = 0x10; - buf[i++] = 0x0F; - buf[i++] = 0x00; - buf[i++] = 0x02; - - buf[i++] = 0x00; - buf[i++] = scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiEncr); - buf[i++] = 0x10; - buf[i++] = 0x27; - - buf[i++] = 0x00; - buf[i++] = pass_len; - memcpy(&buf[i], app->pass_buf, pass_len); - i += pass_len; - buf[i++] = 0x10; - buf[i++] = 0x20; - - buf[i++] = 0x00; - buf[i++] = 0x06; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; + payload[j++] = 0xFF; + payload[j++] = 0xFF; + payload[j++] = 0xFF; + payload[j++] = 0xFF; break; } @@ -283,8 +230,51 @@ void nfc_maker_scene_result_on_enter(void* context) { break; } - // Message length and terminator - buf[start] = i - start - 1; + // Record header + uint8_t flags = 0; + flags |= 1 << 7; // MB (Message Begin) + flags |= 1 << 6; // ME (Message End) + flags |= tnf; // TNF (Type Name Format) + size_t type_len = strlen(type); + + size_t header_len = 0; + header_len += 1; // Flags and TNF + header_len += 1; // Type length + if(payload_len < 0xFF) { + flags |= 1 << 4; // SR (Short Record) + header_len += 1; // Payload length + } else { + header_len += 4; // Payload length + } + header_len += type_len; // Payload type + + size_t record_len = header_len + payload_len; + if(record_len < 0xFF) { + buf[i++] = record_len; // Record length + } else { + buf[i++] = 0xFF; // Record length + buf[i++] = record_len >> 8; // ... + buf[i++] = record_len & 0xFF; // ... + } + buf[i++] = flags; // Flags and TNF + buf[i++] = type_len; // Type length + if(flags & 1 << 4) { // SR (Short Record) + buf[i++] = payload_len; // Payload length + } else { + buf[i++] = 0x00; // Payload length + buf[i++] = 0x00; // ... + buf[i++] = payload_len >> 8; // ... + buf[i++] = payload_len & 0xFF; // ... + } + memcpy(&buf[i], type, type_len); // Payload type + i += type_len; + + // Record payload + memcpy(&buf[i], payload, payload_len); + i += payload_len; + free(payload); + + // Record terminator buf[i++] = 0xFE; // Padding until last 5 pages