@glassly/bluetooth-sdk 0.1.0-dev.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +563 -0
- package/android/build.gradle +450 -0
- package/android/gradle.properties.example +9 -0
- package/android/lc3Lib/CMakeLists.txt +6 -0
- package/android/lc3Lib/build.gradle +212 -0
- package/android/lc3Lib/proguard-rules.pro +33 -0
- package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
- package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
- package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
- package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
- package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
- package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
- package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
- package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
- package/android/settings.gradle +4 -0
- package/android/silero/LICENSE.md +17 -0
- package/android/silero/build.gradle +50 -0
- package/android/silero/proguard-rules.pro +24 -0
- package/android/silero/src/androidTest/assets/hello.wav +0 -0
- package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
- package/android/silero/src/main/assets/LICENSE +21 -0
- package/android/silero/src/main/assets/silero_vad.onnx +0 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
- package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
- package/android/src/main/AndroidManifest.xml +42 -0
- package/android/src/main/assets/G2Firmware/README.md +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
- package/android/src/test/resources/avif_with_exif.avif +0 -0
- package/app.plugin.js +3 -0
- package/build/BluetoothSdk.types.d.ts +1354 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -0
- package/build/BluetoothSdk.types.js +41 -0
- package/build/BluetoothSdk.types.js.map +1 -0
- package/build/_internal.d.ts +17 -0
- package/build/_internal.d.ts.map +1 -0
- package/build/_internal.js +16 -0
- package/build/_internal.js.map +1 -0
- package/build/_private/BluetoothSdkModule.d.ts +172 -0
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
- package/build/_private/BluetoothSdkModule.js +300 -0
- package/build/_private/BluetoothSdkModule.js.map +1 -0
- package/build/_private/LocalNetworkModule.d.ts +38 -0
- package/build/_private/LocalNetworkModule.d.ts.map +1 -0
- package/build/_private/LocalNetworkModule.js +3 -0
- package/build/_private/LocalNetworkModule.js.map +1 -0
- package/build/_private/cameraRequestPayload.d.ts +4 -0
- package/build/_private/cameraRequestPayload.d.ts.map +1 -0
- package/build/_private/cameraRequestPayload.js +32 -0
- package/build/_private/cameraRequestPayload.js.map +1 -0
- package/build/_private/photoRequestPayload.d.ts +6 -0
- package/build/_private/photoRequestPayload.d.ts.map +1 -0
- package/build/_private/photoRequestPayload.js +86 -0
- package/build/_private/photoRequestPayload.js.map +1 -0
- package/build/_private/sdkOtaManifest.d.ts +11 -0
- package/build/_private/sdkOtaManifest.d.ts.map +1 -0
- package/build/_private/sdkOtaManifest.js +15 -0
- package/build/_private/sdkOtaManifest.js.map +1 -0
- package/build/changelogs.d.ts +7 -0
- package/build/changelogs.d.ts.map +1 -0
- package/build/changelogs.js +46 -0
- package/build/changelogs.js.map +1 -0
- package/build/debug.d.ts +3 -0
- package/build/debug.d.ts.map +1 -0
- package/build/debug.js +8 -0
- package/build/debug.js.map +1 -0
- package/build/generated/changelogCatalog.d.ts +9 -0
- package/build/generated/changelogCatalog.d.ts.map +1 -0
- package/build/generated/changelogCatalog.js +12 -0
- package/build/generated/changelogCatalog.js.map +1 -0
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +6 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +171 -0
- package/build/index.js.map +1 -0
- package/build/ota-server/OtaServer.types.d.ts +14 -0
- package/build/ota-server/OtaServer.types.d.ts.map +1 -0
- package/build/ota-server/OtaServer.types.js +2 -0
- package/build/ota-server/OtaServer.types.js.map +1 -0
- package/build/ota-server/OtaServerModule.d.ts +21 -0
- package/build/ota-server/OtaServerModule.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.js +3 -0
- package/build/ota-server/OtaServerModule.js.map +1 -0
- package/build/ota-server/OtaServerModule.web.d.ts +10 -0
- package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.web.js +12 -0
- package/build/ota-server/OtaServerModule.web.js.map +1 -0
- package/build/ota-server/index.d.ts +3 -0
- package/build/ota-server/index.d.ts.map +1 -0
- package/build/ota-server/index.js +3 -0
- package/build/ota-server/index.js.map +1 -0
- package/build/ota-transport/index.d.ts +67 -0
- package/build/ota-transport/index.d.ts.map +1 -0
- package/build/ota-transport/index.js +58 -0
- package/build/ota-transport/index.js.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.js +2 -0
- package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.js +3 -0
- package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
- package/build/photo-receiver/index.d.ts +3 -0
- package/build/photo-receiver/index.d.ts.map +1 -0
- package/build/photo-receiver/index.js +3 -0
- package/build/photo-receiver/index.js.map +1 -0
- package/build/react/index.d.ts +5 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +4 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useBluetooth.d.ts +100 -0
- package/build/react/useBluetooth.d.ts.map +1 -0
- package/build/react/useBluetooth.js +167 -0
- package/build/react/useBluetooth.js.map +1 -0
- package/build/react/useBluetoothEvent.d.ts +6 -0
- package/build/react/useBluetoothEvent.d.ts.map +1 -0
- package/build/react/useBluetoothEvent.js +21 -0
- package/build/react/useBluetoothEvent.js.map +1 -0
- package/build/react/useBluetoothScan.d.ts +22 -0
- package/build/react/useBluetoothScan.d.ts.map +1 -0
- package/build/react/useBluetoothScan.js +135 -0
- package/build/react/useBluetoothScan.js.map +1 -0
- package/build/react/useBluetoothStatus.d.ts +16 -0
- package/build/react/useBluetoothStatus.d.ts.map +1 -0
- package/build/react/useBluetoothStatus.js +137 -0
- package/build/react/useBluetoothStatus.js.map +1 -0
- package/build/react/useGlassesConnection.d.ts +29 -0
- package/build/react/useGlassesConnection.d.ts.map +1 -0
- package/build/react/useGlassesConnection.js +153 -0
- package/build/react/useGlassesConnection.js.map +1 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/expo-module.config.json +14 -0
- package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
- package/ios/BluetoothSdkModule.swift +1034 -0
- package/ios/GlasslyBluetoothSDK.podspec +106 -0
- package/ios/LocalIPv4.swift +150 -0
- package/ios/LocalOtaServer.swift +309 -0
- package/ios/LocalPhotoUploadServer.swift +754 -0
- package/ios/OtaServerModule.swift +147 -0
- package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
- package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
- package/ios/Packages/CoreObjC/attdet.c +92 -0
- package/ios/Packages/CoreObjC/attdet.h +44 -0
- package/ios/Packages/CoreObjC/bits.c +375 -0
- package/ios/Packages/CoreObjC/bits.h +315 -0
- package/ios/Packages/CoreObjC/bwdet.c +129 -0
- package/ios/Packages/CoreObjC/bwdet.h +69 -0
- package/ios/Packages/CoreObjC/common.h +151 -0
- package/ios/Packages/CoreObjC/energy.c +70 -0
- package/ios/Packages/CoreObjC/energy.h +43 -0
- package/ios/Packages/CoreObjC/fastmath.h +158 -0
- package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/lc3.c +704 -0
- package/ios/Packages/CoreObjC/lc3.h +313 -0
- package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
- package/ios/Packages/CoreObjC/lc3_private.h +163 -0
- package/ios/Packages/CoreObjC/ltpf.c +905 -0
- package/ios/Packages/CoreObjC/ltpf.h +111 -0
- package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
- package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
- package/ios/Packages/CoreObjC/makefile.mk +35 -0
- package/ios/Packages/CoreObjC/mdct.c +469 -0
- package/ios/Packages/CoreObjC/mdct.h +57 -0
- package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
- package/ios/Packages/CoreObjC/meson.build +61 -0
- package/ios/Packages/CoreObjC/plc.c +61 -0
- package/ios/Packages/CoreObjC/plc.h +57 -0
- package/ios/Packages/CoreObjC/rnnoise.h +114 -0
- package/ios/Packages/CoreObjC/sns.c +880 -0
- package/ios/Packages/CoreObjC/sns.h +103 -0
- package/ios/Packages/CoreObjC/spec.c +907 -0
- package/ios/Packages/CoreObjC/spec.h +119 -0
- package/ios/Packages/CoreObjC/tables.c +3457 -0
- package/ios/Packages/CoreObjC/tables.h +94 -0
- package/ios/Packages/CoreObjC/tns.c +457 -0
- package/ios/Packages/CoreObjC/tns.h +99 -0
- package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
- package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Packages/libbz2/module.modulemap +5 -0
- package/ios/Packages/libbz2/shim.h +1 -0
- package/ios/PhotoReceiverModule.swift +129 -0
- package/ios/Source/BluetoothSDK.swift +2303 -0
- package/ios/Source/BluetoothSDKDebug.swift +12 -0
- package/ios/Source/BluetoothSdkDefaults.swift +29 -0
- package/ios/Source/Bridge.swift +708 -0
- package/ios/Source/Bridging-Header.h +16 -0
- package/ios/Source/DeviceManager.swift +2109 -0
- package/ios/Source/DeviceStore.swift +336 -0
- package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
- package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
- package/ios/Source/ObservableStore.swift +118 -0
- package/ios/Source/OtaManifest.swift +211 -0
- package/ios/Source/PrivacyInfo.xcprivacy +23 -0
- package/ios/Source/ReleaseChangelog.swift +65 -0
- package/ios/Source/Resources/G2Firmware/README.md +10 -0
- package/ios/Source/audio/AudioModels.swift +178 -0
- package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
- package/ios/Source/camera/CameraModels.swift +866 -0
- package/ios/Source/connection/ScanSession.swift +27 -0
- package/ios/Source/controllers/ControllerManager.swift +184 -0
- package/ios/Source/controllers/R1.swift +829 -0
- package/ios/Source/errors/BluetoothSdkError.swift +19 -0
- package/ios/Source/events/BluetoothEvents.swift +342 -0
- package/ios/Source/internal/BleTraceLogger.swift +192 -0
- package/ios/Source/internal/BluetoothAvailability.swift +78 -0
- package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
- package/ios/Source/internal/ValueParsing.swift +99 -0
- package/ios/Source/requests/DisplayRequests.swift +82 -0
- package/ios/Source/services/PhoneMic.swift +662 -0
- package/ios/Source/sgcs/Ar99.swift +2451 -0
- package/ios/Source/sgcs/Frame.swift +649 -0
- package/ios/Source/sgcs/G1.swift +2554 -0
- package/ios/Source/sgcs/G2.swift +6887 -0
- package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
- package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
- package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
- package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
- package/ios/Source/sgcs/G2Flasher.swift +773 -0
- package/ios/Source/sgcs/Mach1.swift +541 -0
- package/ios/Source/sgcs/MentraLive.swift +7011 -0
- package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
- package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
- package/ios/Source/sgcs/MentraNex.swift +3221 -0
- package/ios/Source/sgcs/Nimo.swift +1886 -0
- package/ios/Source/sgcs/SGCManager.swift +608 -0
- package/ios/Source/sgcs/Simulated.swift +274 -0
- package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
- package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
- package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
- package/ios/Source/status/DeviceStatus.swift +981 -0
- package/ios/Source/status/RuntimeState.swift +359 -0
- package/ios/Source/status/WifiHotspotStatus.swift +345 -0
- package/ios/Source/streaming/StreamModels.swift +693 -0
- package/ios/Source/stt/STTTools.swift +191 -0
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
- package/ios/Source/tts/TTSTools.swift +171 -0
- package/ios/Source/types/DeviceModels.swift +177 -0
- package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
- package/ios/Source/utils/BinaryCodec.swift +61 -0
- package/ios/Source/utils/BleJsonCompact.swift +405 -0
- package/ios/Source/utils/BleWireProtocol.swift +92 -0
- package/ios/Source/utils/Constants.swift +78 -0
- package/ios/Source/utils/Enums.swift +95 -0
- package/ios/Source/utils/G1Text.swift +2096 -0
- package/ios/Source/utils/JSCExperiment.swift +241 -0
- package/ios/Source/utils/MemoryMonitor.swift +44 -0
- package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
- package/ios/Source/utils/MessageChunker.swift +294 -0
- package/ios/Source/utils/Models.swift +135 -0
- package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
- package/ios/Source/utils/TarBz2Extractor.swift +257 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
- package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
- package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
- package/ios/Tests/ReleaseChangelogTests.swift +13 -0
- package/package.json +129 -0
- package/plugin/build/index.d.ts +10 -0
- package/plugin/build/index.js +12 -0
- package/plugin/build/withAndroid.d.ts +3 -0
- package/plugin/build/withAndroid.js +190 -0
- package/plugin/build/withIos.d.ts +5 -0
- package/plugin/build/withIos.js +108 -0
- package/scripts/inject-ios-sdk-version.mjs +65 -0
- package/scripts/public-ota-api.test.mjs +37 -0
- package/scripts/verify-release-package.mjs +45 -0
- package/scripts/write-release-metadata.mjs +152 -0
- package/scripts/write-release-metadata.test.mjs +37 -0
- package/src/BluetoothSdk.types.ts +1623 -0
- package/src/_internal.ts +16 -0
- package/src/_private/BluetoothSdkModule.ts +684 -0
- package/src/_private/LocalNetworkModule.ts +50 -0
- package/src/_private/cameraRequestPayload.ts +34 -0
- package/src/_private/photoRequestPayload.ts +90 -0
- package/src/_private/sdkOtaManifest.ts +18 -0
- package/src/changelogs.ts +46 -0
- package/src/debug.ts +9 -0
- package/src/generated/changelogCatalog.ts +13 -0
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +321 -0
- package/src/ota-server/OtaServer.types.ts +10 -0
- package/src/ota-server/OtaServerModule.ts +23 -0
- package/src/ota-server/OtaServerModule.web.ts +17 -0
- package/src/ota-server/index.ts +2 -0
- package/src/ota-transport/index.ts +116 -0
- package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
- package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
- package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
- package/src/photo-receiver/index.ts +2 -0
- package/src/react/index.ts +21 -0
- package/src/react/useBluetooth.ts +309 -0
- package/src/react/useBluetoothEvent.ts +35 -0
- package/src/react/useBluetoothScan.ts +173 -0
- package/src/react/useBluetoothStatus.ts +180 -0
- package/src/react/useGlassesConnection.ts +202 -0
- package/src/types/index.ts +12 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
package com.glassly.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
import java.io.ByteArrayOutputStream
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Phone-side model of the Glassly CFW's lease-scoped 64 KiB texture cache
|
|
7
|
+
* (g2flash texture_cache.c), plus the mode-12/13/14 wire encoders.
|
|
8
|
+
*
|
|
9
|
+
* The firmware allocates and zeroes the cache on the first mode-12 write and
|
|
10
|
+
* frees it when the fbguard lease ends, so this model is only valid for one
|
|
11
|
+
* lease/generation: the owner bumps a generation counter whenever the lease
|
|
12
|
+
* cycles (or a send fails and residency becomes unknown) and the model
|
|
13
|
+
* re-learns from scratch — uploads are cheap (a full mono font is a few KiB).
|
|
14
|
+
*
|
|
15
|
+
* Cached image format: `[width:u8][height:u8][4bpp RLE]` where the RLE covers
|
|
16
|
+
* exactly width*height pixels with NO row-pad nibbles (unlike modes 3/6).
|
|
17
|
+
* Mode-14 fonts are a 96-entry little-endian u16 image-offset table for
|
|
18
|
+
* characters 32..127; a zero entry points at cache offset 0, so the first
|
|
19
|
+
* two bytes of the cache are left zero (width 0 ⇒ invalid image) and real
|
|
20
|
+
* allocations start past them.
|
|
21
|
+
*/
|
|
22
|
+
internal class G2CfwTextureCache {
|
|
23
|
+
companion object {
|
|
24
|
+
const val CACHE_SIZE = 64 * 1024
|
|
25
|
+
const val FONT_TABLE_CHARS = 96 // ASCII 32..127
|
|
26
|
+
|
|
27
|
+
/** Keep mode-12 payloads comfortably inside one BLE image message. */
|
|
28
|
+
const val MAX_UPLOAD_PAYLOAD_BYTES = 3600
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 0x0F: identity ramp (top color 15), opaque — a full-cell glyph or a
|
|
32
|
+
* full-box image drawn opaque self-erases whatever was under it.
|
|
33
|
+
*/
|
|
34
|
+
const val OPAQUE_DRAW_OPTIONS = 0x0F
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* RLE over a flat 8-bit grayscale pixel sequence (quantized to 4bpp),
|
|
38
|
+
* covering exactly the pixel count — no row padding, per the cached-image
|
|
39
|
+
* contract. Token forms match modes 3/6.
|
|
40
|
+
*/
|
|
41
|
+
fun rleEncodePixels(gray: ByteArray): ByteArray {
|
|
42
|
+
val output = ByteArrayOutputStream()
|
|
43
|
+
var index = 0
|
|
44
|
+
while (index < gray.size) {
|
|
45
|
+
// Same rounded quantization as pack4Bpp: a cached draw must reproduce
|
|
46
|
+
// the composited frame's exact levels or the phone-side shadow
|
|
47
|
+
// diverges from the panel.
|
|
48
|
+
val color = G2CfwRenderer.grayNibble(gray[index].toInt())
|
|
49
|
+
var end = index + 1
|
|
50
|
+
while (end < gray.size && G2CfwRenderer.grayNibble(gray[end].toInt()) == color) end += 1
|
|
51
|
+
var remaining = end - index
|
|
52
|
+
while (remaining > 0) {
|
|
53
|
+
val chunk = minOf(remaining, 0xFFFF)
|
|
54
|
+
when {
|
|
55
|
+
chunk <= 15 -> output.write((chunk shl 4) or color)
|
|
56
|
+
chunk <= 255 -> {
|
|
57
|
+
output.write(color)
|
|
58
|
+
output.write(chunk)
|
|
59
|
+
}
|
|
60
|
+
else -> {
|
|
61
|
+
output.write(color)
|
|
62
|
+
output.write(0)
|
|
63
|
+
output.write(chunk and 0xFF)
|
|
64
|
+
output.write((chunk ushr 8) and 0xFF)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
remaining -= chunk
|
|
68
|
+
}
|
|
69
|
+
index = end
|
|
70
|
+
}
|
|
71
|
+
return output.toByteArray()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Mode-13 cached-image draw: `[13][offset:u16][x:u16][y:u16][options]`. */
|
|
75
|
+
fun imageDrawPayload(offset: Int, x: Int, y: Int, options: Int): ByteArray? {
|
|
76
|
+
if (offset !in 0..0xFFFF || x !in 0..0xFFFF || y !in 0..0xFFFF) return null
|
|
77
|
+
val payload = ByteArrayOutputStream()
|
|
78
|
+
payload.write(13)
|
|
79
|
+
for (value in intArrayOf(offset, x, y)) {
|
|
80
|
+
payload.write(value and 0xFF)
|
|
81
|
+
payload.write((value ushr 8) and 0xFF)
|
|
82
|
+
}
|
|
83
|
+
payload.write(options and 0xFF)
|
|
84
|
+
return payload.toByteArray()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Mode-14 cached-glyph run:
|
|
89
|
+
* `[14][font-offset:u16][x:u16][y:u16][options][strlen:u8][chars]`.
|
|
90
|
+
* Every char must be 32..126 and resident (the firmware validates each
|
|
91
|
+
* referenced glyph and rejects the whole draw otherwise).
|
|
92
|
+
*/
|
|
93
|
+
fun stringRunPayload(
|
|
94
|
+
fontTableOffset: Int,
|
|
95
|
+
x: Int,
|
|
96
|
+
y: Int,
|
|
97
|
+
options: Int,
|
|
98
|
+
chars: ByteArray,
|
|
99
|
+
): ByteArray? {
|
|
100
|
+
if (chars.isEmpty() || chars.size > 255) return null
|
|
101
|
+
if (fontTableOffset !in 0..(CACHE_SIZE - FONT_TABLE_CHARS * 2)) return null
|
|
102
|
+
if (x !in 0..0xFFFF || y !in 0..0xFFFF) return null
|
|
103
|
+
if (chars.any { (it.toInt() and 0xFF) < 32 || (it.toInt() and 0xFF) > 126 }) return null
|
|
104
|
+
val payload = ByteArrayOutputStream()
|
|
105
|
+
payload.write(14)
|
|
106
|
+
for (value in intArrayOf(fontTableOffset, x, y)) {
|
|
107
|
+
payload.write(value and 0xFF)
|
|
108
|
+
payload.write((value ushr 8) and 0xFF)
|
|
109
|
+
}
|
|
110
|
+
payload.write(options and 0xFF)
|
|
111
|
+
payload.write(chars.size)
|
|
112
|
+
payload.write(chars)
|
|
113
|
+
return payload.toByteArray()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
class FontEntry(val tableOffset: Int, val cellWidth: Int, val lineHeight: Int) {
|
|
118
|
+
/** Cache offset per printable char (index = char - 32), null = not resident. */
|
|
119
|
+
val glyphOffsets = arrayOfNulls<Int>(FONT_TABLE_CHARS)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
var generation = -1
|
|
123
|
+
private set
|
|
124
|
+
|
|
125
|
+
private val fonts = mutableMapOf<Int, FontEntry>()
|
|
126
|
+
private val images = mutableMapOf<String, Int>()
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Content hashes seen in earlier frames. Streaming content (a minimap
|
|
130
|
+
* re-rendered every frame) never repeats a hash, so it never enters the
|
|
131
|
+
* cache; static icons promote on their second sighting.
|
|
132
|
+
*/
|
|
133
|
+
private val seenImageHashes = ArrayDeque<String>()
|
|
134
|
+
|
|
135
|
+
/** Bump allocator. Bytes 0..1 stay zero as the invalid-image guard. */
|
|
136
|
+
private var nextOffset = 2
|
|
137
|
+
|
|
138
|
+
/** Mode-12 entries not yet flushed into payloads. */
|
|
139
|
+
private val pendingUploads = mutableListOf<Pair<Int, ByteArray>>()
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The bump allocator filled up. The reference client recycles a full
|
|
143
|
+
* cache (`TextureCacheState.reset` "or we ran out of space"); without
|
|
144
|
+
* recovery every later ensure fails and the texture path silently dies
|
|
145
|
+
* for the rest of the lease. The renderer checks this before each frame
|
|
146
|
+
* and starts a fresh generation.
|
|
147
|
+
*/
|
|
148
|
+
var exhausted = false
|
|
149
|
+
private set
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Forget everything and adopt `generation` (the on-glass cache was freed
|
|
153
|
+
* or its state became unknown).
|
|
154
|
+
*/
|
|
155
|
+
fun reset(generation: Int) {
|
|
156
|
+
this.generation = generation
|
|
157
|
+
fonts.clear()
|
|
158
|
+
images.clear()
|
|
159
|
+
seenImageHashes.clear()
|
|
160
|
+
nextOffset = 2
|
|
161
|
+
pendingUploads.clear()
|
|
162
|
+
exhausted = false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private fun allocate(length: Int): Int? {
|
|
166
|
+
if (length <= 0 || nextOffset + length > CACHE_SIZE) {
|
|
167
|
+
if (length > 0) exhausted = true
|
|
168
|
+
return null
|
|
169
|
+
}
|
|
170
|
+
val offset = nextOffset
|
|
171
|
+
nextOffset += length
|
|
172
|
+
return offset
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The font table for `fontSize`, allocating (and zero-filling on-glass by
|
|
177
|
+
* virtue of the fresh cache) the 192-byte offset table on first use.
|
|
178
|
+
*/
|
|
179
|
+
fun font(fontSize: Int, cellWidth: Int, lineHeight: Int): FontEntry? {
|
|
180
|
+
fonts[fontSize]?.let { return it }
|
|
181
|
+
val tableOffset = allocate(FONT_TABLE_CHARS * 2) ?: return null
|
|
182
|
+
val entry = FontEntry(tableOffset, cellWidth, lineHeight)
|
|
183
|
+
fonts[fontSize] = entry
|
|
184
|
+
return entry
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Make `char` (ASCII 32..126) resident for `font`, uploading its RLE
|
|
189
|
+
* raster and patching the font table. `rasterize` supplies the full-cell
|
|
190
|
+
* 8-bit grayscale raster (cellWidth × lineHeight) on first upload.
|
|
191
|
+
* Returns false when the cache is full or the raster is unavailable.
|
|
192
|
+
*/
|
|
193
|
+
fun ensureGlyph(font: FontEntry, char: Int, rasterize: () -> ByteArray?): Boolean {
|
|
194
|
+
if (char < 32 || char > 126) return false
|
|
195
|
+
val index = char - 32
|
|
196
|
+
if (font.glyphOffsets[index] != null) return true
|
|
197
|
+
val gray = rasterize() ?: return false
|
|
198
|
+
if (gray.size != font.cellWidth * font.lineHeight) return false
|
|
199
|
+
val image = ByteArrayOutputStream()
|
|
200
|
+
image.write(font.cellWidth)
|
|
201
|
+
image.write(font.lineHeight)
|
|
202
|
+
image.write(rleEncodePixels(gray))
|
|
203
|
+
val bytes = image.toByteArray()
|
|
204
|
+
val offset = allocate(bytes.size) ?: return false
|
|
205
|
+
font.glyphOffsets[index] = offset
|
|
206
|
+
pendingUploads.add(offset to bytes)
|
|
207
|
+
pendingUploads.add(
|
|
208
|
+
(font.tableOffset + index * 2) to
|
|
209
|
+
byteArrayOf((offset and 0xFF).toByte(), ((offset ushr 8) and 0xFF).toByte())
|
|
210
|
+
)
|
|
211
|
+
return true
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Record a sighting of an image content hash; true when it was already
|
|
216
|
+
* seen in an earlier frame (worth caching).
|
|
217
|
+
*/
|
|
218
|
+
fun noteImageSighting(hash: String): Boolean {
|
|
219
|
+
if (images.containsKey(hash)) return true
|
|
220
|
+
if (hash in seenImageHashes) return true
|
|
221
|
+
seenImageHashes.addLast(hash)
|
|
222
|
+
if (seenImageHashes.size > 32) seenImageHashes.removeFirst()
|
|
223
|
+
return false
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The cache offset of an image, uploading it on first residency.
|
|
228
|
+
* `gray` is the width×height 8-bit grayscale raster.
|
|
229
|
+
*/
|
|
230
|
+
fun ensureImage(hash: String, gray: ByteArray, width: Int, height: Int): Int? {
|
|
231
|
+
images[hash]?.let { return it }
|
|
232
|
+
if (width !in 1..255 || height !in 1..255 || gray.size != width * height) return null
|
|
233
|
+
val image = ByteArrayOutputStream()
|
|
234
|
+
image.write(width)
|
|
235
|
+
image.write(height)
|
|
236
|
+
image.write(rleEncodePixels(gray))
|
|
237
|
+
val bytes = image.toByteArray()
|
|
238
|
+
val offset = allocate(bytes.size) ?: return null
|
|
239
|
+
images[hash] = offset
|
|
240
|
+
pendingUploads.add(offset to bytes)
|
|
241
|
+
return offset
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Drain the pending mode-12 entries into `[12][offset16][len16][data]...`
|
|
246
|
+
* payloads, each at most [MAX_UPLOAD_PAYLOAD_BYTES]. An entry larger than
|
|
247
|
+
* the budget gets a payload of its own (the BLE fragmenter splits it).
|
|
248
|
+
*/
|
|
249
|
+
fun takeUploadPayloads(): List<ByteArray> {
|
|
250
|
+
if (pendingUploads.isEmpty()) return emptyList()
|
|
251
|
+
val payloads = mutableListOf<ByteArray>()
|
|
252
|
+
var current = ByteArrayOutputStream().apply { write(12) }
|
|
253
|
+
for ((offset, data) in pendingUploads) {
|
|
254
|
+
val record = ByteArrayOutputStream()
|
|
255
|
+
record.write(offset and 0xFF)
|
|
256
|
+
record.write((offset ushr 8) and 0xFF)
|
|
257
|
+
record.write(data.size and 0xFF)
|
|
258
|
+
record.write((data.size ushr 8) and 0xFF)
|
|
259
|
+
record.write(data)
|
|
260
|
+
if (current.size() > 1 && current.size() + record.size() > MAX_UPLOAD_PAYLOAD_BYTES) {
|
|
261
|
+
payloads.add(current.toByteArray())
|
|
262
|
+
current = ByteArrayOutputStream().apply { write(12) }
|
|
263
|
+
}
|
|
264
|
+
record.writeTo(current)
|
|
265
|
+
}
|
|
266
|
+
if (current.size() > 1) payloads.add(current.toByteArray())
|
|
267
|
+
pendingUploads.clear()
|
|
268
|
+
return payloads
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
package com.glassly.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
/** Byte-exact EVENOTA framing, validation, and MRAM brick guard. No BLE I/O lives here. */
|
|
4
|
+
internal object G2FlashProtocol {
|
|
5
|
+
private const val U32_MASK = 0xFFFF_FFFFL
|
|
6
|
+
const val CHUNK = 232
|
|
7
|
+
const val APP_LOAD_ADDR = 0x0043_8000L
|
|
8
|
+
const val APP_MAX_END = 0x007F_0000L
|
|
9
|
+
const val APP_PREAMBLE = 0x20
|
|
10
|
+
const val REQUIRED_SEGMENT = "ota/s200_firmware_ota.bin"
|
|
11
|
+
|
|
12
|
+
class BadImageException(message: String) : Exception("bad firmware image: $message")
|
|
13
|
+
|
|
14
|
+
data class Rx(val sequence: Int, val sid: Int, val pb: ByteArray)
|
|
15
|
+
|
|
16
|
+
data class Segment(
|
|
17
|
+
val eid: Long,
|
|
18
|
+
val off: Long,
|
|
19
|
+
val size: Long,
|
|
20
|
+
val crc: Long,
|
|
21
|
+
val sub: ByteArray,
|
|
22
|
+
val ps: Long,
|
|
23
|
+
val fn: String,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
data class GuardResult(
|
|
27
|
+
val ps: Long,
|
|
28
|
+
val loadAddr: Long,
|
|
29
|
+
val preLen: Long,
|
|
30
|
+
val progEnd: Long,
|
|
31
|
+
val pass: Boolean,
|
|
32
|
+
val reason: String,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
data class ValidatedImage(val segments: List<Segment>, val guardResult: GuardResult)
|
|
36
|
+
|
|
37
|
+
data class GoldenVector(
|
|
38
|
+
val sha256: String,
|
|
39
|
+
val ps: Long,
|
|
40
|
+
val progEnd: Long,
|
|
41
|
+
val pass: Boolean,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
val goldenStock =
|
|
45
|
+
GoldenVector(
|
|
46
|
+
sha256 = "f4dfb0b49ad3de3c2daf17f8a27a157c3dc98411d6a0d3ab2cfd0918f41b9afa",
|
|
47
|
+
ps = 3_523_396,
|
|
48
|
+
progEnd = 0x0079_4324,
|
|
49
|
+
pass = true,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
fun crc16(data: ByteArray): ByteArray {
|
|
53
|
+
var crc = 0xFFFF
|
|
54
|
+
for (byte in data) {
|
|
55
|
+
crc = crc xor ((byte.toInt() and 0xFF) shl 8)
|
|
56
|
+
repeat(8) {
|
|
57
|
+
crc =
|
|
58
|
+
if ((crc and 0x8000) != 0) {
|
|
59
|
+
((crc shl 1) xor 0x1021) and 0xFFFF
|
|
60
|
+
} else {
|
|
61
|
+
(crc shl 1) and 0xFFFF
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return byteArrayOf((crc and 0xFF).toByte(), ((crc ushr 8) and 0xFF).toByte())
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private val crc32cTable =
|
|
69
|
+
LongArray(256).also { table ->
|
|
70
|
+
for (byte in 0 until 256) {
|
|
71
|
+
var crc = (byte.toLong() shl 24) and U32_MASK
|
|
72
|
+
repeat(8) {
|
|
73
|
+
crc =
|
|
74
|
+
if ((crc and 0x8000_0000L) != 0L) {
|
|
75
|
+
((crc shl 1) xor 0x1EDC_6F41L) and U32_MASK
|
|
76
|
+
} else {
|
|
77
|
+
(crc shl 1) and U32_MASK
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
table[byte] = crc
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fun crc32c(data: ByteArray): Long {
|
|
85
|
+
var crc = 0L
|
|
86
|
+
for (byte in data) {
|
|
87
|
+
val index = (((crc ushr 24) xor (byte.toLong() and 0xFF)) and 0xFF).toInt()
|
|
88
|
+
crc = (((crc shl 8) and U32_MASK) xor crc32cTable[index]) and U32_MASK
|
|
89
|
+
}
|
|
90
|
+
return crc
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fun readU32LE(bytes: ByteArray, offset: Int): Long =
|
|
94
|
+
(bytes[offset].toLong() and 0xFF) or
|
|
95
|
+
((bytes[offset + 1].toLong() and 0xFF) shl 8) or
|
|
96
|
+
((bytes[offset + 2].toLong() and 0xFF) shl 16) or
|
|
97
|
+
((bytes[offset + 3].toLong() and 0xFF) shl 24)
|
|
98
|
+
|
|
99
|
+
fun frames(sid: Int, pb: ByteArray, flag: Int = 0, seq: Int): List<ByteArray> {
|
|
100
|
+
val body = pb + crc16(pb)
|
|
101
|
+
val total = maxOf(1, (body.size + CHUNK - 1) / CHUNK)
|
|
102
|
+
return List(total) { index ->
|
|
103
|
+
val start = index * CHUNK
|
|
104
|
+
val chunk = body.copyOfRange(start, minOf(start + CHUNK, body.size))
|
|
105
|
+
byteArrayOf(
|
|
106
|
+
0xAA.toByte(),
|
|
107
|
+
0x21,
|
|
108
|
+
(seq and 0xFF).toByte(),
|
|
109
|
+
chunk.size.toByte(),
|
|
110
|
+
total.toByte(),
|
|
111
|
+
(index + 1).toByte(),
|
|
112
|
+
sid.toByte(),
|
|
113
|
+
flag.toByte(),
|
|
114
|
+
) + chunk
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fun ctrlFrames(op: Int, data: ByteArray = ByteArray(0), seq: Int): List<ByteArray> =
|
|
119
|
+
frames(sid = 0xC0, pb = byteArrayOf(op.toByte()) + data, seq = seq)
|
|
120
|
+
|
|
121
|
+
fun dataFrames(block: ByteArray, seq: Int): List<ByteArray> =
|
|
122
|
+
frames(sid = 0xC1, pb = block, seq = seq)
|
|
123
|
+
|
|
124
|
+
fun parseRx(frame: ByteArray): Rx? {
|
|
125
|
+
if (frame.size < 10 || (frame[0].toInt() and 0xFF) != 0xAA ||
|
|
126
|
+
(frame[1].toInt() and 0xFF) != 0x12
|
|
127
|
+
) {
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
val length = frame[3].toInt() and 0xFF
|
|
131
|
+
val payloadLength = maxOf(0, length - 2)
|
|
132
|
+
val end = minOf(8 + payloadLength, frame.size)
|
|
133
|
+
return Rx(
|
|
134
|
+
sequence = frame[2].toInt() and 0xFF,
|
|
135
|
+
sid = frame[6].toInt() and 0xFF,
|
|
136
|
+
pb = if (end >= 8) frame.copyOfRange(8, end) else ByteArray(0),
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Real OTA replies correlate by notification characteristic and opcode, not echoed seq/SID. */
|
|
141
|
+
fun otaAckStatus(frames: Iterable<ByteArray>, opcode: Int): Int? {
|
|
142
|
+
for (frame in frames) {
|
|
143
|
+
val parsed = parseRx(frame) ?: continue
|
|
144
|
+
if (parsed.pb.size >= 2 && (parsed.pb[0].toInt() and 0xFF) == opcode) {
|
|
145
|
+
return parsed.pb[1].toInt() and 0xFF
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@Throws(BadImageException::class)
|
|
152
|
+
fun parseSegments(image: ByteArray): List<Segment> {
|
|
153
|
+
if (image.size < 0x40) throw BadImageException("file too small")
|
|
154
|
+
val count = readU32LE(image, 8)
|
|
155
|
+
if (count !in 1..64) throw BadImageException("implausible component count $count")
|
|
156
|
+
return List(count.toInt()) { index ->
|
|
157
|
+
val toc = 0x40 + index * 16
|
|
158
|
+
if (toc + 16 > image.size) throw BadImageException("TOC entry $index past EOF")
|
|
159
|
+
val offset = readU32LE(image, toc + 4)
|
|
160
|
+
if (offset > Int.MAX_VALUE || offset + 128 > image.size.toLong()) {
|
|
161
|
+
throw BadImageException("segment $index subheader past EOF")
|
|
162
|
+
}
|
|
163
|
+
val sub = image.copyOfRange(offset.toInt(), offset.toInt() + 128)
|
|
164
|
+
var nameEnd = 48
|
|
165
|
+
while (nameEnd < sub.size && sub[nameEnd].toInt() != 0) nameEnd += 1
|
|
166
|
+
Segment(
|
|
167
|
+
eid = readU32LE(image, toc),
|
|
168
|
+
off = offset,
|
|
169
|
+
size = readU32LE(image, toc + 8),
|
|
170
|
+
crc = readU32LE(image, toc + 12),
|
|
171
|
+
sub = sub,
|
|
172
|
+
ps = readU32LE(sub, 8),
|
|
173
|
+
fn = String(sub, 48, nameEnd - 48, Charsets.ISO_8859_1),
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Throws(BadImageException::class)
|
|
179
|
+
fun validateFirmware(image: ByteArray): ValidatedImage {
|
|
180
|
+
val segments = parseSegments(image)
|
|
181
|
+
val names = segments.map { it.fn }
|
|
182
|
+
if (segments.size !in 5..6) {
|
|
183
|
+
throw BadImageException("expected 5-6 segments, found ${segments.size}: $names")
|
|
184
|
+
}
|
|
185
|
+
if (REQUIRED_SEGMENT !in names) {
|
|
186
|
+
throw BadImageException("required segment $REQUIRED_SEGMENT not found; segments are: $names")
|
|
187
|
+
}
|
|
188
|
+
for ((index, segment) in segments.withIndex()) {
|
|
189
|
+
val payloadOffset = segment.off + 128
|
|
190
|
+
val payloadEnd = payloadOffset + segment.ps
|
|
191
|
+
if (segment.ps <= 0 || payloadOffset < 128 || payloadEnd > image.size.toLong()) {
|
|
192
|
+
throw BadImageException("segment $index (${segment.fn}) payload extends past EOF")
|
|
193
|
+
}
|
|
194
|
+
if (segment.ps > U32_MASK - 128 || segment.size != segment.ps + 128) {
|
|
195
|
+
throw BadImageException(
|
|
196
|
+
"segment $index (${segment.fn}) TOC size ${segment.size} != payload+header ${segment.ps + 128}"
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
val payload = image.copyOfRange(payloadOffset.toInt(), payloadEnd.toInt())
|
|
200
|
+
val calculated = crc32c(payload)
|
|
201
|
+
val subheaderCrc = readU32LE(segment.sub, 12)
|
|
202
|
+
if (calculated != segment.crc || calculated != subheaderCrc) {
|
|
203
|
+
throw BadImageException(
|
|
204
|
+
String.format(
|
|
205
|
+
"segment %d (%s) CRC32C mismatch: payload=%08x TOC=%08x sub=%08x",
|
|
206
|
+
index,
|
|
207
|
+
segment.fn,
|
|
208
|
+
calculated,
|
|
209
|
+
segment.crc,
|
|
210
|
+
subheaderCrc,
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
val guard = checkMainAppFitsMram(image, segments)
|
|
216
|
+
if (!guard.pass) throw BadImageException("brick guard blocked image: ${guard.reason}")
|
|
217
|
+
return ValidatedImage(segments, guard)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
fun checkMainAppFitsMram(image: ByteArray, segments: List<Segment>): GuardResult {
|
|
221
|
+
val segment =
|
|
222
|
+
segments.firstOrNull { it.fn == REQUIRED_SEGMENT }
|
|
223
|
+
?: return GuardResult(0, 0, 0, 0, false, "main-app segment $REQUIRED_SEGMENT not found")
|
|
224
|
+
val payloadOffset = segment.off + 128
|
|
225
|
+
if (payloadOffset + APP_PREAMBLE > image.size.toLong()) {
|
|
226
|
+
return GuardResult(
|
|
227
|
+
segment.ps,
|
|
228
|
+
0,
|
|
229
|
+
0,
|
|
230
|
+
0,
|
|
231
|
+
false,
|
|
232
|
+
"main-app payload smaller than its 32-byte preamble",
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
val offset = payloadOffset.toInt()
|
|
236
|
+
val loadAddr = readU32LE(image, offset + 0x14)
|
|
237
|
+
val preLen = readU32LE(image, offset) and 0x00FF_FFFFL
|
|
238
|
+
if (loadAddr != APP_LOAD_ADDR) {
|
|
239
|
+
return GuardResult(
|
|
240
|
+
segment.ps,
|
|
241
|
+
loadAddr,
|
|
242
|
+
preLen,
|
|
243
|
+
0,
|
|
244
|
+
false,
|
|
245
|
+
String.format("load addr 0x%08x != 0x00438000", loadAddr),
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
if (preLen != segment.ps) {
|
|
249
|
+
return GuardResult(
|
|
250
|
+
segment.ps,
|
|
251
|
+
loadAddr,
|
|
252
|
+
preLen,
|
|
253
|
+
0,
|
|
254
|
+
false,
|
|
255
|
+
"preamble length $preLen != staged payload size ${segment.ps}",
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
val programEnd = (APP_LOAD_ADDR + segment.ps - APP_PREAMBLE) and U32_MASK
|
|
259
|
+
if (programEnd > APP_MAX_END) {
|
|
260
|
+
return GuardResult(
|
|
261
|
+
segment.ps,
|
|
262
|
+
loadAddr,
|
|
263
|
+
preLen,
|
|
264
|
+
programEnd,
|
|
265
|
+
false,
|
|
266
|
+
String.format("too large: prog_end 0x%08x past ceiling 0x%08x", programEnd, APP_MAX_END),
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
return GuardResult(segment.ps, loadAddr, preLen, programEnd, true, "ok")
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fun selfTestGuard(image: ByteArray, expected: GoldenVector): String? {
|
|
273
|
+
val segments =
|
|
274
|
+
try {
|
|
275
|
+
parseSegments(image)
|
|
276
|
+
} catch (error: Exception) {
|
|
277
|
+
return "parse failed: $error"
|
|
278
|
+
}
|
|
279
|
+
val result = checkMainAppFitsMram(image, segments)
|
|
280
|
+
if (result.pass != expected.pass) return "guard pass=${result.pass} != golden ${expected.pass}"
|
|
281
|
+
if (result.ps != expected.ps) return "ps ${result.ps} != golden ${expected.ps}"
|
|
282
|
+
if (result.progEnd != expected.progEnd) {
|
|
283
|
+
return String.format(
|
|
284
|
+
"prog_end 0x%08x != golden 0x%08x",
|
|
285
|
+
result.progEnd,
|
|
286
|
+
expected.progEnd,
|
|
287
|
+
)
|
|
288
|
+
}
|
|
289
|
+
return null
|
|
290
|
+
}
|
|
291
|
+
}
|