# HLWF — HuskyLens Web Flasher

HLWF is a self-contained, dependency-free static Web Serial uploader for
HuskyLens/Kendryte K210 devices. It selects a local `.bin`, validates its size,
computes SHA-256 in the browser, asks for explicit confirmation, and writes the
image through a user-selected serial port.

**Live site:** [aztechell.github.io/HLWF](https://aztechell.github.io/HLWF/)

> **Safety:** flashing replaces the current device firmware. Use a known-good
> image, keep power connected, and do not close the tab during the write stage.
> The project never starts a flash without the explicit confirmation checkbox.
> Automated tests do not access serial hardware.

## Privacy and security

- Firmware is read with the browser File API and is never uploaded.
- There is no analytics, CDN, remote API, service worker, or external runtime
  dependency.
- The only runtime `fetch()` loads the bundled open ISP stub from the same
  static origin.
- A Content Security Policy restricts scripts, styles, and connections to the
  same origin.
- Web Serial requires a secure context: HTTPS (including GitHub Pages) or
  `http://localhost`.

## Browser support

Use a current desktop version of Chrome or Microsoft Edge. Firefox and Safari
do not currently expose the Web Serial API used by HLWF.

1. Connect HuskyLens by USB.
2. Click **Select port** and select its serial adapter.
3. Select or drop a `.bin` file.
4. Check the filename, byte size, and SHA-256.
5. Accept the replacement warning and click **Flash firmware**.
6. Keep the device connected until the port is reported closed.

## Firmware size rule

HLWF targets the 16 MiB flash used by HuskyLens. A standard K210 boot image adds
37 bytes: one SPI/AES flag byte, a four-byte little-endian firmware length, and
a 32-byte SHA-256 suffix. Therefore the maximum accepted raw `.bin` size is
`16 MiB - 37 bytes` (`16,777,179` bytes). Empty files are rejected.

## Why `.kfpkg` is not supported

HLWF intentionally accepts raw `.bin` firmware only. HuskyLens `.kfpkg`
packages are compressed multi-image archives containing firmware, models, and a
flash address map. A typical original package expands to roughly 11.4 MiB of
data that must be written to several flash regions.

The current browser-compatible HuskyLens path is limited to 115200 baud. Web
Serial cannot change the baud rate of an already open port, while closing and
reopening the tested CP210x adapter during the ISP handoff resets HuskyLens and
loses communication. At 115200 baud, a full `.kfpkg` would take at least about
17 minutes in ideal conditions and typically 20–25 minutes with protocol
overhead and retries. For that reason, `.kfpkg` support is excluded until a
reliable faster Web Serial handoff is available.

Original HuskyLens firmware packages and the official desktop uploader are
available from
[`HuskyLens/HUSKYLENSUploader`](https://github.com/HuskyLens/HUSKYLENSUploader).

## K210/HuskyLens protocol

The implementation follows the open [`sipeed/kflash.py`](https://github.com/sipeed/kflash.py)
flow and the HuskyLens-compatible reset behavior:

1. Open UART at 115200, 8-N-1.
2. Try the `dan` and `kd233` DTR/RTS sequences to enter K210 BootROM.
3. Exchange SLIP-framed BootROM commands (`0xC2`, `0xC3`, `0xC5`).
4. Upload the MIT-licensed `kflash.py` ISP stub to SRAM at `0x80000000` and boot it.
5. Initialize on-board flash (`0xD7`, type 1).
6. Create the DIO boot image (`0x02 + uint32(length) + firmware + SHA-256`) and
   write it at flash address `0x000000` with CRC-32 protected `0xD4` packets.
7. Request reboot (`0xD5`) and close the serial port in every success, failure,
   or cancellation path.

HLWF deliberately stays at 115200 baud. This is a practical Web Serial port
lifecycle limitation on the tested HuskyLens adapter, not a K210 hardware baud
rate limit. The conservative rate keeps the flashing path predictable.

The bundled stub was extracted from `sipeed/kflash.py` revision
`550828c768b16ef329695d3f5eace3f6bcf14af2`. Its attribution and exact MIT
license are in [`third_party/kflash.py`](third_party/kflash.py/NOTICE.md). No
user firmware is bundled.

## Local development

No installation or build step is required. Serve the directory over localhost:

```powershell
npm run serve
```

Then open `http://localhost:8000` in Chrome or Edge. Do not open `index.html`
directly with a `file://` URL because Web Serial needs a secure context.

Run the Node.js test suite:

```powershell
npm test
```

The tests cover CRC-32, SLIP encoding, packet construction, K210 image layout,
size limits, static privacy constraints, ISP stub presence, and serial-port
closure after both success and failure. They use no real serial device.

## Reproducing the ISP stub

Given a checkout of the pinned `kflash.py` revision:

```powershell
node tools/extract-kflash-stub.mjs path\to\kflash.py third_party\kflash.py\isp_prog.bin
```

Compare the printed SHA-256 with `third_party/kflash.py/NOTICE.md` and the value
pinned in `src/app.js`.

## GitHub Pages

The public version is available at
[https://aztechell.github.io/HLWF/](https://aztechell.github.io/HLWF/).

The workflow at `.github/workflows/pages.yml` runs tests and deploys this
directory as a static GitHub Pages artifact on pushes to `main`. In the GitHub
repository settings, set **Pages → Source** to **GitHub Actions**.

## License

HLWF is released under the MIT License. The bundled kflash.py ISP stub is also
MIT-licensed by its original author; its license is reproduced separately.
