Table of Contents
Hacking the Insta360 ONE RS
Just two years after purchasing the SJCAM SJ8 Pro, in June 2023 I decided to replace my action camera with a new Insta360 ONE RS. The SJCAM was quite good (but only after heavily customizing the firmware, both in terms of color balance and video codec parameters). The real sore point of the SJCAM is that it is impossible to use it without looking at the screen: if you press the REC button without looking you will never know if you have activated recording, if you have stopped it or if you have simply exited stand-by.
The Insta360 seems quite promising: it uses the same Ambarella H22 processor so it should allow the same level of hacking as the SJCAM, it seems to offer better support (firmware updates) and has different hardware modules (4K lens or dual 360° lens).
The best result I have achieved is to have reverse engineered the WiFi protocol, so that I can control the camera with open source programs (Python scripts) instead of the crap Android app that comes with it.
|Firmware upgraded (2023-06-15)||v188.8.131.52|
|Hardware SoC||Ambarella H22EVK K2 Board (DT)|
|CPU||AArch64 Processor, 4 cores|
|NAND memory||Toshiba TC58NVG1S3H 256 MiB|
Defects and Problems
- Cannot activate the camera for first use without the app
- Cannot set date and time without the app
- WiFi open to the world with known password
Start and stop recording
The camera plays different sounds on power-on, power-off, start recording and stop recording, so you can somewhat operate the camera without looking at its screen. Unfortunately the sounds are not too so loud.
|Power button|| When the camera is off, press it shortly once to power-on the camera.
When the camera is on, press it shortly once to toggle the screen on/off.
When the camera is on, press it for ~2 seconds to power-off the camera.
For all the operations there is a different acoustic feedback.
|Record button|| When the camera is on, press it shortly once to start or stop recording.
If the camera has the screen turned off, it will turn on again and start recroding, all with a single press.
If the camera is off and QuickCapture is enabled, press it once to power-on the camera and start recording.
If you started a QuickCapture, press it once to stop recording and power-off the camera.
|Normal Recording||Start recording pressing the REC button: less than one second.|
|QuickCapture||Start recording from camera turned off, pressing the REC button with QuickCapture mode enabled: less than 6 seconds.|
Video Files Produced
|4k 60fps||100.0 Mb/s||AVC Main@L5.2||M=1, N=15||AAC LC 192 kb/s|
|1080 60fps||60.0 Mb/s||AVC Main@L5.2||M=1, N=15||AAC LC 192 kb/s|
The Android app
Android app minimal requirements
- Android 64-bit system
- 4 Gb RAM
- 3 Gb storage space
- CPU minimal:
- Kirin 980
- Snapdragon 845
- Exynos 9810
The Insta360 Android App is an huge monster of 676 Mb to download (version 1.40.1, June 2023). Once installed it occupies 1.06 Gb for the app and 128 Mb for the cache. The app requires WiFi and Bluetooth to be activated, it finds the camera and connect to it using the WiFi access point provided by the Insta360 camera.
Pairing the camera with the app is required to “activate” the camera. At the first activation you need to enable Bluetooth and WiFi on the Android device, probably the Bluetooth channel is used to broadcast the presence of the camera to the device and to pass the WiFi credentials (SSID and password) to then connect the phone to the camera's WiFi access point. It is required to accept the pairing on the screen of the Insta360.
I have a problem with the app, when I try to open the live view to use it as a camera remote control, the app crashes:
When the camera starts with the WiFi enabled, is turns on the access point mode, the SSID is composed by the serial number and the password is 88888888. If something goes wrong the WiFi configuration could be reset and the password will be 1234567890. The IP address of the camera is 192.168.42.1 and it accepts max 5 clients.
Using nmap I got the list of the opened ports on the camera:
PORT STATE SERVICE 23/tcp open telnet 53/tcp open domain 80/tcp open http 111/tcp open rpcbind 2049/tcp open nfs 6666/tcp open irc 7878/tcp open owms 8787/tcp open msgsrvr 9888/tcp open cyborg-systems 35215/tcp open unknown 39585/tcp open unknown 45223/tcp open unknown 56769/tcp open unknown 57041/tcp open unknown
You can access the GNU/Linux operating system running on the camera using telnet, login root without password.
It seems that the control commands are sent over port TCP/6666, but they are not in cleartext. Instead it seems that data transfer (e.g. retrieving videos an phots) happen over port TCP/80 using plain HTTP protocol and URLs.
Port TCP/7878 is open and it seems to accept Ambarella API commands like the ones accepted by the SJCAM SJ8 Pro camera, but I was not able to start a communication because I always receive an error when I send the AMBA_START_SESSION command.
The WiFi access point service is started by the script /usr/local/share/script/wifi_start.sh.
In normal conditions the starting is demanded to /usr/local/share/script/ap_start.sh, which uses the values found in /pref/wifi.conf. Is something goes wrong, the configuration is reset using the content of /usr/local/share/script/wifi.conf, where the AP_PASSWD is 1234567890.
If the file /proc/ambarella/wifi.conf exists (it is something called “Fast boot”) the starting is demanded to /usr/local/share/script/ap.sh using the wifi.conf content to pass the command line parameters:
ap.sh [SSID] [PSK] [CHANNEL]
The directory /pref/ is actually stored into an ambafs partition named a: bind-mounted from /tmp/FL0/pref/. The ambafs (Ambarella Filesystem?) is managed by a proprietary kernel module. The ambafs is also used to mount the SD Card under /tmp/SD0, reading the the device named c:.
Customize WiFi Configuration
How to change at least the WiFi password?
It turned out that changing the WiFi password into the file /pref/wifi.conf does not work: when you power cycle the camera that file will be overwritten with the default values.
It is possibile to upgrade the firmware using the Android app: the app will check if an upgrade is available from the internet, then it downloads and copies it to the camera. It is also possibile to manually download a new firmware from the download site, copy the file Insta360OneRFW.bin into the root directory of the SD card and power-on the camera.
The anatomy of a firmare file is as follow (analyzed with some problems using ambarella-h22-firmware-unpack):
|Ambarella Firmware Sections found by Magic 90EB24A3|
|#1||0x00000230||0x00000330||27358092||0xD173F88F OK||Real Time Operating System (RTOS) image|
|#2||0x01A176BC||0x01A177BC||3852288||0x7A2024CB OK||ROMFS with RTOS microcode: default_binary.bin, orccode.bin and orcme.bin|
|#3||0x01DC3FBC||0x01DC40BC||10676224||0x889668C0 OK||ROMFS with files for color profiles, LUTs, sounds, etc.|
|#4||0x027F28BC||0x027F29BC||7919624||0x9D4BC0E3 OK||Linux kernel ARM64 boot executable Image.|
|#5||0x02F801C4||0x02F802C4||14458880||0xDCD5AFC8 OK||Linux root filesystem (Squashfs).|
|#6||0x03D4A2C4||0x03D4A3C4||25138||0x97606C13 OK||Device Tree Blob.|
The Insta360 ONE RS camera does run two operating systems at once: RTOS and GNU/Linux. RTOS is dedicated to operate the camera (buttons operations, touch screen, video recording, etc.), GNU/Linux is dedicated e.g. to WiFi operations, etc.
Here it is an overview of the partitions used:
|Partition||Size (kb)||Label||Content||From firmware file|
|mtdblock1||32768||SYS_SW||Real Time Operating System (RTOS) image||Section #1 at offset 0x00000330|
|mtdblock2||6144||DSP_uCode||ROMFS: RTOS microcode binary files||Section #2 at offset 0x01A177BC|
|mtdblock3||40960||SYS_DATA||ROMFS: RTOS data files (color tables, etc.)||Section #3 at offset 0x01DC40BC|
|mtdblock4||16384||LINUX_Kernel||Linux Kernel at offset 0x00000000|
Device Tree at offset 0x00fe0000
| Section #4 at offset 0x027F29BC
Section #6 at offset 0x03D4A3C4
|mtdblock5||16384||LINUX_RFS||Linux root filesystem||Section #5 at offset 0x02F802C4|
|mtdblock6||19968||VIDEO_REC_IDX||Index of files stored into the SD card||None|
|mtdblock9||100992||DRIVE_A||Storage a: mounted into /tmp/FL0/||None|
During normal camera usage only mtdblock6, mtdblock8 and mtdblock9 are changed.
The Instal360 ONE RS has four different USB modes that you can choose from the settings menu. A GNU/Linux host will detect the different modes with different VendorID and ProductID, except the Quick Reader mode, which is not detected at all.
|Mode||Vendor:Product||Linux Kernel Label||Usage|
|U-Disk Mode||070a:4026||Oki Electric Industry Co., Ltd A9 Platform||Allow access to media on the SD card using the USB storage protocol.|
|WebCam||2e1a:00c0||Amba Insta360 One RS||Get the video stream to the attached PC, e.g. using guvcview in GNU/Linux.|
|Quick Reader||Enable the the Quick Reader accessory.|
|Android||2e1a:0002||Arashi Vision Insta360 ONERS||Should be used to operate the camera through the USB cable from an Android (or other OS) host. See CameraSDK.|
WARNING: Streaming the WebCam video into a GNU/Linux computer using guvcview, resulted into a greenish image. Start the
guvcview program with the --format=bgr3 option (formats
rgb3 seem to work). The overall reliability with this setting is poor: starting and stopping
guvcview results in a non-working device; I had to unplug/plug the USB cable and powercycle the camera to get the video stream again.
Useful GNU/Linux Commands
Extract JPEG and GIF files from a binary image:
binwalk --dd 'jpeg image:jpeg' mtdblock1.bin binwalk --dd 'gif image:gif' mtdblock1.bin
Mount a Linux Squashfs image:
mount -o loop,ro mtdblock5.bin /mnt
Extract the kernel image and the device tree blob from the partition #4 image:
# Extract the Kernel Image dd if=mtdblock4.bin of=part4-a.kernel-image.bin bs=1 count=7919624 # Extract the Device Tree Blob, offset is 0x00fe0000 dd if=mtdblock4.bin of=part4-b.device-tree.bin bs=1 skip=16646144 count=25138
Shooting modes with Boost 4K lens
|FlowState (in-camera stabilization)|
|Post FlowState (app stabilization)|
|6K Widescreen Mode|