# Flash User Bootloader

This script will flash [user bootloader](https://docs.luxonis.com/software/depthai-components/bootloader.md) to the connected OAK
camera. can only be flashed to devices that have on-board flash memory.

> We suggest using
> [ Device Manager](https://docs.luxonis.com/software/depthai-components/bootloader.md)
> , a GUI tool for interfacing with the bootloader and its configurations.

## Demo

Example script output

```bash
~/depthai-python/examples/bootloader$ python3 flash_user_bootloader.py
    [0] 1844301041C83D0E00 [X_LINK_USB_VSC] current bootloader: 0.0.26
    Which DepthAI device to flash User Bootloader for (Note: Only NETWORK supported) [0..0]: 0
    User Bootloader version to flash: 0.0.26
    Flashing User Bootloader...
    Flashing progress: 0.0%
    Flashing progress: 18.8%
    Flashing progress: 31.2%
    Flashing progress: 48.2%
    Flashing progress: 94.2%
    Flashing progress: 100.0%
    Flashing successful. Took 7.55600329185836 seconds
```

## Setup

Please run the [install script](https://github.com/luxonis/depthai-python/blob/main/examples/install_requirements.py) to download
all required dependencies. Please note that this script must be ran from git context, so you have to download the
[depthai-python](https://github.com/luxonis/depthai-python) repository first and then run the script

```bash
git clone https://github.com/luxonis/depthai-python.git
cd depthai-python/examples
python3 install_requirements.py
```

For additional information, please follow the [installation guide](https://docs.luxonis.com/software/depthai/manual-install.md).

## Source code

#### Python

```python
#!/usr/bin/env python3

import depthai as dai
import sys
import time

deviceInfos = dai.DeviceBootloader.getAllAvailableDevices()
if len(deviceInfos) == 0:
    print("No device found to flash. Exiting.")
    exit(-1)
else:
    for i, di in enumerate(deviceInfos):
        print(f'[{i}] {di.getMxId()} [{di.protocol.name}]', end='')
        if di.state == dai.XLinkDeviceState.X_LINK_BOOTLOADER:
            with dai.DeviceBootloader(di) as bl:
                print(f' current bootloader: {bl.getVersion()}', end='')
        print()
    selected = input(f'Which DepthAI device to flash User Bootloader for (Note: Only NETWORK supported) [0..{len(deviceInfos)-1}]: ')
    info = deviceInfos[int(selected)]

# Open DeviceBootloader and allow flashing bootloader
with dai.DeviceBootloader(info) as bl:
    print("User Bootloader version to flash:", bl.getVersion())

    # Create a progress callback lambda
    progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')

    print(f"Flashing User Bootloader...")
    startTime = time.monotonic()
    (res, message) = bl.flashUserBootloader(progress)
    if res:
        print("Flashing successful. Took", time.monotonic() - startTime, "seconds")
    else:
        print("Flashing failed:", message)
```

#### C++

```cpp
#include <chrono>
#include <string>

#include "XLink/XLink.h"
#include "depthai/depthai.hpp"
#include "depthai/xlink/XLinkConnection.hpp"

static const char* ProtocolToStr(XLinkProtocol_t val) {
    switch(val) {
        case X_LINK_USB_VSC:
            return "X_LINK_USB_VSC";
        case X_LINK_USB_CDC:
            return "X_LINK_USB_CDC";
        case X_LINK_PCIE:
            return "X_LINK_PCIE";
        case X_LINK_IPC:
            return "X_LINK_IPC";
        case X_LINK_TCP_IP:
            return "X_LINK_TCP_IP";
        case X_LINK_NMB_OF_PROTOCOLS:
            return "X_LINK_NMB_OF_PROTOCOLS";
        case X_LINK_ANY_PROTOCOL:
            return "X_LINK_ANY_PROTOCOL";
        default:
            return "INVALID_ENUM_VALUE";
            break;
    }
}

int main(int argc, char** argv) try {
    using namespace std::chrono;

    dai::DeviceInfo info;
    auto deviceInfos = dai::DeviceBootloader::getAllAvailableDevices();
    if(deviceInfos.empty()) {
        std::cout << "No device found to flash. Exiting." << std::endl;
        return -1;
    } else {
        for(int i = 0; i < deviceInfos.size(); i++) {
            const auto& devInfo = deviceInfos[i];
            std::cout << "[" << i << "] " << devInfo.getMxId() << "[" << ProtocolToStr(devInfo.protocol) << "]";
            if(devInfo.state == X_LINK_BOOTLOADER) {
                dai::DeviceBootloader bl(devInfo);
                std::cout << " current bootloader: " << bl.getVersion();
            }
            std::cout << std::endl;
        }
        int selected = 0;
        std::cout << "Which DepthAI device to flash bootloader for (Note: Only NETWORK supported) [0.." << deviceInfos.size() - 1 << "]\n";
        std::cin >> selected;
        info = deviceInfos[selected];
    }

    dai::DeviceBootloader bl(info);

    // Create a progress callback lambda
    auto progress = [](float p) { std::cout << "Flashing Progress..." << p * 100 << "%" << std::endl; };

    std::cout << "Flashing User Bootloader..." << std::endl;
    auto t1 = steady_clock::now();
    bool success = false;
    std::string message;
    std::tie(success, message) = bl.flashUserBootloader(progress);
    if(success) {
        std::cout << "Flashing successful. Took " << duration_cast<milliseconds>(steady_clock::now() - t1).count() << "ms" << std::endl;
    } else {
        std::cout << "Flashing failed: " << message << std::endl;
    }
    return 0;
} catch(const std::exception& ex) {
    std::cout << "Exception: " << ex.what() << std::endl;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
