Compare commits
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"PQL_VAULT": "/mnt/media/Projects/desklock"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(pql)",
|
||||||
|
"Bash(pql *)",
|
||||||
|
"Bash(/home/jpmschweitzer/.local/bin/pql:*)",
|
||||||
|
"Bash(git status:*)",
|
||||||
|
"Bash(git log:*)",
|
||||||
|
"Bash(git diff:*)",
|
||||||
|
"Bash(git branch:*)",
|
||||||
|
"Bash(make -C gateway *)",
|
||||||
|
"Bash(make setup:*)",
|
||||||
|
"Bash(make run:*)",
|
||||||
|
"Bash(make test:*)",
|
||||||
|
"Bash(make lint:*)",
|
||||||
|
"Bash(make typecheck:*)",
|
||||||
|
"Bash(.venv/bin/pytest:*)",
|
||||||
|
"Bash(.venv/bin/ruff:*)",
|
||||||
|
"Bash(.venv/bin/mypy:*)",
|
||||||
|
"Bash(docker logs desklock-gateway:*)",
|
||||||
|
"Bash(curl -s http://localhost:8600/*)"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"Bash(/mnt/media/Projects/cladmin/ops/bin/toj)",
|
||||||
|
"Bash(/mnt/media/Projects/cladmin/ops/bin/toj:*)",
|
||||||
|
"Bash(chmod -R 777 *)",
|
||||||
|
"Bash(chmod 777 *)",
|
||||||
|
"Bash(dd if=*)",
|
||||||
|
"Bash(find * -delete*)",
|
||||||
|
"Bash(find * -exec*)",
|
||||||
|
"Bash(git * add --all*)",
|
||||||
|
"Bash(git * add -A*)",
|
||||||
|
"Bash(git * add .)",
|
||||||
|
"Bash(git * branch -D *)",
|
||||||
|
"Bash(git * checkout -- *)",
|
||||||
|
"Bash(git * clean -fd*)",
|
||||||
|
"Bash(git * clean -fdx*)",
|
||||||
|
"Bash(git * commit --no-verify*)",
|
||||||
|
"Bash(git * merge --no-ff*)",
|
||||||
|
"Bash(git * push --force*)",
|
||||||
|
"Bash(git * push -f*)",
|
||||||
|
"Bash(git * reset --hard*)",
|
||||||
|
"Bash(git * restore .*)",
|
||||||
|
"Bash(git add --all*)",
|
||||||
|
"Bash(git add -A*)",
|
||||||
|
"Bash(git add .)",
|
||||||
|
"Bash(git branch -D *)",
|
||||||
|
"Bash(git checkout -- *)",
|
||||||
|
"Bash(git clean -fd*)",
|
||||||
|
"Bash(git clean -fdx*)",
|
||||||
|
"Bash(git commit --no-verify*)",
|
||||||
|
"Bash(git merge --no-ff*)",
|
||||||
|
"Bash(git push --force*)",
|
||||||
|
"Bash(git push -f*)",
|
||||||
|
"Bash(git reset --hard*)",
|
||||||
|
"Bash(git restore .*)",
|
||||||
|
"Bash(mkfs*)",
|
||||||
|
"Bash(rm -rf $HOME)",
|
||||||
|
"Bash(rm -rf /)",
|
||||||
|
"Bash(rm -rf ~)",
|
||||||
|
"Bash(su *)",
|
||||||
|
"Bash(sudo *)",
|
||||||
|
"Bash(toj)",
|
||||||
|
"Bash(toj:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
---
|
||||||
|
name: device-screenshot
|
||||||
|
description: >
|
||||||
|
Capture a screenshot of the live DeskLock ESP32-P4 display over USB and view
|
||||||
|
it as a PNG. Use whenever you need to SEE what's on the device screen — verify
|
||||||
|
a face/UI change, check the tap controls overlay, confirm a state (idle,
|
||||||
|
listening, effort), or debug layout remotely without the user's camera.
|
||||||
|
Triggers: "screenshot the device", "what's on the screen", "capture the
|
||||||
|
display", "show me the face", "did the UI change land".
|
||||||
|
---
|
||||||
|
|
||||||
|
# DeskLock device screenshot over USB
|
||||||
|
|
||||||
|
Grabs the current LVGL screen off the device and rebuilds it as a PNG on the
|
||||||
|
host. No camera, no gateway — it rides the USB serial that's already attached for
|
||||||
|
flashing.
|
||||||
|
|
||||||
|
## How it works (so you can debug it)
|
||||||
|
|
||||||
|
The firmware (`main/face.c` `face_screenshot_dump`, gated by `DESKLOCK_DEVMODE`
|
||||||
|
in `desklock_main.c`) runs a task that watches the **USB-serial-JTAG RX FIFO**
|
||||||
|
for a trigger byte, renders the active screen with `lv_snapshot_take_to_draw_buf`
|
||||||
|
into a PSRAM buffer, 2×-downscales to 400×400, and streams it as **raw binary**
|
||||||
|
straight to the USB-serial-JTAG TX FIFO — framed by a text header
|
||||||
|
`###SHOT_BEGIN … bytes=N crc=0x… bin=1###` + N bytes + `###SHOT_END###`. The host
|
||||||
|
tool `firmware/tools/device_shot.py` sends the trigger, reads N bytes, checks the
|
||||||
|
CRC (retrying on the rare dropped frame), and writes a PNG.
|
||||||
|
|
||||||
|
Two things this design is deliberately built around, learned the hard way:
|
||||||
|
- **Don't use `printf`.** The primary console is UART at 115200 baud (~11 KB/s) —
|
||||||
|
a frame would take ~37 s. Writing straight to the USB FIFO runs at USB speed
|
||||||
|
(~1 s). That's why the dump uses `usb_serial_jtag_ll_write_txfifo`, not stdout.
|
||||||
|
- **Opening the port does NOT reset the P4** (unlike esptool), and there's no USB
|
||||||
|
stdin, so the trigger is a byte the firmware polls for — on-demand, no reboot,
|
||||||
|
captures whatever state is currently on screen.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Firmware flashed with **dev mode ON** — it's OFF by default (production spends
|
||||||
|
no internal RAM on the watcher and nothing extra runs on the render path). Flash
|
||||||
|
a dev build with:
|
||||||
|
```bash
|
||||||
|
cd firmware && sg dialout -c "bash -c 'source ~/esp-idf/export.sh && idf.py -DDESKLOCK_DEVMODE=ON -p /dev/ttyACM0 flash'"
|
||||||
|
```
|
||||||
|
If screenshots return "no frame", the flashed build is production — reflash with
|
||||||
|
`-DDESKLOCK_DEVMODE=ON`. Back to production: `-DDESKLOCK_DEVMODE=OFF` (the value
|
||||||
|
sticks in the CMake cache until you flip it). Leave it ON for a UI-dev session
|
||||||
|
(you're reflashing for UI changes anyway); flip OFF for the final/production flash.
|
||||||
|
- Device on `/dev/ttyACM0`. The port needs the `dialout` group, so run the tool
|
||||||
|
under `sg dialout -c '…'` (this login session predates dialout membership).
|
||||||
|
- Nothing else holding the port (no `idf.py monitor` running) — one owner only.
|
||||||
|
|
||||||
|
## Take a shot
|
||||||
|
|
||||||
|
From the `desklock` repo root (`/mnt/media/Projects/desklock`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# current screen (whatever state the device is in right now)
|
||||||
|
sg dialout -c "python3 firmware/tools/device_shot.py /tmp/shot.png"
|
||||||
|
|
||||||
|
# force the tap controls overlay in-frame (mic + volume) — for verifying it
|
||||||
|
# remotely since you can't physically tap
|
||||||
|
sg dialout -c "python3 firmware/tools/device_shot.py /tmp/shot.png --overlay"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then **Read `/tmp/shot.png`** to view it. A clean run prints
|
||||||
|
`[try 1] 400x400 320000B crc … OK` and takes ~5 s.
|
||||||
|
|
||||||
|
Trigger bytes: `s` = current screen, `o` = force overlay. The tool retries up to
|
||||||
|
4× on a CRC mismatch (occasional console contention), so a transient bad frame
|
||||||
|
self-heals.
|
||||||
|
|
||||||
|
## Notes / caveats
|
||||||
|
|
||||||
|
- **RAM / render path:** the watcher costs one ~5 KB internal-RAM task, so it's
|
||||||
|
behind `DESKLOCK_DEVMODE` (off by default). Internal RAM is the scarce resource
|
||||||
|
on this board (it caps the rain sprite pool). Never ship a production build with
|
||||||
|
it on.
|
||||||
|
- 400×400 is plenty for layout/UI checks. To change resolution, adjust `SHOT_DS`
|
||||||
|
in `face.c` (the downscale factor) — the host reads the size from the header.
|
||||||
|
- If you just reflashed, wait ~7 s for boot before the first shot.
|
||||||
|
- Only the USB console path is used; this does not touch the device↔gateway
|
||||||
|
WebSocket protocol.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
.pql/changelog/*.sql merge=union
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
- name: Login to Gitea Registry
|
- name: Login to Gitea Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: git.schweitz.internal
|
registry: git.schweitz.net
|
||||||
username: ${{ secrets.REGISTRY_USER }}
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
@@ -61,11 +61,11 @@ jobs:
|
|||||||
provenance: false
|
provenance: false
|
||||||
sbom: false
|
sbom: false
|
||||||
tags: |
|
tags: |
|
||||||
git.schweitz.internal/jpmschweitzer/desklock-gateway:latest
|
git.schweitz.net/jpmschweitzer/desklock-gateway:latest
|
||||||
git.schweitz.internal/jpmschweitzer/desklock-gateway:${{ github.ref_name }}
|
git.schweitz.net/jpmschweitzer/desklock-gateway:${{ github.ref_name }}
|
||||||
|
|
||||||
- name: Trigger Watchtower update
|
- name: Trigger Watchtower update
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
curl -sf -H "Authorization: Bearer ${{ secrets.WATCHTOWER_TOKEN }}" \
|
curl -sf -H "Authorization: Bearer ${{ secrets.WATCHTOWER_HTTP_API_TOKEN }}" \
|
||||||
http://watchtower:8080/v1/update
|
http://watchtower:8080/v1/update
|
||||||
|
|||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Trigger only. The checks live in the Makefile, where they can be read, run by
|
||||||
|
# hand (`make pre-push`), and changed under review.
|
||||||
|
#
|
||||||
|
# This file is identical in every repo in this workspace, deliberately: the call
|
||||||
|
# surface is the same everywhere even though what each gate runs is not, so
|
||||||
|
# nobody has to read a repo to find out how to check it (D-27).
|
||||||
|
#
|
||||||
|
# Enable per clone with: git config core.hooksPath .githooks
|
||||||
|
# Never bypass with --no-verify. Suppress a specific finding deliberately
|
||||||
|
# instead, with a reason — see `make pre-push`.
|
||||||
|
set -euo pipefail
|
||||||
|
exec make -C "$(git rev-parse --show-toplevel)" pre-push
|
||||||
+15
-1
@@ -4,7 +4,7 @@ firmware/managed_components/
|
|||||||
firmware/sdkconfig
|
firmware/sdkconfig
|
||||||
firmware/sdkconfig.old
|
firmware/sdkconfig.old
|
||||||
firmware/dependencies.lock
|
firmware/dependencies.lock
|
||||||
firmware/secrets.h
|
firmware/main/secrets.h
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@@ -21,3 +21,17 @@ dist/
|
|||||||
.idea/
|
.idea/
|
||||||
*.swp
|
*.swp
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Claude Code local overrides (per-machine, may hold credentials)
|
||||||
|
.claude/settings.local.json
|
||||||
|
|
||||||
|
.pql/*
|
||||||
|
!.pql/changelog/
|
||||||
|
|
||||||
|
# pql shims planted by `pql init` into the dir core.hooksPath points at.
|
||||||
|
# Per-clone: each embeds the absolute path of the pql binary that planted it.
|
||||||
|
# Only .githooks/pre-push is shared.
|
||||||
|
.githooks/pre-commit
|
||||||
|
.githooks/post-merge
|
||||||
|
.githooks/post-checkout
|
||||||
|
.githooks/post-rewrite
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-- Changelog format marker, written by pql. Comments only: this file
|
||||||
|
-- is never executed — Import descends into the per-table directories
|
||||||
|
-- and does not read the changelog root.
|
||||||
|
--
|
||||||
|
-- A changelog carrying no marker is format 1, the shape that existed
|
||||||
|
-- before formats were versioned. An older format is migrated forward
|
||||||
|
-- by `pql plan upgrade` (and automatically from the post-merge hook);
|
||||||
|
-- a newer one is refused rather than replayed under rules this binary
|
||||||
|
-- does not know. See D-28 and docs/versions.md.
|
||||||
|
-- pql:changelog_format: 2.0.0
|
||||||
|
-- pql:written_by: 2.2.0
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
-- Auto-generated by pql init. CREATE TABLE statements
|
||||||
|
-- for the planning schema; per-table dir keeps the changelog
|
||||||
|
-- self-describing per D-15. CREATE TABLE IF NOT EXISTS is
|
||||||
|
-- idempotent so running schema files from each directory in
|
||||||
|
-- replay order is harmless.
|
||||||
|
--
|
||||||
|
-- Importer parses the markers below to detect schema drift
|
||||||
|
-- between the producing pql version and the local one — a
|
||||||
|
-- bumped canonical_version means projection rules changed
|
||||||
|
-- and replay must refuse rather than silently corrupt state.
|
||||||
|
-- pql:created_by: 2.2.0
|
||||||
|
-- pql:canonical_version: 2
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('confirmed','question','rejected')),
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active'
|
||||||
|
CHECK(status IN ('active','superseded','resolved','open')),
|
||||||
|
date TEXT,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
synced_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decision_refs (
|
||||||
|
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
ref_type TEXT NOT NULL
|
||||||
|
CHECK(ref_type IN ('supersedes','references','resolves','depends_on','amends')),
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (source_id, target_id, ref_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Identity split (D-26): a ticket's stable, collision-proof identity is its
|
||||||
|
-- record_id (a locally-generated ULID, planning.NewRecordID); the friendly
|
||||||
|
-- T-NNN label lives in ticket_idmap and may be reconciled. Every structural
|
||||||
|
-- reference (parent, deps, history, labels) targets record_id, so a label
|
||||||
|
-- clash never corrupts the graph — only ticket_idmap needs a relabel.
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
record_id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('initiative','epic','story','task','bug')),
|
||||||
|
parent_record_id TEXT REFERENCES tickets(record_id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
-- No CHECK enumeration: the ticket status vocabulary is per-vault
|
||||||
|
-- configurable (ticket_statuses in .pql/config.yaml). Validation lives
|
||||||
|
-- in Go (planning.StatusSet), so adding/renaming statuses needs no
|
||||||
|
-- schema change. The DEFAULT is a harmless fallback — CreateTicket
|
||||||
|
-- always inserts the configured default explicitly.
|
||||||
|
status TEXT NOT NULL DEFAULT 'backlog',
|
||||||
|
priority TEXT DEFAULT 'medium'
|
||||||
|
CHECK(priority IN ('critical','high','medium','low')),
|
||||||
|
assigned_to TEXT,
|
||||||
|
team TEXT,
|
||||||
|
decision_ref TEXT REFERENCES decisions(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ticket_idmap maps a record_id to its current friendly label (T-NNN).
|
||||||
|
-- ticket_id is intentionally NOT globally unique: two uncoordinated clones
|
||||||
|
-- can mint the same label, which surfaces as a duplicate-label collision
|
||||||
|
-- (detected at replay) and is fixed with "pql ticket relabel".
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_idmap (
|
||||||
|
record_id TEXT PRIMARY KEY REFERENCES tickets(record_id),
|
||||||
|
ticket_id TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_deps (
|
||||||
|
blocker_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
blocked_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (blocker_record_id, blocked_record_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_history (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
field TEXT NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_by TEXT,
|
||||||
|
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT UNIQUE,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_labels (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (ticket_record_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_decision_ref ON tickets(decision_ref);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_record_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_ticket_idmap_label ON ticket_idmap(ticket_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
-- Auto-generated by pql init. CREATE TABLE statements
|
||||||
|
-- for the planning schema; per-table dir keeps the changelog
|
||||||
|
-- self-describing per D-15. CREATE TABLE IF NOT EXISTS is
|
||||||
|
-- idempotent so running schema files from each directory in
|
||||||
|
-- replay order is harmless.
|
||||||
|
--
|
||||||
|
-- Importer parses the markers below to detect schema drift
|
||||||
|
-- between the producing pql version and the local one — a
|
||||||
|
-- bumped canonical_version means projection rules changed
|
||||||
|
-- and replay must refuse rather than silently corrupt state.
|
||||||
|
-- pql:created_by: 2.2.0
|
||||||
|
-- pql:canonical_version: 2
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('confirmed','question','rejected')),
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active'
|
||||||
|
CHECK(status IN ('active','superseded','resolved','open')),
|
||||||
|
date TEXT,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
synced_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decision_refs (
|
||||||
|
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
ref_type TEXT NOT NULL
|
||||||
|
CHECK(ref_type IN ('supersedes','references','resolves','depends_on','amends')),
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (source_id, target_id, ref_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Identity split (D-26): a ticket's stable, collision-proof identity is its
|
||||||
|
-- record_id (a locally-generated ULID, planning.NewRecordID); the friendly
|
||||||
|
-- T-NNN label lives in ticket_idmap and may be reconciled. Every structural
|
||||||
|
-- reference (parent, deps, history, labels) targets record_id, so a label
|
||||||
|
-- clash never corrupts the graph — only ticket_idmap needs a relabel.
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
record_id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('initiative','epic','story','task','bug')),
|
||||||
|
parent_record_id TEXT REFERENCES tickets(record_id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
-- No CHECK enumeration: the ticket status vocabulary is per-vault
|
||||||
|
-- configurable (ticket_statuses in .pql/config.yaml). Validation lives
|
||||||
|
-- in Go (planning.StatusSet), so adding/renaming statuses needs no
|
||||||
|
-- schema change. The DEFAULT is a harmless fallback — CreateTicket
|
||||||
|
-- always inserts the configured default explicitly.
|
||||||
|
status TEXT NOT NULL DEFAULT 'backlog',
|
||||||
|
priority TEXT DEFAULT 'medium'
|
||||||
|
CHECK(priority IN ('critical','high','medium','low')),
|
||||||
|
assigned_to TEXT,
|
||||||
|
team TEXT,
|
||||||
|
decision_ref TEXT REFERENCES decisions(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ticket_idmap maps a record_id to its current friendly label (T-NNN).
|
||||||
|
-- ticket_id is intentionally NOT globally unique: two uncoordinated clones
|
||||||
|
-- can mint the same label, which surfaces as a duplicate-label collision
|
||||||
|
-- (detected at replay) and is fixed with "pql ticket relabel".
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_idmap (
|
||||||
|
record_id TEXT PRIMARY KEY REFERENCES tickets(record_id),
|
||||||
|
ticket_id TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_deps (
|
||||||
|
blocker_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
blocked_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (blocker_record_id, blocked_record_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_history (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
field TEXT NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_by TEXT,
|
||||||
|
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT UNIQUE,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_labels (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (ticket_record_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_decision_ref ON tickets(decision_ref);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_record_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_ticket_idmap_label ON ticket_idmap(ticket_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
-- Auto-generated by pql init. CREATE TABLE statements
|
||||||
|
-- for the planning schema; per-table dir keeps the changelog
|
||||||
|
-- self-describing per D-15. CREATE TABLE IF NOT EXISTS is
|
||||||
|
-- idempotent so running schema files from each directory in
|
||||||
|
-- replay order is harmless.
|
||||||
|
--
|
||||||
|
-- Importer parses the markers below to detect schema drift
|
||||||
|
-- between the producing pql version and the local one — a
|
||||||
|
-- bumped canonical_version means projection rules changed
|
||||||
|
-- and replay must refuse rather than silently corrupt state.
|
||||||
|
-- pql:created_by: 2.2.0
|
||||||
|
-- pql:canonical_version: 2
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('confirmed','question','rejected')),
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active'
|
||||||
|
CHECK(status IN ('active','superseded','resolved','open')),
|
||||||
|
date TEXT,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
synced_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decision_refs (
|
||||||
|
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
ref_type TEXT NOT NULL
|
||||||
|
CHECK(ref_type IN ('supersedes','references','resolves','depends_on','amends')),
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (source_id, target_id, ref_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Identity split (D-26): a ticket's stable, collision-proof identity is its
|
||||||
|
-- record_id (a locally-generated ULID, planning.NewRecordID); the friendly
|
||||||
|
-- T-NNN label lives in ticket_idmap and may be reconciled. Every structural
|
||||||
|
-- reference (parent, deps, history, labels) targets record_id, so a label
|
||||||
|
-- clash never corrupts the graph — only ticket_idmap needs a relabel.
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
record_id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('initiative','epic','story','task','bug')),
|
||||||
|
parent_record_id TEXT REFERENCES tickets(record_id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
-- No CHECK enumeration: the ticket status vocabulary is per-vault
|
||||||
|
-- configurable (ticket_statuses in .pql/config.yaml). Validation lives
|
||||||
|
-- in Go (planning.StatusSet), so adding/renaming statuses needs no
|
||||||
|
-- schema change. The DEFAULT is a harmless fallback — CreateTicket
|
||||||
|
-- always inserts the configured default explicitly.
|
||||||
|
status TEXT NOT NULL DEFAULT 'backlog',
|
||||||
|
priority TEXT DEFAULT 'medium'
|
||||||
|
CHECK(priority IN ('critical','high','medium','low')),
|
||||||
|
assigned_to TEXT,
|
||||||
|
team TEXT,
|
||||||
|
decision_ref TEXT REFERENCES decisions(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ticket_idmap maps a record_id to its current friendly label (T-NNN).
|
||||||
|
-- ticket_id is intentionally NOT globally unique: two uncoordinated clones
|
||||||
|
-- can mint the same label, which surfaces as a duplicate-label collision
|
||||||
|
-- (detected at replay) and is fixed with "pql ticket relabel".
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_idmap (
|
||||||
|
record_id TEXT PRIMARY KEY REFERENCES tickets(record_id),
|
||||||
|
ticket_id TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_deps (
|
||||||
|
blocker_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
blocked_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (blocker_record_id, blocked_record_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_history (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
field TEXT NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_by TEXT,
|
||||||
|
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT UNIQUE,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_labels (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (ticket_record_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_decision_ref ON tickets(decision_ref);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_record_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_ticket_idmap_label ON ticket_idmap(ticket_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
-- Auto-generated by pql init. CREATE TABLE statements
|
||||||
|
-- for the planning schema; per-table dir keeps the changelog
|
||||||
|
-- self-describing per D-15. CREATE TABLE IF NOT EXISTS is
|
||||||
|
-- idempotent so running schema files from each directory in
|
||||||
|
-- replay order is harmless.
|
||||||
|
--
|
||||||
|
-- Importer parses the markers below to detect schema drift
|
||||||
|
-- between the producing pql version and the local one — a
|
||||||
|
-- bumped canonical_version means projection rules changed
|
||||||
|
-- and replay must refuse rather than silently corrupt state.
|
||||||
|
-- pql:created_by: 2.2.0
|
||||||
|
-- pql:canonical_version: 2
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('confirmed','question','rejected')),
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active'
|
||||||
|
CHECK(status IN ('active','superseded','resolved','open')),
|
||||||
|
date TEXT,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
synced_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decision_refs (
|
||||||
|
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
ref_type TEXT NOT NULL
|
||||||
|
CHECK(ref_type IN ('supersedes','references','resolves','depends_on','amends')),
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (source_id, target_id, ref_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Identity split (D-26): a ticket's stable, collision-proof identity is its
|
||||||
|
-- record_id (a locally-generated ULID, planning.NewRecordID); the friendly
|
||||||
|
-- T-NNN label lives in ticket_idmap and may be reconciled. Every structural
|
||||||
|
-- reference (parent, deps, history, labels) targets record_id, so a label
|
||||||
|
-- clash never corrupts the graph — only ticket_idmap needs a relabel.
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
record_id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('initiative','epic','story','task','bug')),
|
||||||
|
parent_record_id TEXT REFERENCES tickets(record_id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
-- No CHECK enumeration: the ticket status vocabulary is per-vault
|
||||||
|
-- configurable (ticket_statuses in .pql/config.yaml). Validation lives
|
||||||
|
-- in Go (planning.StatusSet), so adding/renaming statuses needs no
|
||||||
|
-- schema change. The DEFAULT is a harmless fallback — CreateTicket
|
||||||
|
-- always inserts the configured default explicitly.
|
||||||
|
status TEXT NOT NULL DEFAULT 'backlog',
|
||||||
|
priority TEXT DEFAULT 'medium'
|
||||||
|
CHECK(priority IN ('critical','high','medium','low')),
|
||||||
|
assigned_to TEXT,
|
||||||
|
team TEXT,
|
||||||
|
decision_ref TEXT REFERENCES decisions(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ticket_idmap maps a record_id to its current friendly label (T-NNN).
|
||||||
|
-- ticket_id is intentionally NOT globally unique: two uncoordinated clones
|
||||||
|
-- can mint the same label, which surfaces as a duplicate-label collision
|
||||||
|
-- (detected at replay) and is fixed with "pql ticket relabel".
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_idmap (
|
||||||
|
record_id TEXT PRIMARY KEY REFERENCES tickets(record_id),
|
||||||
|
ticket_id TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_deps (
|
||||||
|
blocker_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
blocked_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (blocker_record_id, blocked_record_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_history (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
field TEXT NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_by TEXT,
|
||||||
|
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT UNIQUE,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_labels (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (ticket_record_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_decision_ref ON tickets(decision_ref);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_record_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_ticket_idmap_label ON ticket_idmap(ticket_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
-- Auto-generated by pql init. CREATE TABLE statements
|
||||||
|
-- for the planning schema; per-table dir keeps the changelog
|
||||||
|
-- self-describing per D-15. CREATE TABLE IF NOT EXISTS is
|
||||||
|
-- idempotent so running schema files from each directory in
|
||||||
|
-- replay order is harmless.
|
||||||
|
--
|
||||||
|
-- Importer parses the markers below to detect schema drift
|
||||||
|
-- between the producing pql version and the local one — a
|
||||||
|
-- bumped canonical_version means projection rules changed
|
||||||
|
-- and replay must refuse rather than silently corrupt state.
|
||||||
|
-- pql:created_by: 2.2.0
|
||||||
|
-- pql:canonical_version: 2
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('confirmed','question','rejected')),
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active'
|
||||||
|
CHECK(status IN ('active','superseded','resolved','open')),
|
||||||
|
date TEXT,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
synced_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS decision_refs (
|
||||||
|
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||||
|
ref_type TEXT NOT NULL
|
||||||
|
CHECK(ref_type IN ('supersedes','references','resolves','depends_on','amends')),
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (source_id, target_id, ref_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Identity split (D-26): a ticket's stable, collision-proof identity is its
|
||||||
|
-- record_id (a locally-generated ULID, planning.NewRecordID); the friendly
|
||||||
|
-- T-NNN label lives in ticket_idmap and may be reconciled. Every structural
|
||||||
|
-- reference (parent, deps, history, labels) targets record_id, so a label
|
||||||
|
-- clash never corrupts the graph — only ticket_idmap needs a relabel.
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
record_id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL CHECK(type IN ('initiative','epic','story','task','bug')),
|
||||||
|
parent_record_id TEXT REFERENCES tickets(record_id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
-- No CHECK enumeration: the ticket status vocabulary is per-vault
|
||||||
|
-- configurable (ticket_statuses in .pql/config.yaml). Validation lives
|
||||||
|
-- in Go (planning.StatusSet), so adding/renaming statuses needs no
|
||||||
|
-- schema change. The DEFAULT is a harmless fallback — CreateTicket
|
||||||
|
-- always inserts the configured default explicitly.
|
||||||
|
status TEXT NOT NULL DEFAULT 'backlog',
|
||||||
|
priority TEXT DEFAULT 'medium'
|
||||||
|
CHECK(priority IN ('critical','high','medium','low')),
|
||||||
|
assigned_to TEXT,
|
||||||
|
team TEXT,
|
||||||
|
decision_ref TEXT REFERENCES decisions(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ticket_idmap maps a record_id to its current friendly label (T-NNN).
|
||||||
|
-- ticket_id is intentionally NOT globally unique: two uncoordinated clones
|
||||||
|
-- can mint the same label, which surfaces as a duplicate-label collision
|
||||||
|
-- (detected at replay) and is fixed with "pql ticket relabel".
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_idmap (
|
||||||
|
record_id TEXT PRIMARY KEY REFERENCES tickets(record_id),
|
||||||
|
ticket_id TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_deps (
|
||||||
|
blocker_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
blocked_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (blocker_record_id, blocked_record_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_history (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
field TEXT NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_by TEXT,
|
||||||
|
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT UNIQUE,
|
||||||
|
canonical_version INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ticket_labels (
|
||||||
|
ticket_record_id TEXT NOT NULL REFERENCES tickets(record_id),
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
deleted_at TEXT,
|
||||||
|
hash TEXT,
|
||||||
|
canonical_version INTEGER,
|
||||||
|
PRIMARY KEY (ticket_record_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_decision_ref ON tickets(decision_ref);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_record_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_ticket_idmap_label ON ticket_idmap(ticket_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
# AGENTS.md
|
|
||||||
|
|
||||||
> Operational protocols and architecture for AI assistants working on DeskLock.
|
|
||||||
> Read [docs/architecture.md](docs/architecture.md) before making design changes.
|
|
||||||
|
|
||||||
## What this project is
|
|
||||||
|
|
||||||
DeskLock is the living-room visual/audio endpoint for **Tatlock**, the homelab butler
|
|
||||||
(`/mnt/media/Projects/tatlock`, API at `http://tatlock.schweitz.internal:8000`). Two halves,
|
|
||||||
one repo:
|
|
||||||
|
|
||||||
- `firmware/` — ESP-IDF (C, LVGL 9) app for the Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C
|
|
||||||
(3.4" round 800×800 touch display, dual mics + ES7210 AEC, ES8311 codec + speaker).
|
|
||||||
- `gateway/` — Python FastAPI container on tower-of-joy orchestrating STT → chat
|
|
||||||
(Tatlock `/v1/chat/completions`) → TTS. Listens on port **8600**. STT/TTS models live
|
|
||||||
in the shared **Speaches** container (live on port 8601, OpenAI-format API), not in
|
|
||||||
the gateway image; `stt.py`/`tts.py` are pluggable backends (`speaches` default,
|
|
||||||
`embedded` fallback needing the `[speech]` extra). Gateway needs **Python ≥ 3.11**
|
|
||||||
(no ceiling; the container runs 3.13) — but system python3 on tower-of-joy is 3.8,
|
|
||||||
so `make setup` explicitly uses `python3.12`. No local audio resampling in the
|
|
||||||
default path: the gateway requests 16 kHz output via Speaches' `sample_rate`
|
|
||||||
extension (verified live).
|
|
||||||
|
|
||||||
The device and gateway speak a WebSocket protocol defined in `docs/architecture.md`.
|
|
||||||
**That doc is the contract** — update it in the same change as any protocol edit on
|
|
||||||
either side.
|
|
||||||
|
|
||||||
The face (black screen, ASCII glyph expressions, matrix rain as activity signal) is
|
|
||||||
designed in `sim/face/index.html` — the design source of truth — and specified in the
|
|
||||||
"Face design" section of `docs/architecture.md`. Change the sim and the doc together;
|
|
||||||
the LVGL implementation follows them. Verify sim changes visually with
|
|
||||||
`~/bin/claude-screenshot` (note: the tool uses `--virtual-time-budget`, which starves
|
|
||||||
`requestAnimationFrame` — drive sim animation with `setInterval`, which also mirrors
|
|
||||||
LVGL timers).
|
|
||||||
|
|
||||||
## Hard rules
|
|
||||||
|
|
||||||
- **Keep the firmware thin.** No STT, no TTS, no conversation logic on the device.
|
|
||||||
If a feature needs intelligence, it goes in the gateway or in Tatlock itself.
|
|
||||||
- **Never modify Tatlock from this repo.** It is a separate project with its own repo.
|
|
||||||
DeskLock consumes its public API only.
|
|
||||||
- **Secrets** (Wi-Fi credentials, any future API keys) never go in source. Firmware
|
|
||||||
gets them via a gitignored `firmware/secrets.h` (see AGENTS notes below) or NVS;
|
|
||||||
the gateway via environment variables (`DESKLOCK_*`).
|
|
||||||
|
|
||||||
## Firmware (`firmware/`)
|
|
||||||
|
|
||||||
- Toolchain: **ESP-IDF ≥ 5.4** (not Arduino, not PlatformIO). Target `esp32p4`.
|
|
||||||
- BSP: [`waveshare/esp32_p4_wifi6_touch_lcd_xc`](https://components.espressif.com/components/waveshare/esp32_p4_wifi6_touch_lcd_xc)
|
|
||||||
from the ESP Component Registry (pulled automatically via `main/idf_component.yml`).
|
|
||||||
- Reference implementations: [waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC](https://github.com/waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC)
|
|
||||||
`examples/esp-idf/` — notably `08_lvgl_demo_v9` (display), `06_I2SCodec` (audio),
|
|
||||||
`04_wifistation` (Wi-Fi via ESP-Hosted). When wiring a new peripheral, check the
|
|
||||||
official example first; do not guess pin mappings.
|
|
||||||
- ⚠️ **Unverified scaffold**: the BSP API calls in `desklock_main.c` and the
|
|
||||||
`sdkconfig.defaults` values were written before the first successful build. Validate
|
|
||||||
against the official examples on first bring-up, then delete this warning.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# One-time: install ESP-IDF (not yet installed on tower-of-joy)
|
|
||||||
git clone -b v5.5 --recursive https://github.com/espressif/esp-idf.git ~/esp-idf
|
|
||||||
~/esp-idf/install.sh esp32p4
|
|
||||||
|
|
||||||
# Every shell:
|
|
||||||
source ~/esp-idf/export.sh
|
|
||||||
|
|
||||||
# Build / flash / monitor (device is on USB-C; check `ls /dev/ttyACM*`)
|
|
||||||
cd firmware
|
|
||||||
idf.py set-target esp32p4 # once
|
|
||||||
idf.py build
|
|
||||||
idf.py -p /dev/ttyACM0 flash monitor # Ctrl+] exits monitor
|
|
||||||
```
|
|
||||||
|
|
||||||
Flashing requires the `dialout` group (or run with sudo once and fix the group). If the
|
|
||||||
device doesn't enumerate, hold BOOT while pressing RESET to enter download mode.
|
|
||||||
|
|
||||||
## Gateway (`gateway/`)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd gateway
|
|
||||||
make setup # venv + dev deps (no ML models)
|
|
||||||
make setup-speech # additionally install faster-whisper + piper
|
|
||||||
make run # uvicorn on :8600 with reload
|
|
||||||
make test # pytest
|
|
||||||
make lint # ruff check + format check
|
|
||||||
make typecheck # mypy
|
|
||||||
```
|
|
||||||
|
|
||||||
- Config via `DESKLOCK_*` env vars — see `src/desklock_gateway/config.py` for the schema
|
|
||||||
and defaults.
|
|
||||||
- `stt.py` / `tts.py` defer their heavy imports so the app boots without the `speech`
|
|
||||||
extra — keep it that way so protocol tests stay fast.
|
|
||||||
- Deployment is CI-driven: pushing a `v*` tag makes Gitea Actions test, build, and push
|
|
||||||
`desklock-gateway:{latest,tag}` to the registry and trigger Watchtower
|
|
||||||
(`.gitea/workflows/build.yml`; needs `REGISTRY_USER`/`REGISTRY_PASSWORD`/
|
|
||||||
`WATCHTOWER_TOKEN` secrets). Plain pushes to `main` run lint + tests only. The
|
|
||||||
gateway deploys as part of the **`tatlock-ui` Portainer stack** —
|
|
||||||
`system-admin-toj/containers/stacks/tatlock-ui.yml` (registered in `CONTAINERS.md`,
|
|
||||||
port 8600). Stack updates go through the Portainer API on :8001 (JWT auth; recipe in
|
|
||||||
`system-admin-toj/containers/setup-new-host.md`), not by editing files on disk.
|
|
||||||
- Verify speech changes against the live Speaches container with a real round trip
|
|
||||||
(TTS → STT of a known phrase, expect the transcript back); warm timings to expect:
|
|
||||||
STT ~0.3 s, TTS ~2 s per sentence.
|
|
||||||
|
|
||||||
## Homelab context
|
|
||||||
|
|
||||||
- This server **is** tower-of-joy; the device, gateway, and Tatlock all share the LAN.
|
|
||||||
- Use `tatlock.schweitz.internal:8000` (direct, no SSO) — the public
|
|
||||||
`tatlock.schweitz.net` route sits behind Authentik and is not for machine-to-machine
|
|
||||||
traffic.
|
|
||||||
- Git remote: `git.schweitz.net` (Gitea).
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable, user-facing changes to DeskLock are documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||||
|
DeskLock is pre-release and unversioned; entries accumulate under **Unreleased**
|
||||||
|
until the first tagged release.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- One Makefile at the repo root now drives firmware, gateway and sim; `gateway/Makefile` is
|
||||||
|
removed. `make test` means the same thing from any directory.
|
||||||
|
- Firmware targets source `~/esp-idf/export.sh` themselves, so `idf.py` resolves without
|
||||||
|
having to remember. Override the location with `IDF_EXPORT=`.
|
||||||
|
- `make setup` now proves the gateway environment actually works instead of trusting a
|
||||||
|
clean `pip install` exit code: it collects the test suite and checks `ruff`/`mypy`
|
||||||
|
resolve in the venv, and fails the target if any of that is broken (T-47).
|
||||||
|
|
||||||
|
## [0.2.2] — 2026-07-19
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- The gateway's default Tatlock URL is now `http://tatlock:8000` (docker
|
||||||
|
container name) — the retiring `tatlock.schweitz.internal` domain is gone
|
||||||
|
from config and docs. Deployments setting `DESKLOCK_TATLOCK_BASE_URL` are
|
||||||
|
unaffected.
|
||||||
|
|
||||||
|
## [0.2.1] — 2026-07-15
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- A spoken volume command no longer leaves the face stuck in the thinking
|
||||||
|
spinner — the feedback gong is a UI cue and no longer holds the busy state,
|
||||||
|
so the return-to-idle isn't swallowed.
|
||||||
|
- The butler filler line reads as one phrase instead of two — reworded to "Let
|
||||||
|
me check on that, sir." to avoid a text-to-speech pause before "for you".
|
||||||
|
|
||||||
|
## [0.2.0] — 2026-07-15
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- After a request, the butler immediately says "Let me check on that for you,
|
||||||
|
sir" and keeps a spinner up while it works, so the long wait isn't dead air.
|
||||||
|
- Spoken volume commands ("volume up/down", "mute/unmute", "set volume to N",
|
||||||
|
"this one goes to eleven") are handled instantly on the gateway, bypassing the
|
||||||
|
assistant — no waiting on a reply just to change the volume.
|
||||||
|
- Tap the screen to reveal on-screen controls — a microphone button plus volume
|
||||||
|
down/up and a live level bar, using Phosphor icon glyphs. Tapping the dimmed
|
||||||
|
backdrop dismisses them.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed the blue-screen flicker during voice activity — the matrix rain now
|
||||||
|
renders as cheap pre-rendered sprites, and the DSI clocks/FIFO are tuned, so
|
||||||
|
the display's memory reads are no longer starved by Wi-Fi and audio DMA.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Volume is now an 0–11 scale (it goes to eleven) with a gong cue on each change
|
||||||
|
and a little "11" that floats off the bar at maximum.
|
||||||
|
- Matrix rain is drawn from a reused pool of pre-rendered streak sprites instead
|
||||||
|
of live text labels, and eases off while the device is listening or speaking.
|
||||||
@@ -1,38 +1,189 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md — desklock
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
Two components, one repo, coupled by a shared WebSocket protocol:
|
||||||
|
|
||||||
Claude Code-specific notes for this project. For architecture, hard rules, and full
|
- `firmware/` — ESP-IDF (C, LVGL 9) app for a Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C
|
||||||
command reference — see [AGENTS.md](AGENTS.md), and read it before starting work.
|
(3.4" round 800×800 touch display, dual mics + ES7210 AEC, ES8311 codec + speaker).
|
||||||
|
Flashed over USB; not containerized.
|
||||||
|
- `gateway/` — Python/FastAPI container `desklock-gateway`, port **8600**, part of the
|
||||||
|
**`tatlock-ui`** Portainer stack (`system-admin-toj/containers/stacks/tatlock-ui.yml`,
|
||||||
|
verified against the live container and `CONTAINERS.md`). Orchestrates STT → Tatlock
|
||||||
|
chat → TTS; carries no ML dependencies itself.
|
||||||
|
|
||||||
## Quick orientation
|
The device↔gateway protocol is specified in `docs/architecture.md` under "WebSocket
|
||||||
|
protocol (device ↔ gateway)". **Any protocol change updates that file in the same
|
||||||
|
change** — it is the contract, not a description of one side's behavior.
|
||||||
|
|
||||||
DeskLock = firmware for a Waveshare ESP32-P4 round-display device (`firmware/`, ESP-IDF/C/LVGL)
|
**Never modify Tatlock from this repo.** desklock consumes Tatlock's public API only
|
||||||
plus a voice gateway container (`gateway/`, Python/FastAPI, port 8600) that bridges device
|
(`http://tatlock:8000` on `docker-dataplane`); this is a standing cross-repo rule, not
|
||||||
audio to the Tatlock butler API. The device↔gateway WebSocket protocol lives in
|
local policy.
|
||||||
`docs/architecture.md` and must stay in sync with both implementations.
|
|
||||||
|
**Keep the firmware thin.** No STT, no TTS, no conversation logic on the device — that
|
||||||
|
intelligence belongs in the gateway or in Tatlock itself.
|
||||||
|
|
||||||
|
**Secrets never go in source.** Firmware gets them via gitignored `firmware/main/secrets.h`
|
||||||
|
(verified: gitignored, and `#include`d by `gw_client.c`/`net.c`) or NVS; the gateway via
|
||||||
|
`DESKLOCK_*` environment variables.
|
||||||
|
|
||||||
|
## Gotchas — firmware
|
||||||
|
|
||||||
|
- Toolchain: **ESP-IDF ≥ 5.4** (this box has 5.5, installed at `~/esp-idf`), not
|
||||||
|
Arduino, not PlatformIO. Target `esp32p4`. `source ~/esp-idf/export.sh` is required
|
||||||
|
every shell — `idf.py` is not on the non-interactive PATH otherwise.
|
||||||
|
- BSP: `waveshare/esp32_p4_wifi6_touch_lcd_xc` from the ESP Component Registry, pulled
|
||||||
|
automatically via `main/idf_component.yml`. Reference implementations:
|
||||||
|
[waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC](https://github.com/waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC)
|
||||||
|
`examples/esp-idf/` — `08_lvgl_demo_v9` (display), `06_I2SCodec` (audio),
|
||||||
|
`04_wifistation` (Wi-Fi). Check the official example before guessing a pin mapping.
|
||||||
|
- Flashing needs the `dialout` group; a login session started before that membership
|
||||||
|
took effect needs `sg dialout -c "bash -lc 'source ~/esp-idf/export.sh >/dev/null &&
|
||||||
|
idf.py -p /dev/ttyACM0 flash'"` — a plain `idf.py flash` works after any re-login.
|
||||||
|
- **PSRAM 200 MHz requires `CONFIG_IDF_EXPERIMENTAL_FEATURES=y`.** Without it,
|
||||||
|
`CONFIG_SPIRAM_SPEED_200M` is silently dropped to 20 MHz and the 800×800 MIPI-DSI
|
||||||
|
framebuffer underruns (`lcd.dsi.dpi: can't fetch data…` spam, LVGL lock never frees,
|
||||||
|
task watchdog). Verified both settings present in `firmware/sdkconfig.defaults`.
|
||||||
|
- **Wi-Fi radio stack must be esp_hosted ≥ 2.x on both the P4 host and the C6 slave,
|
||||||
|
non-negotiable.** 1.x is formally incompatible with IDF 5.5 (esp-hosted-mcu#47) —
|
||||||
|
symptom is control-plane-only: RPC/scan/connect all work, but no data frame ever
|
||||||
|
flows (no DHCP, no ARP, no ping). Waveshare's examples and the factory C6 slave
|
||||||
|
firmware both pin the wrong (1.x-era) version. The host manifest pins
|
||||||
|
`espressif/esp_hosted: "^2.12"` (verified in `firmware/main/idf_component.yml`); the
|
||||||
|
matching slave image is embedded as `main/c6_slave.bin`, and `c6_ota.c` flashes the
|
||||||
|
C6 over SDIO at boot whenever it reports a version below 2.x.
|
||||||
|
- **Boot-loop assert `xTaskCreateStaticPinnedToCore … xPortcheckValidStackMem`** before
|
||||||
|
`app_main` means internal SRAM starvation (hosted 2.x is hungry). Keep
|
||||||
|
`CONFIG_ESP_HOSTED_MEMPOOL_PREFER_SPIRAM=y` and the reduced `WIFI_RMT_*` buffer counts
|
||||||
|
in `sdkconfig.defaults` (both verified present); check `heap_init:` pool lines in the
|
||||||
|
boot log when the binary grows.
|
||||||
|
- SDIO clock is conservative by design: `CONFIG_ESP_HOSTED_SDIO_CLOCK_FREQ_KHZ=20000`
|
||||||
|
(verified), ample for 16 kHz voice — raising it to 40 MHz is untested on this board's
|
||||||
|
data path.
|
||||||
|
- **Wi-Fi diagnosis ladder**: set `WIFI_DIAG_MODE 1` in `desklock_main.c` (verified the
|
||||||
|
macro and `#if` guard exist, currently `0`) — the device becomes AP `DESKLOCK-DIAG`
|
||||||
|
(password `desklock123`, page at `http://192.168.4.1/`, verified in `wifi_diag.c`),
|
||||||
|
proving radio+SDIO+IP with zero external network variables. Ladder: L0 SDIO control →
|
||||||
|
L1 softap data → L2 STA to any network → L3 STA to "Outside" → L4 gateway.
|
||||||
|
- Non-interactive boot-log capture: avoid `idf.py monitor` (interactive) — open
|
||||||
|
`/dev/ttyACM0` at 115200 with pyserial, pulse RTS to reset, read ~8s. Reported boot
|
||||||
|
time (~1.6s to `desklock: DeskLock up`) is carried from `AGENTS.md` and was **not**
|
||||||
|
re-timed this pass — no device was connected in this session (see Liveness below).
|
||||||
|
- If the device doesn't enumerate, hold BOOT while pressing RESET for download mode.
|
||||||
|
|
||||||
|
## Gotchas — gateway
|
||||||
|
|
||||||
|
- Gateway speech deps (`faster-whisper`, `piper-tts`) are an optional extra —
|
||||||
|
`make setup` alone runs the app and the test suite without them. `make setup` invokes
|
||||||
|
`python3.12` explicitly; system `python3` on tower-of-joy is 3.8.
|
||||||
|
- `ruff` and `mypy` are **not** on the non-interactive PATH — they exist only inside
|
||||||
|
`gateway/.venv/bin/` once `make setup` has run. Use `make lint` / `make typecheck`, or
|
||||||
|
invoke `.venv/bin/ruff` / `.venv/bin/mypy` directly; a bare `ruff`/`mypy` will fail to
|
||||||
|
resolve, which is why the `.claude/settings.json` allow list uses the venv-relative
|
||||||
|
paths and `make` targets rather than bare tool names.
|
||||||
|
- Tatlock replies open with a `<think>` block — always strip it via
|
||||||
|
`tatlock.strip_reasoning()` (`gateway/src/desklock_gateway/tatlock.py`) before TTS or
|
||||||
|
display. Verified present and called at the one call site.
|
||||||
|
- Low power is a stated hardware requirement — read "Power management" in
|
||||||
|
`docs/architecture.md` before touching the face/render loop.
|
||||||
|
- Gateway health check is `GET /healthz` (verified in `main.py` and matches the
|
||||||
|
container healthcheck in `tatlock-ui.yml`), not `/health`.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```bash
|
**One Makefile at the root drives all three components.** There is deliberately no
|
||||||
# Firmware (requires `source ~/esp-idf/export.sh` first; IDF ≥ 5.4)
|
`gateway/Makefile` any more — `make test` meant "the gateway's tests" or "nothing"
|
||||||
cd firmware && idf.py build
|
depending on which directory you were standing in, and now it means the same thing
|
||||||
idf.py -p /dev/ttyACM0 flash monitor
|
everywhere (workspace D-27).
|
||||||
|
|
||||||
# Gateway
|
```bash
|
||||||
cd gateway && make setup # once
|
make help # every target, self-documenting
|
||||||
make run # dev server :8600
|
|
||||||
make test # pytest; single test: .venv/bin/pytest tests/test_health.py -k healthz
|
make test # gateway pytest; reports firmware + sim as undetermined
|
||||||
make lint typecheck
|
make lint # ruff check + format --check
|
||||||
|
make typecheck # mypy
|
||||||
|
|
||||||
|
make setup # gateway venv + dev deps (no ML models)
|
||||||
|
make setup-speech # additionally faster-whisper + piper
|
||||||
|
make run # uvicorn on :8600 with reload
|
||||||
|
|
||||||
|
make build-firmware # sources export.sh for you, then idf.py build
|
||||||
|
make flash PORT=/dev/ttyACM0 # flash + monitor
|
||||||
|
make serve-sim # face simulator on :8601
|
||||||
```
|
```
|
||||||
|
|
||||||
## Gotchas
|
**The firmware targets source `~/esp-idf/export.sh` themselves.** `idf.py` is not on
|
||||||
|
`PATH` until that runs, so the old `cd firmware && idf.py build` fails with "command
|
||||||
|
not found" for anyone who forgets — the same class of failure as four other tool
|
||||||
|
misses on this host. Override with `IDF_EXPORT=<path>/export.sh` on another machine;
|
||||||
|
the target fails loudly with that hint if the file is absent.
|
||||||
|
|
||||||
- **ESP-IDF is not yet installed on this machine** — install instructions in AGENTS.md.
|
`make test` never reports green for the firmware. It has no suite, so it is
|
||||||
- The firmware scaffold has never been built; treat BSP calls and sdkconfig as
|
**undetermined**, printed explicitly rather than skipped silently (workspace D-26).
|
||||||
provisional until first successful `idf.py build` (see warning in AGENTS.md).
|
|
||||||
- The device flashes over USB-C on this server, but it doesn't currently enumerate
|
## Liveness
|
||||||
(`/dev/ttyACM*` empty) and this user lacks the `dialout` group — resolve both before
|
|
||||||
attempting to flash.
|
- **Gateway (`desklock-gateway` container, port 8600):** confirmed live — `docker ps`
|
||||||
- Gateway speech deps are optional extras; `make setup` alone runs the app and tests
|
shows the container running under that name (method: direct container inspection;
|
||||||
without GPU/ML packages.
|
blind spot: none relevant here, this confirms the process is up, not that every route
|
||||||
|
behaves correctly — that would need a request against it, not checked this pass).
|
||||||
|
- **Firmware / device:** liveness is **undetermined** and cannot be established the way
|
||||||
|
the gateway's can. No `/dev/ttyACM0` was present in this session (checked: `ls
|
||||||
|
/dev/ttyACM*` found nothing) and there is no remote telemetry — the device only proves
|
||||||
|
itself alive over a physical USB serial connection or by joining the LAN and speaking
|
||||||
|
the WebSocket protocol, neither of which this session had access to. Do not infer
|
||||||
|
device state from repo contents or from the gateway being up.
|
||||||
|
- `strip_reasoning()` reachability: confirmed by direct read of
|
||||||
|
`gateway/src/desklock_gateway/tatlock.py` (method: source read of the one call site;
|
||||||
|
blind spot: does not confirm it's exercised by a live request — that's what
|
||||||
|
`tests/test_tatlock.py` is for, not re-run this pass).
|
||||||
|
|
||||||
|
## Work tracking
|
||||||
|
|
||||||
|
This repo's vault is standalone — its tickets and internal decisions live in its own
|
||||||
|
`.pql/` and `governance/`, and travel with a clone (`.pql/changelog/` is committed).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/home/jpmschweitzer/.local/bin/pql ticket list
|
||||||
|
/home/jpmschweitzer/.local/bin/pql plan whatsnext
|
||||||
|
/home/jpmschweitzer/.local/bin/pql decisions list
|
||||||
|
```
|
||||||
|
|
||||||
|
`pql` is not on the non-interactive PATH — use the absolute path above. From inside this
|
||||||
|
repo no `--vault` flag is needed (pql anchors at the nearest `.git/` ancestor, which is
|
||||||
|
this repo) — but that also means a bare `pql` run from the **workspace root** will not
|
||||||
|
see this repo's tickets, and a write from the workspace root would go to the wrong
|
||||||
|
vault. Cross-repo/stack-level decisions (host, network, deploy mechanics — none specific
|
||||||
|
to desklock were found at the time of writing) live in the workspace vault instead:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/home/jpmschweitzer/.local/bin/pql --vault /mnt/media/Projects decisions list --domain desklock
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git
|
||||||
|
|
||||||
|
- **History is linear — no merge commits.** Work on `main`, or a short-lived branch that
|
||||||
|
is fast-forwarded and deleted. This is the workspace-wide policy; there is no
|
||||||
|
per-repo exception here.
|
||||||
|
- Conventional Commits (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`).
|
||||||
|
- Stage explicitly — never `git add -A` (denied by `.claude/settings.json` policy).
|
||||||
|
- Update `CHANGELOG.md` under `[Unreleased]` for user-facing changes.
|
||||||
|
|
||||||
|
## Releasing (gateway only — firmware has no release flow)
|
||||||
|
|
||||||
|
Deploy is not automatic — confirm one is wanted first.
|
||||||
|
|
||||||
|
1. Bump `version` in `gateway/pyproject.toml`.
|
||||||
|
2. Move `[Unreleased]` entries into a dated `CHANGELOG.md` section.
|
||||||
|
3. Commit, tag `vX.Y.Z`, push with tags.
|
||||||
|
4. `.gitea/workflows/build.yml` runs lint + pytest on every push to `main`; on a `v*`
|
||||||
|
tag it additionally builds and pushes
|
||||||
|
`git.schweitz.net/jpmschweitzer/desklock-gateway:{latest,tag}` and pings Watchtower.
|
||||||
|
5. Verify: `curl http://192.168.86.149:8600/healthz`.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
`docs/architecture.md` is the source of truth for system design, the face design
|
||||||
|
(`sim/face/index.html` is its visual source — change both together and verify with
|
||||||
|
`~/bin/claude-screenshot`, noting its `--virtual-time-budget` starves
|
||||||
|
`requestAnimationFrame`, so sim animation is driven by `setInterval` instead), power
|
||||||
|
budget, latency budget, and the full WebSocket protocol spec. Not restated here because
|
||||||
|
it is detailed enough to drift if duplicated — read it directly.
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
# desklock — one entry point for a three-component repo.
|
||||||
|
#
|
||||||
|
# firmware/ ESP-IDF application for the device. No tests, no release flow.
|
||||||
|
# gateway/ Python service on :8600. The only component with a test suite.
|
||||||
|
# sim/ a static page that mimics the device face in a browser.
|
||||||
|
#
|
||||||
|
# This lives at the root and the components have no Makefiles of their own, so
|
||||||
|
# `make test` means the same thing wherever you are standing. A per-component
|
||||||
|
# Makefile makes it mean "some of the tests" depending on your working
|
||||||
|
# directory, which is the `git -C` failure in another costume (D-27).
|
||||||
|
#
|
||||||
|
# Paths resolve here rather than in callers (D-10). Two of them bite:
|
||||||
|
#
|
||||||
|
# ESP-IDF is invisible until export.sh is sourced, so `idf.py` is
|
||||||
|
# "command not found" for anyone who forgets — the same class of failure as
|
||||||
|
# the four tool-resolution misses recorded in D-24. The firmware targets
|
||||||
|
# source it themselves.
|
||||||
|
#
|
||||||
|
# `python3` on this host is 3.8, which cannot parse the gateway's sources.
|
||||||
|
# PYTHON names 3.12 explicitly and is overridable for other machines.
|
||||||
|
|
||||||
|
PYTHON ?= python3.12
|
||||||
|
IDF_EXPORT ?= $(HOME)/esp-idf/export.sh
|
||||||
|
GATEWAY := $(CURDIR)/gateway
|
||||||
|
VENV := $(GATEWAY)/.venv
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -hE '^[a-z][a-z0-9_-]*:.*?## ' $(MAKEFILE_LIST) \
|
||||||
|
| awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
# --- the three D-27 required targets -----------------------------------------
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: test-gateway ## Run every component's tests that exist
|
||||||
|
@echo " -- firmware: no test suite (undetermined, not passing)"
|
||||||
|
@echo " -- sim: a static page, nothing to test"
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: lint-gateway ## Lint every component that has a linter
|
||||||
|
|
||||||
|
# --- gateway ------------------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: setup
|
||||||
|
setup: ## Gateway venv + dev deps + prove it works (firmware needs export.sh — see below)
|
||||||
|
cd $(GATEWAY) && $(PYTHON) -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
||||||
|
@# This covers the gateway half only, deliberately. The firmware half needs
|
||||||
|
@# `source ~/esp-idf/export.sh` in every shell (see the firmware gotchas
|
||||||
|
@# above); a Makefile recipe runs in its own subshell, so it cannot leave
|
||||||
|
@# that sourced in the caller's shell. A `setup` that appeared to prepare
|
||||||
|
@# firmware and silently left `idf.py` unresolved would be worse than one
|
||||||
|
@# that says plainly it does not touch that half — hence `build-firmware`
|
||||||
|
@# sources export.sh itself, per target, instead.
|
||||||
|
@#
|
||||||
|
@# Exit 0 from `pip install` is not evidence (D-24) — pip reports success
|
||||||
|
@# even when the result is unusable (e.g. a dependency that resolved but
|
||||||
|
@# doesn't actually import, or a stale .venv left over from a different
|
||||||
|
@# Python). Prove the environment works instead of trusting the install
|
||||||
|
@# step: `--collect-only` imports every test module and therefore every
|
||||||
|
@# src module each one pulls in (T-47). It runs zero tests, so it stays
|
||||||
|
@# cheap, and it also confirms ruff/mypy landed in .venv/bin — the venv
|
||||||
|
@# is the only place either binary exists (see gateway gotchas above);
|
||||||
|
@# `--version` is enough to prove each resolves and runs.
|
||||||
|
cd $(GATEWAY) && .venv/bin/python -m pytest tests/ --collect-only -q
|
||||||
|
cd $(GATEWAY) && .venv/bin/ruff --version >/dev/null
|
||||||
|
cd $(GATEWAY) && .venv/bin/mypy --version >/dev/null
|
||||||
|
|
||||||
|
.PHONY: setup-speech
|
||||||
|
setup-speech: ## Additionally install faster-whisper and piper
|
||||||
|
cd $(GATEWAY) && .venv/bin/pip install -e ".[dev,speech]"
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: ## Run the gateway on :8600 with reload
|
||||||
|
cd $(GATEWAY) && .venv/bin/uvicorn desklock_gateway.main:app --host 0.0.0.0 --port 8600 --reload
|
||||||
|
|
||||||
|
.PHONY: test-gateway
|
||||||
|
test-gateway: ## Gateway pytest suite
|
||||||
|
@cd $(GATEWAY) && .venv/bin/pytest
|
||||||
|
|
||||||
|
.PHONY: lint-gateway
|
||||||
|
lint-gateway: ## ruff check and format --check over the gateway
|
||||||
|
cd $(GATEWAY) && .venv/bin/ruff check src tests && .venv/bin/ruff format --check src tests
|
||||||
|
|
||||||
|
.PHONY: typecheck
|
||||||
|
typecheck: ## mypy over the gateway sources
|
||||||
|
cd $(GATEWAY) && .venv/bin/mypy src
|
||||||
|
|
||||||
|
# --- firmware -----------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Each target sources export.sh in its own shell. That is deliberate: make runs
|
||||||
|
# every recipe line in a fresh shell, so exporting in one target would not carry
|
||||||
|
# to the next, and a caller who sources it by hand still works because sourcing
|
||||||
|
# twice is harmless.
|
||||||
|
|
||||||
|
.PHONY: build-firmware
|
||||||
|
build-firmware: ## Build the ESP-IDF firmware (sources export.sh for you)
|
||||||
|
@test -f $(IDF_EXPORT) || { echo "FAIL — no ESP-IDF at $(IDF_EXPORT); set IDF_EXPORT=<path>/export.sh"; exit 69; }
|
||||||
|
. $(IDF_EXPORT) && cd firmware && idf.py build
|
||||||
|
|
||||||
|
.PHONY: flash
|
||||||
|
flash: ## Flash and monitor the device (PORT=/dev/ttyACM0 by default)
|
||||||
|
@test -f $(IDF_EXPORT) || { echo "FAIL — no ESP-IDF at $(IDF_EXPORT); set IDF_EXPORT=<path>/export.sh"; exit 69; }
|
||||||
|
. $(IDF_EXPORT) && cd firmware && idf.py -p $(or $(PORT),/dev/ttyACM0) flash monitor
|
||||||
|
|
||||||
|
# --- sim ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: serve-sim
|
||||||
|
serve-sim: ## Serve the face simulator on :8601
|
||||||
|
cd sim/face && $(PYTHON) -m http.server 8601
|
||||||
|
|
||||||
|
# --- housekeeping -------------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: ## Remove the gateway venv and caches
|
||||||
|
rm -rf $(VENV) $(GATEWAY)/.pytest_cache $(GATEWAY)/.ruff_cache $(GATEWAY)/.mypy_cache
|
||||||
|
find $(GATEWAY) -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
# git hands a hook a non-login shell, which never sees ~/.local/bin — where
|
||||||
|
# gitleaks lands. Without this the scan reports "not installed" on every push,
|
||||||
|
# which is a check that fails open (D-24).
|
||||||
|
export PATH := $(HOME)/.local/bin:/usr/local/bin:$(PATH)
|
||||||
|
|
||||||
|
.PHONY: secrets
|
||||||
|
secrets: ## Scan the commits about to be pushed for credentials
|
||||||
|
@ci/secrets.sh
|
||||||
|
|
||||||
|
# The call surface is identical in every repo; what it runs is not.
|
||||||
|
#
|
||||||
|
# `secrets` runs first, deliberately: it is the only failure here that cannot be
|
||||||
|
# undone by fixing it afterwards. A failed lint costs another commit; a pushed
|
||||||
|
# credential is cached and indexed whether or not it is later deleted.
|
||||||
|
#
|
||||||
|
# Some of these fail today, and are left wired anyway. The state was measured
|
||||||
|
# once and written down in T-56 rather than being worked around here — a gate
|
||||||
|
# quietly narrowed to what already passes is a gate that reports success for
|
||||||
|
# doing nothing, which is the failure this workspace keeps rediscovering.
|
||||||
|
.PHONY: pre-push
|
||||||
|
pre-push: secrets lint typecheck test ## Everything the pre-push hook runs
|
||||||
@@ -38,8 +38,8 @@ happens on this server.
|
|||||||
▼ │ Speaches (container, GPU) │
|
▼ │ Speaches (container, GPU) │
|
||||||
┌────────────────────┐ │ • STT: faster-whisper │
|
┌────────────────────┐ │ • STT: faster-whisper │
|
||||||
│ Tatlock (butler) │ │ • TTS: Kokoro / Piper │
|
│ Tatlock (butler) │ │ • TTS: Kokoro / Piper │
|
||||||
│ tatlock.schweitz. │ │ also usable by Open WebUI, │
|
│ http://tatlock │ │ also usable by Open WebUI, │
|
||||||
│ internal :8000 │ │ Home Assistant, … │
|
│ :8000 │ │ Home Assistant, … │
|
||||||
└────────────────────┘ └─────────────────────────────┘
|
└────────────────────┘ └─────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -61,8 +61,8 @@ See [docs/architecture.md](docs/architecture.md) for the full design.
|
|||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
1. **Bring-up** — ESP-IDF toolchain, build/flash, BSP display + Wi-Fi working
|
1. ~~**Bring-up**~~ ✅ — display, touch, audio, 200 MHz PSRAM, cathedral gong
|
||||||
2. **Face** — LVGL face with idle/listening/thinking/speaking states, clock while idle
|
2. **Face + voice loop** (in hardware test) — full LVGL face (7 states, rain, orbit, power ladder), Wi-Fi, WebSocket, touch-to-talk
|
||||||
3. **Voice (touch-to-talk)** — tap to talk → gateway → Tatlock → spoken reply
|
3. **Voice (touch-to-talk)** — tap to talk → gateway → Tatlock → spoken reply
|
||||||
4. **Wake word** — esp-sr WakeNet on-device, echo cancellation, barge-in
|
4. **Wake word** — esp-sr WakeNet on-device, echo cancellation, barge-in
|
||||||
5. **Polish** — Tatlock-initiated notifications, presence, OTA updates
|
5. **Polish** — Tatlock-initiated notifications, presence, OTA updates
|
||||||
|
|||||||
Executable
+50
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Secret scan over the commits about to be pushed.
|
||||||
|
#
|
||||||
|
# Lives here rather than inside .githooks/pre-push so it can be read, run by
|
||||||
|
# hand (`make secrets`), and changed under review. A hook is a trigger; it is
|
||||||
|
# not a home for logic. Identical in every repo in this workspace (D-27).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
# A non-login shell — which is what git gives a hook — skips /etc/profile.d
|
||||||
|
# and never sees ~/.local/bin, where the gitleaks release tarball lands.
|
||||||
|
# Without this the scan reports "not installed" on every push.
|
||||||
|
[ -d "$HOME/.local/bin" ] && PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if ! command -v gitleaks >/dev/null 2>&1; then
|
||||||
|
echo "FAIL secrets — gitleaks not installed, so this check would be a no-op pretending to pass." >&2
|
||||||
|
echo " https://github.com/gitleaks/gitleaks/releases → ~/.local/bin/gitleaks" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Scan the outgoing range, not full history. History here carries findings
|
||||||
|
# that are settled — test fixtures and vendored third-party code — and a gate
|
||||||
|
# that fails on something unfixable gets bypassed within a week. What matters
|
||||||
|
# is what is about to leave this machine.
|
||||||
|
if upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null); then
|
||||||
|
range="$upstream..HEAD"
|
||||||
|
elif git rev-parse --verify --quiet origin/main >/dev/null; then
|
||||||
|
range="origin/main..HEAD"
|
||||||
|
else
|
||||||
|
range=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$range" ]; then
|
||||||
|
gitleaks dir . --redact --no-banner --exit-code 1 || {
|
||||||
|
echo "FAIL secrets — gitleaks found a credential in the working tree." >&2; exit 1; }
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$(git log --oneline "$range" 2>/dev/null)" ] || exit 0
|
||||||
|
|
||||||
|
gitleaks git . --log-opts="$range" --redact --no-banner --exit-code 1 >/dev/null 2>&1 || {
|
||||||
|
echo "FAIL secrets — gitleaks found a credential in the commits being pushed." >&2
|
||||||
|
echo " inspect (values redacted): gitleaks git . --log-opts=\"$range\" --redact" >&2
|
||||||
|
echo " then remove and rotate it, or suppress deliberately:" >&2
|
||||||
|
echo " inline '# gitleaks:allow <reason>'" >&2
|
||||||
|
echo " or add the fingerprint to .gitleaksignore WITH a reason" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
echo " ok secrets"
|
||||||
+120
-24
@@ -24,8 +24,8 @@ tower-of-joy. Everything is local — no audio, transcript, or reply ever leaves
|
|||||||
▼ │ Speaches (container, GPU) │
|
▼ │ Speaches (container, GPU) │
|
||||||
┌────────────────────┐ │ • STT: faster-whisper │
|
┌────────────────────┐ │ • STT: faster-whisper │
|
||||||
│ Tatlock (butler) │ │ • TTS: Kokoro / Piper │
|
│ Tatlock (butler) │ │ • TTS: Kokoro / Piper │
|
||||||
│ tatlock.schweitz. │ │ also usable by Open WebUI, │
|
│ container name: │ │ also usable by Open WebUI, │
|
||||||
│ internal :8000 │ │ Home Assistant, … │
|
│ tatlock:8000 │ │ Home Assistant, … │
|
||||||
└────────────────────┘ └─────────────────────────────┘
|
└────────────────────┘ └─────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ models — the container stays a slim pure-Python image with no CUDA/ML dependen
|
|||||||
2. Buffers inbound PCM until end-of-utterance (client-signalled in phase 1; VAD later).
|
2. Buffers inbound PCM until end-of-utterance (client-signalled in phase 1; VAD later).
|
||||||
3. **STT**: POST to Speaches `/v1/audio/transcriptions`.
|
3. **STT**: POST to Speaches `/v1/audio/transcriptions`.
|
||||||
4. **Chat**: POST the transcript to Tatlock `/v1/chat/completions`
|
4. **Chat**: POST the transcript to Tatlock `/v1/chat/completions`
|
||||||
(`http://tatlock.schweitz.internal:8000`, OpenAI-compatible, **streaming**),
|
(`http://tatlock:8000`, OpenAI-compatible, **streaming**),
|
||||||
maintaining the conversation history so follow-ups have context.
|
maintaining the conversation history so follow-ups have context.
|
||||||
5. **TTS**: as Tatlock's token stream completes each sentence, POST it to Speaches
|
5. **TTS**: as Tatlock's token stream completes each sentence, POST it to Speaches
|
||||||
`/v1/audio/speech` and forward the PCM immediately — see
|
`/v1/audio/speech` and forward the PCM immediately — see
|
||||||
@@ -103,19 +103,25 @@ we may adopt later for streaming transcription.
|
|||||||
extension, verified live; default voice `bm_george`, en-GB male). LAN-only like the
|
extension, verified live; default voice `bm_george`, en-GB male). LAN-only like the
|
||||||
Tatlock internal route — do not expose through NPM without auth. Register in
|
Tatlock internal route — do not expose through NPM without auth. Register in
|
||||||
`CONTAINERS.md`.
|
`CONTAINERS.md`.
|
||||||
- **Measured** (live round trip through the gateway code, warm): STT ~0.3 s for a
|
- **Measured** (live round trip, warm, 2026-08-07): STT ~0.30 s for a ~4.8 s utterance;
|
||||||
~3 s utterance; TTS ~1.9 s for a ~3 s sentence. Cold start after model TTL offload
|
TTS ~0.24 s for a ~4.5 s sentence (real-time factor ~0.05). The first call after an
|
||||||
adds ~5–10 s to the first request.
|
idle gap costs ~1.2 s; a full cold start after model TTL offload adds ~4 s.
|
||||||
- **Why a shared layer instead of models inside the gateway**: one GPU-resident model
|
- **Why a shared layer instead of models inside the gateway**: one GPU-resident model
|
||||||
instance serves the whole homelab. Open WebUI is currently configured with
|
instance serves the whole homelab. Open WebUI is currently configured with
|
||||||
`AUDIO_STT_ENGINE=openai` / `AUDIO_TTS_ENGINE=openai` (OpenAI *cloud*) — pointing its
|
`AUDIO_STT_ENGINE=openai` / `AUDIO_TTS_ENGINE=openai` (OpenAI *cloud*) — pointing its
|
||||||
audio base URL at Speaches makes it fully local with a config change. Home Assistant
|
audio base URL at Speaches makes it fully local with a config change. Home Assistant
|
||||||
can share it too. Meanwhile the gateway image needs no CUDA and rebuilds in seconds.
|
can share it too. Meanwhile the gateway image needs no CUDA and rebuilds in seconds.
|
||||||
- **VRAM budget**: RTX 2080 Ti, 11 GB, shared with Ollama (~3.6 GB in use as of
|
- **VRAM budget**: RTX 2080 Ti, 11,264 MiB, shared with Ollama. As of 2026-08-07 the
|
||||||
2026-07). whisper `small` at int8 is <1 GB; Kokoro is a few hundred MB. Speaches'
|
steady state is ~4.9 GB used / ~5.9 GB free with everything resident: `gemma4:e2b`
|
||||||
model TTL offload keeps idle pressure near zero. If VRAM contention ever bites,
|
1.9 GB and `nomic-embed-text` 0.3 GB (both pinned), whisper `small` int8 <1 GB,
|
||||||
faster-whisper `small` on CPU is an acceptable fallback (int8, a few seconds per
|
Kokoro a few hundred MB. Speaches' model TTL offload keeps idle pressure near zero.
|
||||||
utterance).
|
**This budget is not slack — it is the constraint.** On 2026-08-07 Tatlock was
|
||||||
|
deployed against `mistral-nemo:latest` (9.3 GB, 2 h keep-alive), which left 7 MiB
|
||||||
|
free and made every transcription fail with `CUDA failed with error out of memory`
|
||||||
|
while the Speaches container still reported healthy. Keep Tatlock's model at or below
|
||||||
|
~4 GB resident, and check `nvidia-smi` free VRAM before changing it. If contention
|
||||||
|
ever bites anyway, faster-whisper `small` on CPU is an acceptable fallback (int8, a
|
||||||
|
few seconds per utterance).
|
||||||
|
|
||||||
### 4. Tatlock — existing backend (`/mnt/media/Projects/tatlock`)
|
### 4. Tatlock — existing backend (`/mnt/media/Projects/tatlock`)
|
||||||
|
|
||||||
@@ -144,6 +150,12 @@ ported to LVGL. The `STATES` table in the sim defines the contract:
|
|||||||
| `rage` | — | — | 34 fast streams | 3-frame kaomoji loop through the eyes slot: `(°□°) ┬─┬` → `(╯°□°)╯︵ ┻━┻` → `┬─┬ ノ( º_º ノ)` — flips the table, then composes itself and puts it back |
|
| `rage` | — | — | 34 fast streams | 3-frame kaomoji loop through the eyes slot: `(°□°) ┬─┬` → `(╯°□°)╯︵ ┻━┻` → `┬─┬ ノ( º_º ノ)` — flips the table, then composes itself and puts it back |
|
||||||
| `error` | `x x` | `-` | none (rain dies) | face dims to 45% |
|
| `error` | `x x` | `-` | none (rain dies) | face dims to 45% |
|
||||||
|
|
||||||
|
**Sound signature**: the cathedral gong (`play_boot_gong` in firmware — 220 Hz
|
||||||
|
inharmonic partial stack, feedback-comb reflections, ~-7 dBFS) is the approved house
|
||||||
|
sound: "audible and butler-non-intrusive." Plays at boot; planned as the
|
||||||
|
wake-from-`dormant` sound. Tune by adjective: tail = `tau`s, cathedral size = echo
|
||||||
|
delays, depth = fundamental, presence = `GONG_PEAK`/`GONG_VOLUME`.
|
||||||
|
|
||||||
**Wait cues are a hard requirement** (user-stated): Tatlock turns take 10–25 s, so
|
**Wait cues are a hard requirement** (user-stated): Tatlock turns take 10–25 s, so
|
||||||
`effort` must always show *alive-and-working* signals — the orbiting bezel arc, the
|
`effort` must always show *alive-and-working* signals — the orbiting bezel arc, the
|
||||||
elapsed-seconds counter, and max rain. Never a bare static face during a wait, and no
|
elapsed-seconds counter, and max rain. Never a bare static face during a wait, and no
|
||||||
@@ -164,21 +176,72 @@ WebSocket disconnected → `error` (quiet, persistent); otherwise `idle`.
|
|||||||
The `rage` frames additionally need `╯ ︵ ┻ ━ ┬ ─ ノ ° □ º` in the subset.
|
The `rage` frames additionally need `╯ ︵ ┻ ━ ┬ ─ ノ ° □ º` in the subset.
|
||||||
- The sim's text glow (`text-shadow`) is browser flair — the device renders flat glyphs.
|
- The sim's text glow (`text-shadow`) is browser flair — the device renders flat glyphs.
|
||||||
|
|
||||||
|
## Power management (prime concern)
|
||||||
|
|
||||||
|
User requirement: the device idles on a wall 95%+ of its life — low power when nothing
|
||||||
|
is happening is a first-class design goal, not a phase-5 nicety. The face state machine
|
||||||
|
is therefore built around a **power ladder** from day one:
|
||||||
|
|
||||||
|
| Power state | Backlight | Rendering | CPU | Entered when |
|
||||||
|
|-------------|-----------|-----------|-----|--------------|
|
||||||
|
| `active` | 100% | full animation | full clock | conversation in progress (listening→speaking) |
|
||||||
|
| `ambient` | ~35% | idle face, sparse rain | DFS enabled | idle, but activity in the last few minutes |
|
||||||
|
| `dormant` | off (or ≤5%) | **no redraws** — render loop parked | min clock via DFS | no voice/touch for N min (default 10) |
|
||||||
|
| `night` | off, panel sleep | none | min clock | schedule or "goodnight" command |
|
||||||
|
|
||||||
|
Levers, in order of impact:
|
||||||
|
|
||||||
|
1. **Backlight** — this is an IPS LCD: black pixels still burn backlight (unlike OLED),
|
||||||
|
so brightness is the dominant lever. `bsp_display_brightness_set()` drives it.
|
||||||
|
2. **Render idleness** — rain off and animations parked means LVGL stops producing
|
||||||
|
frames, which is what lets DFS actually reach its floor.
|
||||||
|
3. **DFS / power management** (`CONFIG_PM_ENABLE`) — automatic frequency scaling when
|
||||||
|
tasks are quiet. Note the MIPI-DSI constraint below.
|
||||||
|
4. **Radio** — the C6 runs Wi-Fi modem power-save; the gateway WebSocket widens its
|
||||||
|
ping interval when the device reports `dormant`.
|
||||||
|
|
||||||
|
Wake triggers (any → `ambient`/`active`): wake word (phase 5), touch (from phase 2),
|
||||||
|
local VAD "someone is speaking" pre-warm, a gateway-initiated event (butler wants to
|
||||||
|
say something), scheduled morning end of `night`.
|
||||||
|
|
||||||
|
**Hard edges — what limits how low we can go:**
|
||||||
|
|
||||||
|
- **The hands-free promise sets the power floor.** Wake word requires mics + the AFE
|
||||||
|
pipeline running continuously; deep sleep is permanently off the table while the
|
||||||
|
device promises to answer its name. The floor is "CPU lightly loaded at min clock,
|
||||||
|
radios in power-save, backlight off."
|
||||||
|
- **DSI needs clocks while the panel is active** — the deepest CPU savings only unlock
|
||||||
|
in `dormant`/`night` when the panel stops being refreshed (panel sleep / blank).
|
||||||
|
- **Wake latency budget: ≤ ~300 ms** from trigger to visible face (backlight ramp +
|
||||||
|
first render). Anything slower reads as "it's off," which kills the butler illusion.
|
||||||
|
- **Touch stays powered** in all states except possibly `night` — its idle draw is
|
||||||
|
negligible and tap-to-wake must always work.
|
||||||
|
- **No invented numbers**: actual draw gets measured with a USB power meter at each
|
||||||
|
phase; working target is `dormant` ≤ ⅓ of `active`. (Always-on device: every watt
|
||||||
|
saved ≈ 9 kWh/year.)
|
||||||
|
|
||||||
|
Implementation order: backlight dimming + `dormant` timeout + touch wake land in
|
||||||
|
**phase 2** with the face state machine (timeout-driven); voice-linked triggers upgrade
|
||||||
|
it in phase 5.
|
||||||
|
|
||||||
## Latency budget & streaming
|
## Latency budget & streaming
|
||||||
|
|
||||||
Measured/known numbers that shape the design (Tatlock figures per tatlock CLAUDE.md,
|
Measured 2026-08-07 against the deployed stack (`gemma4:e2b` at ~95 tok/s, GPU-resident):
|
||||||
GPU-resident benchmarks of 2026-07-14, gemma4:e2b at ~100 tok/s):
|
|
||||||
|
|
||||||
| Stage | Cost |
|
| Stage | Cost |
|
||||||
|-------|------|
|
|-------|------|
|
||||||
| STT (Speaches whisper `small`) | ~0.3 s warm (measured) |
|
| STT (Speaches whisper `small`) | ~0.30 s warm, for ~4.8 s of audio |
|
||||||
| TTS (Speaches Kokoro) | ~1.9 s per ~3 s sentence, warm (measured) |
|
| TTS (Speaches Kokoro) | ~0.24 s warm, for ~4.5 s of audio (RTF ~0.05) |
|
||||||
| Tatlock Steward analysis | ~6 s warm |
|
| **Tatlock, full local flow** | **~10–13 s end-to-end** for simple turns |
|
||||||
| **Tatlock, full local flow** | **11–25 s end-to-end** (librarian-routed ~20–25 s) |
|
| Tatlock cold model load | +~36 s — avoided while the model is pinned |
|
||||||
| Tatlock cold start (>2 h idle) | +~8 s (`OLLAMA_KEEP_ALIVE=2h`) |
|
|
||||||
|
|
||||||
(Older "~35 s Steward / ~2 min flow" figures were from a CPU-only driver-mismatch era —
|
A Tatlock turn costs **3 sequential Ollama calls** (Steward routing → tool orchestration →
|
||||||
do not plan against them.)
|
butler-tone synthesis) and ~710 generated tokens even for "what is 61 plus 12?". Most of
|
||||||
|
that is the model's own reasoning: gemma4 thinks by default, and the effort is spent three
|
||||||
|
times per turn.
|
||||||
|
|
||||||
|
(Older figures — "~35 s Steward / ~2 min flow" from the CPU-only era, and "11–25 s full
|
||||||
|
flow" from 2026-07-14 — are superseded. Do not plan against them.)
|
||||||
|
|
||||||
Speech is not the bottleneck — **Tatlock is**, by one to two orders of magnitude.
|
Speech is not the bottleneck — **Tatlock is**, by one to two orders of magnitude.
|
||||||
Constraints this imposes:
|
Constraints this imposes:
|
||||||
@@ -187,11 +250,11 @@ Constraints this imposes:
|
|||||||
sentence-by-sentence**, forwarding audio as each sentence is ready. The device starts
|
sentence-by-sentence**, forwarding audio as each sentence is ready. The device starts
|
||||||
speaking after the first sentence instead of waiting for the full reply — with
|
speaking after the first sentence instead of waiting for the full reply — with
|
||||||
streaming, first audio should land roughly at Steward-time + first-sentence-time,
|
streaming, first audio should land roughly at Steward-time + first-sentence-time,
|
||||||
well under the 11–25 s full-flow figure. The WS protocol already supports this: one
|
well under the ~10–13 s full-flow figure. The WS protocol already supports this: one
|
||||||
`audio_start` … PCM … `audio_end` envelope with chunks arriving as they're
|
`audio_start` … PCM … `audio_end` envelope with chunks arriving as they're
|
||||||
synthesized — the device just plays a continuous stream.
|
synthesized — the device just plays a continuous stream.
|
||||||
2. **The `thinking` face state is a first-class feature**, not decoration — it's what
|
2. **The `thinking` face state is a first-class feature**, not decoration — it's what
|
||||||
makes a 10–25 s Tatlock turn feel intentional instead of broken. Consider progress
|
makes a ~10 s Tatlock turn feel intentional instead of broken. Consider progress
|
||||||
cues (e.g. surface Tatlock's reasoning summaries on-screen) later.
|
cues (e.g. surface Tatlock's reasoning summaries on-screen) later.
|
||||||
3. A **fast lane** may eventually be needed: MultiNet on-device commands for instant
|
3. A **fast lane** may eventually be needed: MultiNet on-device commands for instant
|
||||||
home-automation phrases, and/or a low-latency intent path in Tatlock itself. Out of
|
home-automation phrases, and/or a low-latency intent path in Tatlock itself. Out of
|
||||||
@@ -212,8 +275,17 @@ gateway → device: {"type": "reply_text", "text": "..."}
|
|||||||
gateway → device: {"type": "audio_start", "sample_rate": 16000}
|
gateway → device: {"type": "audio_start", "sample_rate": 16000}
|
||||||
gateway → device: <binary PCM frames> (may arrive sentence-by-sentence; play as a stream)
|
gateway → device: <binary PCM frames> (may arrive sentence-by-sentence; play as a stream)
|
||||||
gateway → device: {"type": "audio_end"}
|
gateway → device: {"type": "audio_end"}
|
||||||
|
|
||||||
|
gateway → device: {"type": "command", "action": "volume_up"} (LLM-bypass; see below)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`command` (gateway → device) is an **alternative to the reply path**: when the
|
||||||
|
gateway recognizes a simple device command in the transcript (volume/mute), it
|
||||||
|
sends a `command` instead of calling Tatlock — no `reply_text`/audio — then returns
|
||||||
|
to `idle`. Actions: `volume_up`, `volume_down`, `mute`, `unmute`, and `volume_set`
|
||||||
|
with an extra `"level"` field (0–11, the on-device volume scale). Matched by the
|
||||||
|
gateway's `commands.py`; applied on the device in `gw_client.c` → `face.c`.
|
||||||
|
|
||||||
Planned additions (documented before implemented, here first):
|
Planned additions (documented before implemented, here first):
|
||||||
|
|
||||||
- `reply_delta` (gateway → device): incremental reply text for on-screen streaming while
|
- `reply_delta` (gateway → device): incremental reply text for on-screen streaming while
|
||||||
@@ -247,17 +319,36 @@ it is the one contract between the two halves of the repo.
|
|||||||
- **Monorepo**: the WS protocol couples firmware and gateway; versioning them together
|
- **Monorepo**: the WS protocol couples firmware and gateway; versioning them together
|
||||||
avoids contract drift.
|
avoids contract drift.
|
||||||
|
|
||||||
|
## Additional endpoints — sauron (planned)
|
||||||
|
|
||||||
|
**sauron** is an old iMac (Linux, text-only console) that will run the same UX as a
|
||||||
|
second butler endpoint plus an ops console. Because the gateway protocol is
|
||||||
|
endpoint-agnostic and each WS connection gets its own conversation, extra endpoints
|
||||||
|
are architecturally free.
|
||||||
|
|
||||||
|
- **Client**: a terminal UI (`clients/sauron/`, Python + curses/textual) — the face
|
||||||
|
design is already ASCII, so a TTY renders it natively: glyph face states,
|
||||||
|
character-cell matrix rain, green-on-black. Audio via ALSA (arecord/aplay-level,
|
||||||
|
16 kHz mono PCM), same WebSocket protocol, same state machine.
|
||||||
|
- **Screensaver model** (user-confirmed): the face+voice layer is the *idle mode* —
|
||||||
|
full-screen butler when nobody's working. The *workspace mode* is an SSH ops console:
|
||||||
|
live stats and remote control of tower-of-joy and forge. Any keypress drops from face
|
||||||
|
to console; idle timeout (and wake word later) raises the face again. Voice stays
|
||||||
|
available in both modes.
|
||||||
|
- **Not started** — planned after the device reaches phase 4/5. No browser/kiosk stack
|
||||||
|
needed unless we later want the glow.
|
||||||
|
|
||||||
## CI & deployment
|
## CI & deployment
|
||||||
|
|
||||||
Gitea Actions (`.gitea/workflows/build.yml`), following the tatlock/tatlock-ui pattern:
|
Gitea Actions (`.gitea/workflows/build.yml`), following the tatlock/tatlock-ui pattern:
|
||||||
|
|
||||||
- **Every push to `main`**: lint + tests for the gateway (Python 3.12).
|
- **Every push to `main`**: lint + tests for the gateway (Python 3.12).
|
||||||
- **Version tags (`v0.1.0`, …)**: tests, then build `gateway/` into
|
- **Version tags (`v0.1.0`, …)**: tests, then build `gateway/` into
|
||||||
`git.schweitz.internal/jpmschweitzer/desklock-gateway:{latest,tag}`, push to the
|
`git.schweitz.net/jpmschweitzer/desklock-gateway:{latest,tag}`, push to the
|
||||||
Gitea registry, create a release, and trigger Watchtower to roll the running
|
Gitea registry, create a release, and trigger Watchtower to roll the running
|
||||||
container.
|
container.
|
||||||
- Required repo/org secrets: `REGISTRY_USER`, `REGISTRY_PASSWORD`,
|
- Required repo/org secrets: `REGISTRY_USER`, `REGISTRY_PASSWORD`,
|
||||||
`WATCHTOWER_TOKEN` (same trio tatlock uses).
|
`WATCHTOWER_HTTP_API_TOKEN` (same trio tatlock uses).
|
||||||
- The gateway is a service in the **`tatlock-ui` Portainer stack**
|
- The gateway is a service in the **`tatlock-ui` Portainer stack**
|
||||||
(`system-admin-toj/containers/stacks/tatlock-ui.yml`, registered in
|
(`system-admin-toj/containers/stacks/tatlock-ui.yml`, registered in
|
||||||
`CONTAINERS.md`): it shares `docker-dataplane` with Speaches (service-name URL
|
`CONTAINERS.md`): it shares `docker-dataplane` with Speaches (service-name URL
|
||||||
@@ -265,3 +356,8 @@ Gitea Actions (`.gitea/workflows/build.yml`), following the tatlock/tatlock-ui p
|
|||||||
|
|
||||||
Firmware is not containerized: it's flashed over USB (`idf.py flash`), with OTA planned
|
Firmware is not containerized: it's flashed over USB (`idf.py flash`), with OTA planned
|
||||||
for phase 5.
|
for phase 5.
|
||||||
|
|
||||||
|
**Versioning**: `0.x` while interfaces are still moving — roughly one minor bump per
|
||||||
|
roadmap phase (`0.1.x` gateway server-side, `0.2.x` first device firmware, `0.3.x`
|
||||||
|
hands-free). **`v1.0.0` is reserved for the wall milestone**: the device mounted in the
|
||||||
|
living room, talking to Tatlock end to end.
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# SDIO wedge reproduction pack (esp-hosted-mcu #167 family)
|
||||||
|
|
||||||
|
Evidence gathered overnight 2026-07-14→15 on Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C
|
||||||
|
(ESP32-P4 host + ESP32-C6-MINI-1 slave, SDIO: CLK18 CMD19 D0-14 D1-15 D2-16 D3-17,
|
||||||
|
slave reset GPIO54, on-board routed traces). Ready to post as an upstream issue
|
||||||
|
comment when we choose to.
|
||||||
|
|
||||||
|
## Signature
|
||||||
|
|
||||||
|
```
|
||||||
|
E H_SDIO_DRV: sdio_write_task: 0: Failed to send data: 258 72 72
|
||||||
|
E H_SDIO_DRV: sdio_write_task: 1: Failed to send data: 258 72 72
|
||||||
|
E H_SDIO_DRV: Unrecoverable host sdio state
|
||||||
|
→ SW_CPU_RESET (H_TRANSPORT_RESTART_ON_FAILURE)
|
||||||
|
```
|
||||||
|
|
||||||
|
Decoded from `sdio_drv.c` `sdio_write_task`: a 72-byte frame (`len_to_send=72,
|
||||||
|
data_left=72`, i.e. keepalive-sized) fails `_h_sdio_write_block` with
|
||||||
|
`ESP_ERR_TIMEOUT` (258) on both retries — **after** `sdio_is_write_buffer_available()`
|
||||||
|
reported credits. The slave's SDIO peripheral stops ACKing CMD53 between the credit
|
||||||
|
read and the data write. Serial is completely silent for minutes before the event
|
||||||
|
(idle link, WS ping traffic only).
|
||||||
|
|
||||||
|
## Occurrence matrix (all: host IDF v5.5, matched host+slave versions)
|
||||||
|
|
||||||
|
| Config | Time to wedge |
|
||||||
|
|---|---|
|
||||||
|
| 2.12.11, 4-bit, 40 MHz, PS default, DHCP client active | ~437 s |
|
||||||
|
| 2.12.11, 1-bit, 20 MHz, PS default, DHCP active | ~297 s |
|
||||||
|
| 2.12.11, 1-bit, 10 MHz, WIFI_PS_NONE, DHCP active | ~322 s, ~297 s |
|
||||||
|
| 2.12.11, 1-bit, 10 MHz, WIFI_PS_NONE, **static IP (no dhcpc)** | **~783 s** |
|
||||||
|
|
||||||
|
- Bus width, clock (40→10 MHz), and Wi-Fi power save have **no effect**.
|
||||||
|
- Removing the DHCP client ~2.6×'d the survival time → trigger frequency correlates
|
||||||
|
with (small-packet?) TX activity, but idle WS keepalives eventually wedge it too.
|
||||||
|
- Recovery: host auto-restart works every time (~15 s to reconnected).
|
||||||
|
- 2.9.7 slave could not be tested: its image consistently rolls back on this C6
|
||||||
|
(bootloops back to the 2.12.11 OTA slot); 2.12.11↔2.12.11 is the tested pair.
|
||||||
|
- esp-hosted 1.4.x is not comparable (no data path at all on IDF 5.5, see #47).
|
||||||
|
|
||||||
|
## Current mitigation in DeskLock
|
||||||
|
|
||||||
|
- `H_TRANSPORT_RESTART_ON_FAILURE` (default) + gong silenced on SW resets → the
|
||||||
|
device self-heals invisibly except ~15 s of CONNECTING face.
|
||||||
|
- Static addressing (`192.168.86.53`) reduces wedge frequency to ~13 min MTBF.
|
||||||
|
- Full raw serial history of every wedge in `scratchpad/nightwatch.log` captures
|
||||||
|
(session artifacts), timestamps in the repo's commit trail.
|
||||||
@@ -1,4 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
|
# Grow LVGL's invalidation buffer (default 32) so the ~80 moving rain labels of the
|
||||||
|
# busy face states stay as separate partial-redraw rects instead of collapsing into
|
||||||
|
# one full-screen redraw. Secondary mitigation for the DSI PSRAM-bandwidth underrun
|
||||||
|
# (primary fix is the reduced DPI clock in the BSP): a full-screen redraw dumps a
|
||||||
|
# ~1.3 MB PSRAM write burst that competes with the DSI's continuous framebuffer read
|
||||||
|
# and can re-trigger the underrun; keeping busy states partial avoids that. Applied
|
||||||
|
# globally so LVGL and esp_lvgl_adapter (both size inv_areas[] by LV_INV_BUF_SIZE)
|
||||||
|
# agree. The partial-flush path's stack scales with this, so app_main starts the LVGL
|
||||||
|
# task with a 16 KB stack (see desklock_main.c) — the 8 KB default overflows at 128.
|
||||||
|
# Must sit after the project.cmake include (defines idf_build_set_property) and before
|
||||||
|
# project() consumes it.
|
||||||
|
idf_build_set_property(COMPILE_OPTIONS "-DLV_INV_BUF_SIZE=128" APPEND)
|
||||||
|
|
||||||
project(desklock)
|
project(desklock)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
e7a07d2556e2aab26e17533ef1cc5f7574d57303f395c5ec9c8e36ee8742496d
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.5")
|
||||||
|
set(REQ esp_driver_gpio esp_driver_i2s esp_driver_sdmmc esp_driver_sdspi esp_driver_i2c)
|
||||||
|
set(PRIV_REQ esp_driver_spi esp_driver_ledc)
|
||||||
|
else()
|
||||||
|
set(REQ driver)
|
||||||
|
set(PRIV_REQ "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${IDF_VERSION_MAJOR} LESS 6)
|
||||||
|
list(APPEND PRIV_REQ usb)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(
|
||||||
|
SRCS "esp32_p4_wifi6_touch_lcd_xc.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
PRIV_INCLUDE_DIRS "priv_include"
|
||||||
|
REQUIRES ${REQ} fatfs
|
||||||
|
PRIV_REQUIRES ${PRIV_REQ} esp_lcd spiffs esp_psram
|
||||||
|
)
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
menu "Board Support Package(ESP32-P4)"
|
||||||
|
|
||||||
|
config BSP_ERROR_CHECK
|
||||||
|
bool "Enable error check in BSP"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Error check assert the application before returning the error code.
|
||||||
|
|
||||||
|
menu "I2C"
|
||||||
|
config BSP_I2C_NUM
|
||||||
|
int "I2C peripheral index"
|
||||||
|
default 1
|
||||||
|
range 0 1
|
||||||
|
help
|
||||||
|
ESP32P4 has two I2C peripherals, pick the one you want to use.
|
||||||
|
|
||||||
|
config BSP_I2C_FAST_MODE
|
||||||
|
bool "Enable I2C fast mode"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
I2C has two speed modes: normal (100kHz) and fast (400kHz).
|
||||||
|
|
||||||
|
config BSP_I2C_CLK_SPEED_HZ
|
||||||
|
int
|
||||||
|
default 400000 if BSP_I2C_FAST_MODE
|
||||||
|
default 100000
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "I2S"
|
||||||
|
config BSP_I2S_NUM
|
||||||
|
int "I2S peripheral index"
|
||||||
|
default 1
|
||||||
|
range 0 2
|
||||||
|
help
|
||||||
|
ESP32P4 has three I2S peripherals, pick the one you want to use.
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "uSD card - Virtual File System"
|
||||||
|
config BSP_SD_FORMAT_ON_MOUNT_FAIL
|
||||||
|
bool "Format uSD card if mounting fails"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
The SDMMC host will format (FAT) the uSD card if it fails to mount the filesystem.
|
||||||
|
|
||||||
|
config BSP_SD_MOUNT_POINT
|
||||||
|
string "uSD card mount point"
|
||||||
|
default "/sdcard"
|
||||||
|
help
|
||||||
|
Mount point of the uSD card in the Virtual File System
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "SPIFFS - Virtual File System"
|
||||||
|
config BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL
|
||||||
|
bool "Format SPIFFS if mounting fails"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Format SPIFFS if it fails to mount the filesystem.
|
||||||
|
|
||||||
|
config BSP_SPIFFS_MOUNT_POINT
|
||||||
|
string "SPIFFS mount point"
|
||||||
|
default "/spiffs"
|
||||||
|
help
|
||||||
|
Mount point of SPIFFS in the Virtual File System.
|
||||||
|
|
||||||
|
config BSP_SPIFFS_PARTITION_LABEL
|
||||||
|
string "Partition label of SPIFFS"
|
||||||
|
default "storage"
|
||||||
|
help
|
||||||
|
Partition label which stores SPIFFS.
|
||||||
|
|
||||||
|
config BSP_SPIFFS_MAX_FILES
|
||||||
|
int "Max files supported for SPIFFS VFS"
|
||||||
|
default 5
|
||||||
|
help
|
||||||
|
Supported max files for SPIFFS in the Virtual File System.
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "Display"
|
||||||
|
config BSP_LCD_DPI_BUFFER_NUMS
|
||||||
|
int "Set number of frame buffers"
|
||||||
|
default 3
|
||||||
|
range 1 3
|
||||||
|
help
|
||||||
|
Let DPI LCD driver create a specified number of frame-size buffers. Only when it is set to multiple can the avoiding tearing be turned on.
|
||||||
|
|
||||||
|
config BSP_DISPLAY_BRIGHTNESS_LEDC_CH
|
||||||
|
int "LEDC channel index"
|
||||||
|
default 1
|
||||||
|
range 0 7
|
||||||
|
help
|
||||||
|
LEDC channel is used to generate PWM signal that controls display brightness.
|
||||||
|
Set LEDC index that should be used.
|
||||||
|
|
||||||
|
choice BSP_LCD_COLOR_FORMAT
|
||||||
|
prompt "Select LCD color format"
|
||||||
|
default BSP_LCD_COLOR_FORMAT_RGB565
|
||||||
|
help
|
||||||
|
Select the LCD color format RGB565/RGB888.
|
||||||
|
|
||||||
|
config BSP_LCD_COLOR_FORMAT_RGB565
|
||||||
|
bool "RGB565"
|
||||||
|
config BSP_LCD_COLOR_FORMAT_RGB888
|
||||||
|
bool "RGB888"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice BSP_LCD_TYPE
|
||||||
|
prompt "Select LCD type"
|
||||||
|
default BSP_LCD_TYPE_800_800_3_4_INCH
|
||||||
|
help
|
||||||
|
Select the LCD.
|
||||||
|
|
||||||
|
config BSP_LCD_TYPE_800_800_3_4_INCH
|
||||||
|
bool "Waveshare board with 800*800 3.4-inch Display"
|
||||||
|
config BSP_LCD_TYPE_720_720_4_INCH
|
||||||
|
bool "Waveshare board with 720*720 4-inch Display"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
endmenu
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# BSP: Waveshare ESP32-P4-WIFI6-Touch-LCD-XC
|
||||||
|
|
||||||
|
[](https://components.espressif.com/components/waveshare/esp32_p4_wifi6_touch_lcd_xc)
|
||||||
|
|
||||||
|
ESP32-P4-NANO is a small size and highly integrated development board designed by waveshare electronics based on ESP32-P4 chip
|
||||||
|
| HW version | BSP Version |
|
||||||
|
| :--------: | :---------: |
|
||||||
|
| [V1.0](http://www.waveshare.com/wiki/ESP32-P4-WIFI6-Touch-LCD-XC) | ^2 |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configuration in `menuconfig`.
|
||||||
|
|
||||||
|
Selection LCD display `Board Support Package(ESP32-P4) --> Display --> Select LCD type`
|
||||||
|
- Waveshare board with 800*800 3.4-inch Display (default)
|
||||||
|
- Waveshare board with 720*720 4-inch Display
|
||||||
|
|
||||||
|
|
||||||
|
## BackLight
|
||||||
|
```c
|
||||||
|
bsp_display_brightness_init();
|
||||||
|
|
||||||
|
bsp_display_backlight_on();
|
||||||
|
|
||||||
|
bsp_display_backlight_off();
|
||||||
|
|
||||||
|
bsp_display_brightness_set(100);
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
|||||||
|
dependencies:
|
||||||
|
esp_codec_dev:
|
||||||
|
public: true
|
||||||
|
version: ~1.5
|
||||||
|
esp_lcd_jd9365: ^2.0.0
|
||||||
|
esp_lcd_touch_gt911: ^1
|
||||||
|
espressif/esp_lvgl_adapter:
|
||||||
|
public: true
|
||||||
|
version: ~0.6
|
||||||
|
idf: '>=5.5'
|
||||||
|
lvgl/lvgl: '>=8,<10'
|
||||||
|
usb:
|
||||||
|
public: true
|
||||||
|
rules:
|
||||||
|
- if: idf_version >=6.0
|
||||||
|
version: ^1.0.0
|
||||||
|
description: Based on ESP32-P4 chip, waveshare electronics designed a 3.4-inch, 4-inch
|
||||||
|
circular screen, highly integrated development board
|
||||||
|
repository: git://github.com/waveshareteam/Waveshare-ESP32-components.git
|
||||||
|
repository_info:
|
||||||
|
commit_sha: bfeb6e6d5737178cdde78b630c8118074da0a657
|
||||||
|
path: bsp/esp32_p4_wifi6_touch_lcd_xc
|
||||||
|
tags:
|
||||||
|
- bsp
|
||||||
|
targets:
|
||||||
|
- esp32p4
|
||||||
|
url: https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-3.4c.htm
|
||||||
|
version: 3.0.1
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* BSP configuration
|
||||||
|
**************************************************************************************************/
|
||||||
|
// By default, this BSP is shipped with LVGL graphical library. Enabling this option will exclude it.
|
||||||
|
// If you want to use BSP without LVGL, select BSP version with 'noglib' suffix.
|
||||||
|
#if !defined(BSP_CONFIG_NO_GRAPHIC_LIB) // Check if the symbol is not coming from compiler definitions (-D...)
|
||||||
|
#define BSP_CONFIG_NO_GRAPHIC_LIB (0)
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "esp_lcd_types.h"
|
||||||
|
#include "esp_lcd_mipi_dsi.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
/* LCD color formats */
|
||||||
|
#define ESP_LCD_COLOR_FORMAT_RGB565 (1)
|
||||||
|
#define ESP_LCD_COLOR_FORMAT_RGB888 (2)
|
||||||
|
|
||||||
|
/* LCD display color format */
|
||||||
|
#if CONFIG_BSP_LCD_COLOR_FORMAT_RGB888
|
||||||
|
#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB888)
|
||||||
|
#else
|
||||||
|
#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB565)
|
||||||
|
#endif
|
||||||
|
/* LCD display color bytes endianess */
|
||||||
|
#define BSP_LCD_BIGENDIAN (0)
|
||||||
|
/* LCD display color bits */
|
||||||
|
#define BSP_LCD_BITS_PER_PIXEL (16)
|
||||||
|
/* LCD display color space */
|
||||||
|
#define BSP_LCD_COLOR_SPACE (LCD_RGB_ELEMENT_ORDER_RGB)
|
||||||
|
|
||||||
|
#if CONFIG_BSP_LCD_TYPE_800_800_3_4_INCH
|
||||||
|
#define BSP_LCD_H_RES (800)
|
||||||
|
#define BSP_LCD_V_RES (800)
|
||||||
|
/* 720 Mbps, not the stock 1500 (the P4 max): a high DSI lane rate makes the
|
||||||
|
* framebuffer read bursty (a whole line slammed out fast, then idle), and those
|
||||||
|
* bursty high-demand reads are what underrun when esp-hosted's Wi-Fi SDIO DMA
|
||||||
|
* contends for the PSRAM bus. Lowering the lane rate smooths the read so it
|
||||||
|
* tolerates the contention. Espressif's documented underrun fix. Floor at the
|
||||||
|
* 40 MHz pixel clock / 2 lanes is ~480 Mbps, so 720 keeps margin. */
|
||||||
|
#define BSP_LCD_MIPI_DSI_LANE_BITRATE_MBPS (720)
|
||||||
|
#elif CONFIG_BSP_LCD_TYPE_720_720_4_INCH
|
||||||
|
#define BSP_LCD_H_RES (720)
|
||||||
|
#define BSP_LCD_V_RES (720)
|
||||||
|
#define BSP_LCD_MIPI_DSI_LANE_BITRATE_MBPS (1500)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BSP_LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes
|
||||||
|
#define BSP_MIPI_DSI_PHY_PWR_LDO_CHAN (3) // LDO_VO3 is connected to VDD_MIPI_DPHY
|
||||||
|
#define BSP_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BSP display configuration structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int dummy;
|
||||||
|
} bsp_display_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BSP display return handles
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
esp_lcd_dsi_bus_handle_t mipi_dsi_bus; /*!< MIPI DSI bus handle */
|
||||||
|
esp_lcd_panel_io_handle_t io; /*!< ESP LCD IO handle */
|
||||||
|
esp_lcd_panel_handle_t panel; /*!< ESP LCD panel (color) handle */
|
||||||
|
esp_lcd_panel_handle_t control; /*!< ESP LCD panel (control) handle */
|
||||||
|
} bsp_lcd_handles_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create new display panel
|
||||||
|
*
|
||||||
|
* For maximum flexibility, this function performs only reset and initialization of the display.
|
||||||
|
* You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off().
|
||||||
|
* The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(),
|
||||||
|
* bsp_display_brightness_set() (on supported boards) or implement your own backlight control.
|
||||||
|
*
|
||||||
|
* If you want to free resources allocated by this function, you can use esp_lcd API, ie.:
|
||||||
|
*
|
||||||
|
* \code{.c}
|
||||||
|
* esp_lcd_panel_del(panel);
|
||||||
|
* esp_lcd_panel_io_del(io);
|
||||||
|
* esp_lcd_del_dsi_bus(mipi_dsi_bus);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* @param[in] config display configuration
|
||||||
|
* @param[out] ret_panel esp_lcd panel handle
|
||||||
|
* @param[out] ret_io esp_lcd IO handle
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - Else esp_lcd failure
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create new display panel
|
||||||
|
*
|
||||||
|
* For maximum flexibility, this function performs only reset and initialization of the display.
|
||||||
|
* You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off().
|
||||||
|
* The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(),
|
||||||
|
* bsp_display_brightness_set() (on supported boards) or implement your own backlight control.
|
||||||
|
*
|
||||||
|
* If you want to free resources allocated by this function, you can use esp_lcd API, ie.:
|
||||||
|
*
|
||||||
|
* \code{.c}
|
||||||
|
* esp_lcd_panel_del(panel);
|
||||||
|
* esp_lcd_panel_del(control);
|
||||||
|
* esp_lcd_panel_io_del(io);
|
||||||
|
* esp_lcd_del_dsi_bus(mipi_dsi_bus);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* @param[in] config display configuration
|
||||||
|
* @param[out] ret_handles all esp_lcd handles in one structure
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - Else esp_lcd failure
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_new_with_handles(const bsp_display_config_t *config, bsp_lcd_handles_t *ret_handles);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize display's brightness
|
||||||
|
*
|
||||||
|
* Brightness is controlled with PWM signal to a pin controlling backlight.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_brightness_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set display's brightness
|
||||||
|
*
|
||||||
|
* Brightness is controlled with PWM signal to a pin controlling backlight.
|
||||||
|
* Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new()
|
||||||
|
*
|
||||||
|
* @param[in] brightness_percent Brightness in [%]
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_brightness_set(int brightness_percent);
|
||||||
|
int bsp_display_brightness_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Turn on display backlight
|
||||||
|
*
|
||||||
|
* Brightness is controlled with PWM signal to a pin controlling backlight.
|
||||||
|
* Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new()
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_backlight_on(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Turn off display backlight
|
||||||
|
*
|
||||||
|
* Brightness is controlled with PWM signal to a pin controlling backlight.
|
||||||
|
* Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new()
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_display_backlight_off(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "bsp/esp32_p4_wifi6_touch_lcd_xc.h"
|
||||||
+342
@@ -0,0 +1,342 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/i2c_master.h"
|
||||||
|
#include "driver/sdmmc_host.h"
|
||||||
|
#include "driver/i2s_std.h"
|
||||||
|
#include "bsp/config.h"
|
||||||
|
#include "bsp/display.h"
|
||||||
|
#include "esp_codec_dev.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
|
||||||
|
#include "lvgl.h"
|
||||||
|
#include "esp_lv_adapter.h"
|
||||||
|
#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* BSP Capabilities
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
#define BSP_CAPS_DISPLAY 1
|
||||||
|
#define BSP_CAPS_TOUCH 1
|
||||||
|
#define BSP_CAPS_BUTTONS 0
|
||||||
|
#define BSP_CAPS_AUDIO 1
|
||||||
|
#define BSP_CAPS_AUDIO_SPEAKER 1
|
||||||
|
#define BSP_CAPS_AUDIO_MIC 1
|
||||||
|
#define BSP_CAPS_SDCARD 1
|
||||||
|
#define BSP_CAPS_IMU 0
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* ESP-BOX pinout
|
||||||
|
**************************************************************************************************/
|
||||||
|
/* I2C */
|
||||||
|
#define BSP_I2C_SCL (GPIO_NUM_8)
|
||||||
|
#define BSP_I2C_SDA (GPIO_NUM_7)
|
||||||
|
|
||||||
|
/* Audio */
|
||||||
|
#define BSP_I2S_SCLK (GPIO_NUM_12)
|
||||||
|
#define BSP_I2S_MCLK (GPIO_NUM_13)
|
||||||
|
#define BSP_I2S_LCLK (GPIO_NUM_10)
|
||||||
|
#define BSP_I2S_DOUT (GPIO_NUM_9)
|
||||||
|
#define BSP_I2S_DSIN (GPIO_NUM_11)
|
||||||
|
#define BSP_POWER_AMP_IO (GPIO_NUM_53)
|
||||||
|
|
||||||
|
#define BSP_LCD_BACKLIGHT (GPIO_NUM_26)
|
||||||
|
#define BSP_LCD_RST (GPIO_NUM_27)
|
||||||
|
#define BSP_LCD_TOUCH_RST (GPIO_NUM_NC)
|
||||||
|
#define BSP_LCD_TOUCH_INT (GPIO_NUM_NC)
|
||||||
|
|
||||||
|
/* uSD card */
|
||||||
|
#define BSP_SD_D0 (GPIO_NUM_39)
|
||||||
|
#define BSP_SD_D1 (GPIO_NUM_40)
|
||||||
|
#define BSP_SD_D2 (GPIO_NUM_41)
|
||||||
|
#define BSP_SD_D3 (GPIO_NUM_42)
|
||||||
|
#define BSP_SD_CMD (GPIO_NUM_44)
|
||||||
|
#define BSP_SD_CLK (GPIO_NUM_43)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* I2C interface
|
||||||
|
*
|
||||||
|
* There are multiple devices connected to I2C peripheral:
|
||||||
|
* - Codec ES8311 (configuration only)
|
||||||
|
* - LCD Touch controller
|
||||||
|
**************************************************************************************************/
|
||||||
|
#define BSP_I2C_NUM CONFIG_BSP_I2C_NUM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Init I2C driver
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG I2C parameter error
|
||||||
|
* - ESP_FAIL I2C driver installation error
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_i2c_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinit I2C driver and free its resources
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG I2C parameter error
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_i2c_deinit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get I2C driver handle
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - I2C handle
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
i2c_master_bus_handle_t bsp_i2c_get_handle(void);
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* I2S audio interface
|
||||||
|
*
|
||||||
|
* There are two devices connected to the I2S peripheral:
|
||||||
|
* - Codec ES8311 for output(playback) and input(recording) path
|
||||||
|
*
|
||||||
|
* For speaker initialization use bsp_audio_codec_speaker_init() which is inside initialize I2S with bsp_audio_init().
|
||||||
|
* For microphone initialization use bsp_audio_codec_microphone_init() which is inside initialize I2S with bsp_audio_init().
|
||||||
|
* After speaker or microphone initialization, use functions from esp_codec_dev for play/record audio.
|
||||||
|
* Example audio play:
|
||||||
|
* \code{.c}
|
||||||
|
* esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
|
||||||
|
* esp_codec_dev_open(spk_codec_dev, &fs);
|
||||||
|
* esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read_from_spiffs);
|
||||||
|
* esp_codec_dev_close(spk_codec_dev);
|
||||||
|
* \endcode
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Init audio
|
||||||
|
*
|
||||||
|
* @note There is no deinit audio function. Users can free audio resources by calling i2s_del_channel()
|
||||||
|
* @warning The type of i2s_config param is depending on IDF version.
|
||||||
|
* @param[in] i2s_config I2S configuration. Pass NULL to use default values (Mono, duplex, 16bit, 22050 Hz)
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_NOT_SUPPORTED The communication mode is not supported on the current chip
|
||||||
|
* - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration
|
||||||
|
* - ESP_ERR_NOT_FOUND No available I2S channel found
|
||||||
|
* - ESP_ERR_NO_MEM No memory for storing the channel information
|
||||||
|
* - ESP_ERR_INVALID_STATE This channel has not initialized or already started
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_audio_init(const i2s_std_config_t *i2s_config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize speaker codec device
|
||||||
|
*
|
||||||
|
* @return Pointer to codec device handle or NULL when error occurred
|
||||||
|
*/
|
||||||
|
esp_codec_dev_handle_t bsp_audio_codec_speaker_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize microphone codec device
|
||||||
|
*
|
||||||
|
* @return Pointer to codec device handle or NULL when error occurred
|
||||||
|
*/
|
||||||
|
esp_codec_dev_handle_t bsp_audio_codec_microphone_init(void);
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* SPIFFS
|
||||||
|
*
|
||||||
|
* After mounting the SPIFFS, it can be accessed with stdio functions ie.:
|
||||||
|
* \code{.c}
|
||||||
|
* FILE* f = fopen(BSP_SPIFFS_MOUNT_POINT"/hello.txt", "w");
|
||||||
|
* fprintf(f, "Hello World!\n");
|
||||||
|
* fclose(f);
|
||||||
|
* \endcode
|
||||||
|
**************************************************************************************************/
|
||||||
|
#define BSP_SPIFFS_MOUNT_POINT CONFIG_BSP_SPIFFS_MOUNT_POINT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mount SPIFFS to virtual file system
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_register was already called
|
||||||
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||||
|
* - ESP_FAIL if partition can not be mounted
|
||||||
|
* - other error codes
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_spiffs_mount(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmount SPIFFS from virtual file system
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_NOT_FOUND if the partition table does not contain SPIFFS partition with given label
|
||||||
|
* - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_unregister was already called
|
||||||
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||||
|
* - ESP_FAIL if partition can not be mounted
|
||||||
|
* - other error codes
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_spiffs_unmount(void);
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* uSD card
|
||||||
|
*
|
||||||
|
* After mounting the uSD card, it can be accessed with stdio functions ie.:
|
||||||
|
* \code{.c}
|
||||||
|
* FILE* f = fopen(BSP_MOUNT_POINT"/hello.txt", "w");
|
||||||
|
* fprintf(f, "Hello %s!\n", bsp_sdcard->cid.name);
|
||||||
|
* fclose(f);
|
||||||
|
* \endcode
|
||||||
|
**************************************************************************************************/
|
||||||
|
#define BSP_SD_MOUNT_POINT CONFIG_BSP_SD_MOUNT_POINT
|
||||||
|
extern sdmmc_card_t *bsp_sdcard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mount microSD card to virtual file system
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
|
||||||
|
* - ESP_ERR_NO_MEM if memory cannot be allocated
|
||||||
|
* - ESP_FAIL if partition cannot be mounted
|
||||||
|
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_sdcard_mount(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmount microSD card from virtual file system
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label
|
||||||
|
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called
|
||||||
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||||
|
* - ESP_FAIL if partition can not be mounted
|
||||||
|
* - other error codes from wear levelling library, SPI flash driver, or FATFS drivers
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_sdcard_unmount(void);
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* LCD interface
|
||||||
|
*
|
||||||
|
* ESP-BOX is shipped with 2.4inch ST7789 display controller.
|
||||||
|
* It features 16-bit colors, 320x240 resolution and capacitive touch controller.
|
||||||
|
*
|
||||||
|
* LVGL is used as graphics library. LVGL is NOT thread safe, therefore the user must take LVGL mutex
|
||||||
|
* by calling bsp_display_lock() before calling and LVGL API (lv_...) and then give the mutex with
|
||||||
|
* bsp_display_unlock().
|
||||||
|
*
|
||||||
|
* Display's backlight must be enabled explicitly by calling bsp_display_backlight_on()
|
||||||
|
**************************************************************************************************/
|
||||||
|
#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BSP display configuration structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
esp_lv_adapter_config_t lv_adapter_cfg;
|
||||||
|
esp_lv_adapter_rotation_t rotation;
|
||||||
|
esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode;
|
||||||
|
struct {
|
||||||
|
unsigned int swap_xy; /*!< Swap X and Y after read coordinates */
|
||||||
|
unsigned int mirror_x; /*!< Mirror X after read coordinates */
|
||||||
|
unsigned int mirror_y; /*!< Mirror Y after read coordinates */
|
||||||
|
} touch_flags;
|
||||||
|
} bsp_display_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize display
|
||||||
|
*
|
||||||
|
* This function initializes SPI, display controller and starts LVGL handling task.
|
||||||
|
* LCD backlight must be enabled separately by calling bsp_display_brightness_set()
|
||||||
|
*
|
||||||
|
* @return Pointer to LVGL display or NULL when error occured
|
||||||
|
*/
|
||||||
|
lv_display_t *bsp_display_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize display
|
||||||
|
*
|
||||||
|
* This function initializes SPI, display controller and starts LVGL handling task.
|
||||||
|
* LCD backlight must be enabled separately by calling bsp_display_brightness_set()
|
||||||
|
*
|
||||||
|
* @param cfg display configuration
|
||||||
|
*
|
||||||
|
* @return Pointer to LVGL display or NULL when error occured
|
||||||
|
*/
|
||||||
|
lv_display_t *bsp_display_start_with_config(bsp_display_cfg_t *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to input device (touch, buttons, ...)
|
||||||
|
*
|
||||||
|
* @note The LVGL input device is initialized in bsp_display_start() function.
|
||||||
|
*
|
||||||
|
* @return Pointer to LVGL input device or NULL when not initialized
|
||||||
|
*/
|
||||||
|
lv_indev_t *bsp_display_get_input_dev(void);
|
||||||
|
|
||||||
|
esp_err_t bsp_display_lock(uint32_t timeout_ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Give LVGL mutex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void bsp_display_unlock(void);
|
||||||
|
esp_lcd_panel_handle_t bsp_display_get_panel_handle(void);
|
||||||
|
#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
*
|
||||||
|
* USB
|
||||||
|
*
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power modes of USB Host connector
|
||||||
|
*/
|
||||||
|
typedef enum bsp_usb_host_power_mode_t {
|
||||||
|
BSP_USB_HOST_POWER_MODE_USB_DEV, //!< Power from USB DEV port
|
||||||
|
} bsp_usb_host_power_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start USB host
|
||||||
|
*
|
||||||
|
* This is a one-stop-shop function that will configure the board for USB Host mode
|
||||||
|
* and start USB Host library
|
||||||
|
*
|
||||||
|
* @param[in] mode USB Host connector power mode (Not used on this board)
|
||||||
|
* @param[in] limit_500mA Limit output current to 500mA (Not used on this board)
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
* - ESP_ERR_NO_MEM Memory cannot be allocated
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_usb_host_start(bsp_usb_host_power_mode_t mode, bool limit_500mA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop USB host
|
||||||
|
*
|
||||||
|
* USB Host lib will be uninstalled and power from connector removed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_usb_host_stop(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "esp_lcd_touch.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create new touchscreen
|
||||||
|
*
|
||||||
|
* If you want to free resources allocated by this function, you can use esp_lcd_touch API, ie.:
|
||||||
|
*
|
||||||
|
* \code{.c}
|
||||||
|
* esp_lcd_touch_del(tp);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* @param[in] config touch configuration
|
||||||
|
* @param[out] ret_touch esp_lcd_touch touchscreen handle
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - Else esp_lcd_touch failure
|
||||||
|
*/
|
||||||
|
esp_err_t bsp_touch_new(const bsp_display_cfg_t *cfg, esp_lcd_touch_handle_t *ret_touch);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Assert on error, if selected in menuconfig. Otherwise return error code. */
|
||||||
|
#if CONFIG_BSP_ERROR_CHECK
|
||||||
|
#define BSP_ERROR_CHECK_RETURN_ERR(x) ESP_ERROR_CHECK(x)
|
||||||
|
#define BSP_ERROR_CHECK_RETURN_NULL(x) ESP_ERROR_CHECK(x)
|
||||||
|
#define BSP_ERROR_CHECK(x, ret) ESP_ERROR_CHECK(x)
|
||||||
|
#define BSP_NULL_CHECK(x, ret) assert(x)
|
||||||
|
#define BSP_NULL_CHECK_GOTO(x, goto_tag) assert(x)
|
||||||
|
#else
|
||||||
|
#define BSP_ERROR_CHECK_RETURN_ERR(x) do { \
|
||||||
|
esp_err_t err_rc_ = (x); \
|
||||||
|
if (unlikely(err_rc_ != ESP_OK)) { \
|
||||||
|
return err_rc_; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define BSP_ERROR_CHECK_RETURN_NULL(x) do { \
|
||||||
|
if (unlikely((x) != ESP_OK)) { \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define BSP_NULL_CHECK(x, ret) do { \
|
||||||
|
if ((x) == NULL) { \
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define BSP_ERROR_CHECK(x, ret) do { \
|
||||||
|
if (unlikely((x) != ESP_OK)) { \
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define BSP_NULL_CHECK_GOTO(x, goto_tag) do { \
|
||||||
|
if ((x) == NULL) { \
|
||||||
|
goto goto_tag; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
[codespell]
|
||||||
|
skip = build,*.drawio,*.svg,*.pdf,common/proto/esp_hosted_rpc.pb-c.*,slave/main/esp_hosted_coprocessor_fw_ver.h,host/esp_hosted_host_fw_ver.h
|
||||||
|
ignore-words-list = rsource,INDX,ans,aNULL,aci,DEACTIVE,OT,ot
|
||||||
|
write-changes = true
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
f970ce453bcd6e779e067de04488aa6212295f4a607f041d038844c8cf8edea3
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# EditorConfig helps developers define and maintain consistent
|
||||||
|
# coding styles between different editors and IDEs
|
||||||
|
# http://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Default configuration for all files
|
||||||
|
# - tabs for indentation
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
# Some Mermaid diagram commands need to end with a trailing whitespace in Markdown files
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
# Use two spaces for YAML files
|
||||||
|
[{*.yml,*.yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
build
|
||||||
|
dependencies.lock
|
||||||
|
managed_components
|
||||||
|
sdkconfig
|
||||||
|
sdkconfig.old
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
espressif/esp_hosted:
|
||||||
|
version: ">=1.0"
|
||||||
|
override_path: "${OVERRIDE_PATH}"
|
||||||
|
rules:
|
||||||
|
- if: "target in [esp32p4, esp32h2]"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
.check_pre_commit_template:
|
||||||
|
stage: pre
|
||||||
|
image: python:3.8
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
script:
|
||||||
|
- python3 -m venv .venv
|
||||||
|
- source .venv/bin/activate
|
||||||
|
- pip install --upgrade pip
|
||||||
|
- pip install pre-commit
|
||||||
|
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME --depth=1
|
||||||
|
- git fetch origin $CI_COMMIT_REF_NAME --depth=1
|
||||||
|
- |
|
||||||
|
echo "Target branch: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
|
||||||
|
echo "Source branch: $CI_COMMIT_REF_NAME"
|
||||||
|
|
||||||
|
MODIFIED_FILES=$(git diff --name-only origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME..origin/$CI_COMMIT_REF_NAME)
|
||||||
|
echo "Modified files to check:"
|
||||||
|
echo "$MODIFIED_FILES"
|
||||||
|
|
||||||
|
if [ -n "$MODIFIED_FILES" ]; then
|
||||||
|
CI=true pre-commit run --files $MODIFIED_FILES
|
||||||
|
else
|
||||||
|
echo "No modified files to check."
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_pre_commit:
|
||||||
|
extends:
|
||||||
|
- .check_pre_commit_template
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
# Holds jobs that run before promoting to main branch
|
||||||
|
|
||||||
|
### Notes:
|
||||||
|
# IDF v5.3 and v5.3.1 do not build for P4
|
||||||
|
# - fix only merged for v5.3.2 and above
|
||||||
|
# - https://github.com/espressif/esp-idf/commit/1aec9e7df38bb7ccc9ec2fb846288910c329d77a
|
||||||
|
|
||||||
|
### IDF master and v6.x don't build mqtt example with wifi-remote and ESP-Hosted
|
||||||
|
### so we only verify mqtt example against earlier IDF
|
||||||
|
regression_build_idf_v5.3_mqtt_h2:
|
||||||
|
variables:
|
||||||
|
EXAMPLE_CI_FILE: "sdkconfig.ci.p4_wifi"
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example_mqtt
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_TARGET: ["esp32h2"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
|
||||||
|
regression_build_idf_v5.3_mqtt_p4:
|
||||||
|
variables:
|
||||||
|
EXAMPLE_CI_FILE: "sdkconfig.ci.p4_wifi"
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example_mqtt
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
|
||||||
|
regression_build_idf_v5.4_mqtt:
|
||||||
|
variables:
|
||||||
|
EXAMPLE_CI_FILE: "sdkconfig.ci.p4_wifi"
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example_mqtt
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "v5.4.4", "release-v5.4"]
|
||||||
|
IDF_TARGET: ["esp32p4", "esp32h2"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
|
||||||
|
regression_build_idf_v5.5_iperf:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["v5.5", "v5.5.1", "v5.5.2", "v5.5.3", "release-v5.5"]
|
||||||
|
IDF_TARGET: ["esp32p4", "esp32h2"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32", "esp32c2", "esp32c3", "esp32s3" ]
|
||||||
|
IDF_EXAMPLE_PATH: ["examples/wifi/iperf"]
|
||||||
|
|
||||||
|
regression_build_idf_master_iperf:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:latest
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4", "esp32h2"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32", "esp32c2", "esp32c3", "esp32s3" ]
|
||||||
|
IDF_EXAMPLE_PATH: ["examples/wifi/iperf"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.3_pt1:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6"]
|
||||||
|
IDF_VER: ["v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "spi_hd", "uart", "dpp"]
|
||||||
|
# override performance optimization to prevent build errors
|
||||||
|
CONFIG_OVERRIDE: "CONFIG_COMPILER_OPTIMIZATION_DEBUG=y"
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.3_pt2:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c2", "esp32c3", "esp32s3"]
|
||||||
|
IDF_VER: ["v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
SLAVE_CI_FILE: ["spi", "spi_hd", "uart"]
|
||||||
|
# override performance optimization to prevent build errors
|
||||||
|
CONFIG_OVERRIDE: "CONFIG_COMPILER_OPTIMIZATION_DEBUG=y"
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.3_esp32:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32"]
|
||||||
|
IDF_VER: ["v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "uart"]
|
||||||
|
# override performance optimization to prevent build errors
|
||||||
|
CONFIG_OVERRIDE: "CONFIG_COMPILER_OPTIMIZATION_DEBUG=y"
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.4_pt1:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "v5.4.4", "release-v5.4"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "spi_hd", "uart", "dpp"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.4_pt2:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c2", "esp32c3", "esp32s3"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "v5.4.4", "release-v5.4"]
|
||||||
|
SLAVE_CI_FILE: ["spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.4_esp32:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "v5.4.4", "release-v5.4"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "uart"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.5:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c2", "esp32c3", "esp32s3"]
|
||||||
|
IDF_VER: ["v5.5", "v5.5.1", "v5.5.2", "v5.5.3", "release-v5.5"]
|
||||||
|
SLAVE_CI_FILE: ["spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_v5.5_esp32:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32"]
|
||||||
|
IDF_VER: ["v5.5", "v5.5.1", "v5.5.2", "v5.5.3", "release-v5.5"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "uart"]
|
||||||
|
|
||||||
|
regression_build_coprocessor_idf_master_all_features_enabled:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:latest
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6"]
|
||||||
|
SLAVE_CI_FILE: ["all_features"]
|
||||||
|
|
||||||
|
regression_build_nimble_examples_h2:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32h2"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_nimble_bleprph_host_only_vhci",
|
||||||
|
"host_nimble_bleprph_host_only_uart_hci"]
|
||||||
|
|
||||||
|
regression_build_nimble_examples_p4:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_nimble_bleprph_host_only_vhci",
|
||||||
|
"host_nimble_bleprph_host_only_uart_hci"]
|
||||||
|
|
||||||
|
regression_build_bluedroid_examples_h2:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32h2"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_bluedroid_ble_compatibility_test",
|
||||||
|
"host_bluedroid_bt_hid_mouse_device",
|
||||||
|
"host_bluedroid_host_only",
|
||||||
|
"host_bt_controller_mac_addr"]
|
||||||
|
|
||||||
|
regression_build_bluedroid_examples_p4:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_bluedroid_ble_compatibility_test",
|
||||||
|
"host_bluedroid_bt_hid_mouse_device",
|
||||||
|
"host_bluedroid_host_only",
|
||||||
|
"host_bt_controller_mac_addr"]
|
||||||
|
|
||||||
|
regression_build_wifi_examples_h2:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32h2"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3", "v5.3.1", "v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_wifi_easy_connect_dpp_enrollee",
|
||||||
|
"host_wifi_itwt",
|
||||||
|
"host_transport_config",
|
||||||
|
"host_network_split__power_save"]
|
||||||
|
|
||||||
|
regression_build_wifi_examples_p4:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_wifi_easy_connect_dpp_enrollee",
|
||||||
|
"host_wifi_itwt",
|
||||||
|
"host_transport_config",
|
||||||
|
"host_network_split__power_save"]
|
||||||
|
|
||||||
|
# build an example using the various transports
|
||||||
|
# this is to verify transport builds as expected on the host
|
||||||
|
# for h2, build only for ESP-IDF v5.3 and v5.3.1
|
||||||
|
# for p4, build for other ESP-IDFs
|
||||||
|
regression_build_transport_examples_h2:
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32h2"]
|
||||||
|
IDF_VER: ["v5.3", "v5.3.1"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_network_split__power_save"]
|
||||||
|
EXAMPLE_CI_FILE: ["spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
regression_build_transport_examples_p4:
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_network_split__power_save"]
|
||||||
|
EXAMPLE_CI_FILE: ["sdio", "spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
regression_build_misc_examples:
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
rules:
|
||||||
|
- !reference [.staging_branch_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4", "esp32h2"]
|
||||||
|
IDF_VER: ["v5.4", "v5.4.1", "v5.4.2", "v5.4.3", "release-v5.4",
|
||||||
|
"v5.3.2", "v5.3.3", "v5.3.4", "v5.3.5", "release-v5.3"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_gpio_expander",
|
||||||
|
"host_peer_data_transfer",
|
||||||
|
"host_performs_slave_ota"]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Holds rules for running jobs
|
||||||
|
|
||||||
|
# default rule
|
||||||
|
# used for running jobs on a merge request to staging
|
||||||
|
.default_rules:
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == "staging" && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
when: never
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "staging"
|
||||||
|
|
||||||
|
# staging branch rule
|
||||||
|
# used for running regression jobs on staging branch
|
||||||
|
.staging_branch_rules:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
when: never
|
||||||
|
- if: $CI_COMMIT_BRANCH == "staging" && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
|
||||||
|
# no build rule to disable jobs temporarily
|
||||||
|
# while testing new build rules
|
||||||
|
.no_build_rules:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
when: never
|
||||||
|
- if: $CI_COMMIT_BRANCH == "staging" && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
when: never
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
# Holds jobs that run from a merge request
|
||||||
|
|
||||||
|
###
|
||||||
|
### Check project pre-requisites have been fulfilled
|
||||||
|
###
|
||||||
|
|
||||||
|
premerge_check:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .premerge_check_template
|
||||||
|
image: espressif/idf:latest
|
||||||
|
|
||||||
|
###
|
||||||
|
### Build host using ESP-IDF examples
|
||||||
|
###
|
||||||
|
|
||||||
|
### protocols/mqtt example
|
||||||
|
### IDF master and v6.x don't build mqtt example with wifi-remote and ESP-Hosted
|
||||||
|
### so we only verify mqtt example against earlier IDF
|
||||||
|
sanity_build_idf_release_mqtt:
|
||||||
|
variables:
|
||||||
|
EXAMPLE_CI_FILE: "sdkconfig.ci.p4_wifi"
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example_mqtt
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["release-v5.5"]
|
||||||
|
IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
|
||||||
|
### wifi/iperf example
|
||||||
|
sanity_build_idf_v5.5_iperf:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_VER: ["v5.5.4", "release-v5.5"]
|
||||||
|
IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
IDF_EXAMPLE_PATH: ["examples/wifi/iperf"]
|
||||||
|
|
||||||
|
sanity_build_idf_master_iperf:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:latest
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5", "esp32c61"]
|
||||||
|
IDF_EXAMPLE_PATH: ["examples/wifi/iperf"]
|
||||||
|
|
||||||
|
###
|
||||||
|
### Build coprocessor
|
||||||
|
###
|
||||||
|
|
||||||
|
sanity_build_coprocessor_idf_v5.5:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
IDF_VER: ["v5.5.4", "release-v5.5"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "spi_hd", "uart", "dpp"]
|
||||||
|
|
||||||
|
# verify co-processor targets with Wi-Fi + BT
|
||||||
|
sanity_build_coprocessor_idf_master:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:latest
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6", "esp32c5", "esp32c61"]
|
||||||
|
SLAVE_CI_FILE: ["sdio", "spi", "spi_hd", "uart", "dpp"]
|
||||||
|
|
||||||
|
# verify co-processor targets with BT only
|
||||||
|
sanity_build_coprocessor_idf_master_2:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:latest
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32h2"]
|
||||||
|
SLAVE_CI_FILE: ["spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
# verify co-processor targets with OpenThread RCP
|
||||||
|
# v5.5.4 is for Zigbee SDK release
|
||||||
|
sanity_build_coprocessor_rcp:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_coprocessor
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32c6", "esp32c5", "esp32h2"]
|
||||||
|
IDF_VER: ["latest", "v5.5.4"]
|
||||||
|
SLAVE_CI_FILE: ["openthread_rcp"]
|
||||||
|
|
||||||
|
###
|
||||||
|
### build ESP-Hosted examples
|
||||||
|
###
|
||||||
|
|
||||||
|
sanity_build_nimble_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest",
|
||||||
|
"v5.5.4", "release-v5.5"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32h2"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_nimble_bleprph_host_only_vhci",
|
||||||
|
"host_nimble_bleprph_host_only_uart_hci"]
|
||||||
|
|
||||||
|
# verify host builds with co-processor target with BT only
|
||||||
|
sanity_build_nimble_examples_2:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32h2"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_nimble_bleprph_host_only_vhci",
|
||||||
|
"host_nimble_bleprph_host_only_uart_hci"]
|
||||||
|
|
||||||
|
sanity_build_bluedroid_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest",
|
||||||
|
"v5.5.4", "release-v5.5"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_bluedroid_ble_compatibility_test",
|
||||||
|
"host_bluedroid_bt_hid_mouse_device",
|
||||||
|
"host_bluedroid_host_only",
|
||||||
|
"host_bt_controller_mac_addr"]
|
||||||
|
|
||||||
|
sanity_build_wifi_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest",
|
||||||
|
"v5.5.4", "release-v5.5"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_wifi_easy_connect_dpp_enrollee",
|
||||||
|
"host_wifi_itwt",
|
||||||
|
"host_transport_config",
|
||||||
|
"host_network_split__power_save",
|
||||||
|
"host_performs_slave_ota"]
|
||||||
|
|
||||||
|
# build an example using the various transports
|
||||||
|
# this is to verify transport builds as expected on the host
|
||||||
|
sanity_build_transport_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest",
|
||||||
|
"v5.5.4", "release-v5.5"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_network_split__power_save"]
|
||||||
|
EXAMPLE_CI_FILE: ["sdio", "spi", "spi_hd", "uart"]
|
||||||
|
|
||||||
|
# build OpenThread Host examples
|
||||||
|
sanity_build_openthread_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["latest"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_openthread_border_router",
|
||||||
|
"host_openthread_cli"]
|
||||||
|
|
||||||
|
# build Zigbee Host examples
|
||||||
|
sanity_build_zigbee_examples:
|
||||||
|
rules:
|
||||||
|
- !reference [.default_rules, rules]
|
||||||
|
extends: .build_template_example
|
||||||
|
image: espressif/idf:${IDF_VER}
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- IDF_TARGET: ["esp32p4"]
|
||||||
|
IDF_VER: ["v5.5.4"]
|
||||||
|
IDF_SLAVE_TARGET: ["esp32c6", "esp32c5"]
|
||||||
|
EXAMPLE_TO_BUILD: ["host_zigbee_thermostat"]
|
||||||
|
|
||||||
|
###
|
||||||
|
### Promote staging to main after successful regression testing
|
||||||
|
###
|
||||||
|
|
||||||
|
promote_staging_to_main:
|
||||||
|
stage: deploy
|
||||||
|
dependencies: []
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == "staging" && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
script:
|
||||||
|
- git remote set-url origin https://oauth2:${GITLAB_TOKEN_STAGING_TO_MAIN}@gitlab.espressif.cn:6688/app-frameworks/esp_hosted_mcu.git
|
||||||
|
- git push origin $CI_COMMIT_SHA:main
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
# Holds templates used for jobs
|
||||||
|
|
||||||
|
.premerge_check_template:
|
||||||
|
stage: pre
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
script:
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
# check the exported fw versions
|
||||||
|
- python tools/check_fw_versions.py
|
||||||
|
# check the changelog
|
||||||
|
- python tools/check_changelog.py
|
||||||
|
# check weak functions # Can also pass --functions optionally # Can also pass --functions optionally.
|
||||||
|
- python tools/check_weak_functions.py --file host/api/src/esp_wifi_weak.c
|
||||||
|
|
||||||
|
.build_template_coprocessor:
|
||||||
|
stage: build_coprocessor
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
dependencies: []
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
expire_in: 4 days
|
||||||
|
script:
|
||||||
|
- export IDF_PYTHON_CHECK_CONSTRAINTS=yes
|
||||||
|
- ${IDF_PATH}/install.sh --enable-ci
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
- SDKCONFIG_PATTERN="sdkconfig.ci.${SLAVE_CI_FILE}"
|
||||||
|
# Build with IDF pedantic flags and IDF build apps script
|
||||||
|
- export ESP_HOSTED_CI_PEDANTIC=1
|
||||||
|
- export EXTRA_CFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- export EXTRA_CXXFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- |
|
||||||
|
if [[ -n ${CONFIG_OVERRIDE} ]]; then
|
||||||
|
CONFIG_OVERRIDE_STRING="--override-sdkconfig-items=${CONFIG_OVERRIDE}"
|
||||||
|
echo "adding ${CONFIG_OVERRIDE_STRING} to build"
|
||||||
|
fi
|
||||||
|
- cd slave
|
||||||
|
# use --enable-preview-targets to build for all targets
|
||||||
|
- idf-build-apps find -p . --enable-preview-targets --config ${SDKCONFIG_PATTERN} ${CONFIG_OVERRIDE_STRING} -vv --target ${IDF_TARGET}
|
||||||
|
- idf-build-apps build -p . --enable-preview-targets --config ${SDKCONFIG_PATTERN} ${CONFIG_OVERRIDE_STRING} -vv --target ${IDF_TARGET}
|
||||||
|
|
||||||
|
.build_template_example:
|
||||||
|
stage: build_example
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
dependencies: []
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
expire_in: 4 days
|
||||||
|
script:
|
||||||
|
- export IDF_PYTHON_CHECK_CONSTRAINTS=yes
|
||||||
|
- ${IDF_PATH}/install.sh --enable-ci
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
# Need to rename the cloned "esp_hosted_mcu" directory since the injected component name is "esp_hosted"
|
||||||
|
- cd .. && rm -rf esp_hosted && mv esp_hosted_mcu esp_hosted && cd esp_hosted
|
||||||
|
# Create components directory and link esp_hosted component
|
||||||
|
- export OVERRIDE_PATH=`pwd`
|
||||||
|
- cd examples/${EXAMPLE_TO_BUILD}
|
||||||
|
# Create components directory and link esp_hosted component
|
||||||
|
- mkdir -p components
|
||||||
|
- ln -sf ${OVERRIDE_PATH} components/esp_hosted
|
||||||
|
# Override component dependency as backup only if not already present
|
||||||
|
- |
|
||||||
|
if ! grep -q "esp_hosted" main/idf_component.yml 2>/dev/null; then
|
||||||
|
cat ${OVERRIDE_PATH}/.gitlab-ci-override-idf-component.yml >> main/idf_component.yml
|
||||||
|
echo "Added esp_hosted override to idf_component.yml"
|
||||||
|
fi
|
||||||
|
# Add slave target configuration if specified
|
||||||
|
# Also add wi-fi remote slave target for supported targets (not ESP32-H2)
|
||||||
|
- |
|
||||||
|
if [ ! -z "${IDF_SLAVE_TARGET}" ]; then
|
||||||
|
if [[ "${IDF_SLAVE_TARGET}" != "esp32h2" ]]; then
|
||||||
|
echo "CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
echo "CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# Append sdkconfig.ci.common if available
|
||||||
|
- |
|
||||||
|
if [ -f sdkconfig.ci.common ]; then
|
||||||
|
cat sdkconfig.ci.common >> sdkconfig.defaults
|
||||||
|
echo "Appended sdkconfig.ci.common to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# Build with IDF pedantic flags and IDF build apps script
|
||||||
|
- export ESP_HOSTED_CI_PEDANTIC=1
|
||||||
|
- export EXTRA_CFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- export EXTRA_CXXFLAGS="-DIDF_CI_BUILD"
|
||||||
|
# Build with extra ci config file if specified
|
||||||
|
- |
|
||||||
|
if [ ! -z "${EXAMPLE_CI_FILE}" ]; then
|
||||||
|
idf-build-apps find -p . -vv --config sdkconfig.ci.${EXAMPLE_CI_FILE} --target ${IDF_TARGET}
|
||||||
|
idf-build-apps build -p . -vv --config sdkconfig.ci.${EXAMPLE_CI_FILE} --target ${IDF_TARGET}
|
||||||
|
else
|
||||||
|
idf-build-apps find -p . -vv --target ${IDF_TARGET}
|
||||||
|
idf-build-apps build -p . -vv --target ${IDF_TARGET}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build mqtt example from examples/protocol/mqtt
|
||||||
|
# the example may be mqtt or mqtt/tcp, depending on IDF version
|
||||||
|
.build_template_example_mqtt:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- "artifacts_*/"
|
||||||
|
when: always
|
||||||
|
expire_in: 4 days
|
||||||
|
script:
|
||||||
|
- export IDF_PYTHON_CHECK_CONSTRAINTS=yes
|
||||||
|
- ${IDF_PATH}/install.sh --enable-ci
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
# Need to rename the cloned "esp_hosted_mcu" directory since the injected component name is "esp_hosted"
|
||||||
|
- cd .. && rm -rf esp_hosted && mv esp_hosted_mcu esp_hosted && cd esp_hosted
|
||||||
|
- export OVERRIDE_PATH=`pwd`
|
||||||
|
# get path to mqtt example to build
|
||||||
|
- |
|
||||||
|
# Check if the newer path structure exists (latest and release-v6.0)
|
||||||
|
if [ -f "${IDF_PATH}/examples/protocols/mqtt/main/idf_component.yml" ]; then
|
||||||
|
MQTT_EXAMPLE_PATH="${IDF_PATH}/examples/protocols/mqtt"
|
||||||
|
# Fall back to older path structure (release-v5.x and earlier)
|
||||||
|
elif [ -f "${IDF_PATH}/examples/protocols/mqtt/tcp/main/idf_component.yml" ]; then
|
||||||
|
MQTT_EXAMPLE_PATH="${IDF_PATH}/examples/protocols/mqtt/tcp"
|
||||||
|
else
|
||||||
|
echo "Error: Could not find MQTT example at either path"
|
||||||
|
ls -la ${IDF_PATH}/examples/protocols/mqtt/ || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Using MQTT example path: ${MQTT_EXAMPLE_PATH}"
|
||||||
|
- cd ${MQTT_EXAMPLE_PATH}
|
||||||
|
# Create components directory and link esp_hosted component
|
||||||
|
- mkdir -p components
|
||||||
|
- ln -sf ${OVERRIDE_PATH} components/esp_hosted
|
||||||
|
# Override component dependency as backup only if not already present
|
||||||
|
- |
|
||||||
|
if ! grep -q "esp_hosted" main/idf_component.yml 2>/dev/null; then
|
||||||
|
cat ${OVERRIDE_PATH}/.gitlab-ci-override-idf-component.yml >> main/idf_component.yml
|
||||||
|
echo "Added esp_hosted override to idf_component.yml"
|
||||||
|
fi
|
||||||
|
# Add slave target configuration if specified
|
||||||
|
# Also add wi-fi remote slave target for supported targets (not ESP32-H2)
|
||||||
|
- |
|
||||||
|
if [ ! -z "${IDF_SLAVE_TARGET}" ]; then
|
||||||
|
if [[ "${IDF_SLAVE_TARGET}" != "esp32h2" ]]; then
|
||||||
|
echo "CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
echo "CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# Append sdkconfig.ci.common if available
|
||||||
|
- |
|
||||||
|
if [ -f sdkconfig.ci.common ]; then
|
||||||
|
cat sdkconfig.ci.common >> sdkconfig.defaults
|
||||||
|
echo "Appended sdkconfig.ci.common to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# Build with IDF pedantic flags and IDF build apps script
|
||||||
|
- export ESP_HOSTED_CI_PEDANTIC=1
|
||||||
|
- export EXTRA_CFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- export EXTRA_CXXFLAGS="-DIDF_CI_BUILD"
|
||||||
|
# use --config-file to override default IDF config file
|
||||||
|
# use --enable-preview-targets to build for all targets
|
||||||
|
# use --override-sdkconfig-items to override (possibly incorrect) build target that may be in provided config file
|
||||||
|
- idf-build-apps find -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
- idf-build-apps build -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
# Copy config files back to project directory for artifacts
|
||||||
|
- mkdir -p ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}
|
||||||
|
- cp sdkconfig* ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No sdkconfig files found"
|
||||||
|
- cp main/idf_component.yml ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No component file found"
|
||||||
|
# Clean up the component symlink
|
||||||
|
- unlink components/esp_hosted
|
||||||
|
- echo "Cleaned up esp_hosted component symlink"
|
||||||
|
# Rename back, since post scripts expect the original name
|
||||||
|
- cd ${OVERRIDE_PATH} && cd .. && mv esp_hosted esp_hosted_mcu
|
||||||
|
|
||||||
|
# build mqtt/tcp example from espressif/mqtt Registry Component
|
||||||
|
.build_template_mqtt_tcp_component:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- "artifacts_*/"
|
||||||
|
when: always
|
||||||
|
expire_in: 4 days
|
||||||
|
script:
|
||||||
|
- export IDF_PYTHON_CHECK_CONSTRAINTS=yes
|
||||||
|
- ${IDF_PATH}/install.sh --enable-ci
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
# Need to rename the cloned "esp_hosted_mcu" directory since the injected component name is "esp_hosted"
|
||||||
|
- cd .. && rm -rf esp_hosted && mv esp_hosted_mcu esp_hosted && cd esp_hosted
|
||||||
|
- export OVERRIDE_PATH=`pwd`
|
||||||
|
# get the example from Component Registry
|
||||||
|
- echo "Checking out example ${IDF_REGISTRY_COMPONENT}:${IDF_REGISTRY_COMPONENT_EXAMPLE}"
|
||||||
|
- cd ..
|
||||||
|
- idf.py create-project-from-example "${IDF_REGISTRY_COMPONENT}:${IDF_REGISTRY_COMPONENT_EXAMPLE}"
|
||||||
|
- cd "${IDF_REGISTRY_COMPONENT_EXAMPLE}"
|
||||||
|
# Override esp_hosted component in example's deps with the one from the current repository
|
||||||
|
- mkdir -p components
|
||||||
|
- ln -sf ${OVERRIDE_PATH} components/esp_hosted
|
||||||
|
# Add slave target configuration if specified
|
||||||
|
# Also add wi-fi remote slave target for supported targets (not ESP32-H2)
|
||||||
|
- |
|
||||||
|
if [ ! -z "${IDF_SLAVE_TARGET}" ]; then
|
||||||
|
if [[ "${IDF_SLAVE_TARGET}" != "esp32h2" ]]; then
|
||||||
|
echo "CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
echo "CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added slave target CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# EXAMPLE_CI_FILE: use sdkconfig CI file in example directory
|
||||||
|
- |
|
||||||
|
if [ ! -z "${SDKCONFIG_CI_FILE}" ]; then
|
||||||
|
cp ${OVERRIDE_PATH}/${SDKCONFIG_CI_FILE} ./sdkconfig.ci.custom
|
||||||
|
echo "Using custom sdkconfig: ${SDKCONFIG_CI_FILE}"
|
||||||
|
SDKCONFIG_PATTERN="sdkconfig.ci.custom"
|
||||||
|
elif [ ! -z "${EXAMPLE_CI_FILE}" ]; then
|
||||||
|
echo "Using CI sdkconfig file in example: ${EXAMPLE_CI_FILE}"
|
||||||
|
SDKCONFIG_PATTERN="./${EXAMPLE_CI_FILE}"
|
||||||
|
else
|
||||||
|
SDKCONFIG_PATTERN="sdkconfig.ci*"
|
||||||
|
fi
|
||||||
|
- echo "SDKCONFIG_PATTERN is ${SDKCONFIG_PATTERN}"
|
||||||
|
# Build with IDF pedantic flags and IDF build apps script
|
||||||
|
- export ESP_HOSTED_CI_PEDANTIC=1
|
||||||
|
- export EXTRA_CFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- export EXTRA_CXXFLAGS="-DIDF_CI_BUILD"
|
||||||
|
# use --config-file to override default IDF config file
|
||||||
|
# use --enable-preview-targets to build for all targets
|
||||||
|
# use --override-sdkconfig-items to override (possibly incorrect) build target that may be in provided config file
|
||||||
|
- idf-build-apps find -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --config ${SDKCONFIG_PATTERN} --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
- idf-build-apps build -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --config ${SDKCONFIG_PATTERN} --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
# Copy config files back to project directory for artifacts
|
||||||
|
- mkdir -p ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}
|
||||||
|
- cp sdkconfig* ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No sdkconfig files found"
|
||||||
|
- cp main/idf_component.yml ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No component file found"
|
||||||
|
# Clean up the component symlink
|
||||||
|
- unlink components/esp_hosted
|
||||||
|
- echo "Cleaned up esp_hosted component symlink"
|
||||||
|
# Rename back, since post scripts expect the original name
|
||||||
|
- cd ${OVERRIDE_PATH} && cd .. && mv esp_hosted esp_hosted_mcu
|
||||||
|
|
||||||
|
|
||||||
|
.build_template:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- "artifacts_*/"
|
||||||
|
when: always
|
||||||
|
expire_in: 4 days
|
||||||
|
script:
|
||||||
|
- export IDF_PYTHON_CHECK_CONSTRAINTS=yes
|
||||||
|
- ${IDF_PATH}/install.sh --enable-ci
|
||||||
|
- source ${IDF_PATH}/export.sh
|
||||||
|
# Need to rename the cloned "esp_hosted_mcu" directory since the injected component name is "esp_hosted"
|
||||||
|
- cd .. && rm -rf esp_hosted && mv esp_hosted_mcu esp_hosted && cd esp_hosted
|
||||||
|
# Replaces esp_hosted component in example's deps with the one from the current repository
|
||||||
|
- export OVERRIDE_PATH=`pwd`
|
||||||
|
- cd ${IDF_PATH}/${IDF_EXAMPLE_PATH}
|
||||||
|
# Create components directory and link esp_hosted component
|
||||||
|
- mkdir -p components
|
||||||
|
- ln -sf ${OVERRIDE_PATH} components/esp_hosted
|
||||||
|
- echo "Created components directory with esp_hosted link:"
|
||||||
|
- ls -la components/
|
||||||
|
# Override component dependency as backup only if not already present
|
||||||
|
- |
|
||||||
|
if ! grep -q "esp_hosted" main/idf_component.yml 2>/dev/null; then
|
||||||
|
cat ${OVERRIDE_PATH}/.gitlab-ci-override-idf-component.yml >> main/idf_component.yml
|
||||||
|
echo "Added esp_hosted override to idf_component.yml"
|
||||||
|
fi
|
||||||
|
# Add slave target configuration if specified
|
||||||
|
# Also add wi-fi remote slave target for supported targets (not ESP32-H2)
|
||||||
|
- |
|
||||||
|
if [ ! -z "${IDF_SLAVE_TARGET}" ]; then
|
||||||
|
if [[ "${IDF_SLAVE_TARGET}" != "esp32h2" ]]; then
|
||||||
|
echo "CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added target CONFIG_SLAVE_IDF_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
echo "CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y" >> sdkconfig.defaults
|
||||||
|
echo "Added slave target CONFIG_ESP_HOSTED_CP_TARGET_${IDF_SLAVE_TARGET^^}=y to sdkconfig.defaults"
|
||||||
|
fi
|
||||||
|
# HOSTED_CI_FILE: use custom sdkconfig CI file from esp_hosted directory, or
|
||||||
|
# EXAMPLE_CI_FILE: use sdkconfig CI file in example directory
|
||||||
|
- |
|
||||||
|
if [ ! -z "${SDKCONFIG_CI_FILE}" ]; then
|
||||||
|
cp ${OVERRIDE_PATH}/${SDKCONFIG_CI_FILE} ./sdkconfig.ci.custom
|
||||||
|
echo "Using custom sdkconfig: ${SDKCONFIG_CI_FILE}"
|
||||||
|
SDKCONFIG_PATTERN="sdkconfig.ci.custom"
|
||||||
|
elif [ ! -z "${EXAMPLE_CI_FILE}" ]; then
|
||||||
|
echo "Using CI sdkconfig file in example: ${EXAMPLE_CI_FILE}"
|
||||||
|
SDKCONFIG_PATTERN="./${EXAMPLE_CI_FILE}"
|
||||||
|
else
|
||||||
|
SDKCONFIG_PATTERN="sdkconfig.ci*"
|
||||||
|
fi
|
||||||
|
- echo "SDKCONFIG_PATTERN is ${SDKCONFIG_PATTERN}"
|
||||||
|
# Build with IDF pedantic flags and IDF build apps script
|
||||||
|
- export ESP_HOSTED_CI_PEDANTIC=1
|
||||||
|
- export EXTRA_CFLAGS="-DIDF_CI_BUILD"
|
||||||
|
- export EXTRA_CXXFLAGS="-DIDF_CI_BUILD"
|
||||||
|
# Remove the conflicting extconn config that disables hosted
|
||||||
|
- rm -f sdkconfig.ci.*extconn*
|
||||||
|
# use --config-file to override default IDF config file
|
||||||
|
# use --enable-preview-targets to build for all targets
|
||||||
|
# use --override-sdkconfig-items to override (possibly incorrect) build target that may be in provided config file
|
||||||
|
- idf-build-apps find -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --config ${SDKCONFIG_PATTERN} --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
- idf-build-apps build -p . --enable-preview-targets --config-file "${OVERRIDE_PATH}/.idf_build_apps.toml" --config ${SDKCONFIG_PATTERN} --override-sdkconfig-items=CONFIG_IDF_TARGET=${IDF_TARGET} -vv --target ${IDF_TARGET}
|
||||||
|
# - echo "----------- last sdkconfig.defaults,ci* used (${IDF_TARGET}-${IDF_SLAVE_TARGET}) --------------"
|
||||||
|
# - cat sdkconfig.defaults
|
||||||
|
# - cat sdkconfig.ci*
|
||||||
|
# - echo "----------- last (generated) sdkconfig used (${IDF_TARGET}-${IDF_SLAVE_TARGET}) --------------"
|
||||||
|
# - cat sdkconfig
|
||||||
|
# - echo "----------------------------------------------"
|
||||||
|
# Copy config files back to project directory for artifacts
|
||||||
|
- mkdir -p ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}
|
||||||
|
- cp sdkconfig* ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No sdkconfig files found"
|
||||||
|
- cp main/idf_component.yml ${OVERRIDE_PATH}/artifacts_${IDF_TARGET}_${IDF_SLAVE_TARGET}/ 2>/dev/null || echo "No component file found"
|
||||||
|
# Clean up the component symlink
|
||||||
|
- unlink components/esp_hosted
|
||||||
|
- echo "Cleaned up esp_hosted component symlink"
|
||||||
|
# Rename back, since post scripts expect the original name
|
||||||
|
- cd ${OVERRIDE_PATH} && cd .. && mv esp_hosted esp_hosted_mcu
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "esp_hosted_fg/common/protobuf-c"]
|
||||||
|
path = common/protobuf-c
|
||||||
|
url = https://github.com/protobuf-c/protobuf-c.git
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
build_log_filename = ""
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: version-checker
|
||||||
|
name: ESP-Hosted Version Checker
|
||||||
|
entry: tools/check_fw_versions.py
|
||||||
|
language: python
|
||||||
|
args: [ "--update" ]
|
||||||
|
always_run: true
|
||||||
|
pass_filenames: false
|
||||||
|
- id: rpc-checker
|
||||||
|
name: ESP-Hosted RPC Checker
|
||||||
|
entry: tools/check_rpc_calls.py
|
||||||
|
language: python
|
||||||
|
always_run: true
|
||||||
|
pass_filenames: false
|
||||||
|
- id: changelog-checker
|
||||||
|
name: ESP-Hosted Changelog Checker
|
||||||
|
entry: tools/check_changelog.py
|
||||||
|
language: python
|
||||||
|
files: ^idf_component.yml$
|
||||||
|
- id: esp-weak-function-checker
|
||||||
|
name: ESP-Hosted Weak Function Checker
|
||||||
|
entry: tools/check_weak_functions.py
|
||||||
|
language: python
|
||||||
|
args:
|
||||||
|
- "--file"
|
||||||
|
- "host/api/src/esp_wifi_weak.c"
|
||||||
|
# add more files/functions like in below:
|
||||||
|
# - "--file"
|
||||||
|
# - "host/api/src/esp_extra_weak.c"
|
||||||
|
# - "--functions"
|
||||||
|
# - "esp_extra_foo,esp_extra_bar"
|
||||||
|
files: ^host/api/src/.*\.c$
|
||||||
|
pass_filenames: false
|
||||||
|
- repo: https://github.com/espressif/check-copyright/
|
||||||
|
rev: v1.1.1
|
||||||
|
hooks:
|
||||||
|
- id: check-copyright
|
||||||
|
args: ['--config', 'tools/check_copyright_config.yaml']
|
||||||
|
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: v2.4.1
|
||||||
|
hooks:
|
||||||
|
- id: codespell
|
||||||
|
args: [--config=.codespellrc]
|
||||||
@@ -0,0 +1,816 @@
|
|||||||
|
# Unreleased - Main Branch
|
||||||
|
|
||||||
|
# Releases
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.11}}$$
|
||||||
|
|
||||||
|
- fixed SDIO deinit tearing down the shared SDMMC host (broke a co-existing SD card on the other slot)
|
||||||
|
- fixed public headers failing to build under `-Werror=undef` (e.g. Matter/external host consumers)
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.10}}$$
|
||||||
|
|
||||||
|
- added `esp_wifi_disable_pmf_config()` support (host ↔ co-processor RPC); previously returned `ESP_ERR_NOT_SUPPORTED`
|
||||||
|
- fixed SDIO RX heap corruption on transport deinit and hardened RX buffer allocation
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.9}}$$
|
||||||
|
|
||||||
|
- added gpios for `ESP32_P4X_C5_Function_EV_Board V2.0`
|
||||||
|
- fix build break for IDF v6 when enable power save (API renamed)
|
||||||
|
- update Kconfig to check for config `SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP` introduced in IDF v6
|
||||||
|
- fixed bug causing a crash in SPI-HD interface with IDF v6.1 due to new uninitialised member in `spi_bus_config_t`
|
||||||
|
- reduced default number of buffers for SPI-HD and SPI-FD to resolve memory issues
|
||||||
|
- Zigbee:
|
||||||
|
- added support for Zigbee
|
||||||
|
- added Home Automation thermostat on a Zigbee Coordinator example
|
||||||
|
- added support for SPI-HD 1-bit mode (SPI 3-wire interface)
|
||||||
|
- **NOTE**: SPI-HD 1-bit mode is only supported on ESP-IDF v6.1 and above and requires [git Commit bf10423](https://github.com/espressif/esp-idf/commit/bf10423a5b01888b33ab1f4e45ef5a880eed69e6)
|
||||||
|
- updated `_h_get_semaphore` and `_h_lock_mutex` to use milliseconds instead of seconds as a timeout parameter
|
||||||
|
- added `_h_thread_yield` for use by threads to request a context switch
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.8}}$$
|
||||||
|
|
||||||
|
- SDIO: added `ESP_HOSTED_MEMPOOL_PREFER_SPIRAM` to allocate transport buffers from PSRAM (e.g. ESP32-P4), saving internal RAM; off by default
|
||||||
|
- OS APIs: `_h_get_semaphore` and `_h_lock_mutex` now take timeout in milliseconds (was seconds)
|
||||||
|
- added `_h_thread_yield` for threads to request a context switch
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.7}}$$
|
||||||
|
|
||||||
|
- OpenThread: added OpenThread over dedicated UART support
|
||||||
|
- co-processor is the OpenThead RCP (Radio Co-Processor)
|
||||||
|
- added host examples: `host_openthread_border_router`, `host_openthread_cli`
|
||||||
|
- Common Mempool: fixed build error on ESP-IDF v6.x when using PicolibC with `CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY` disabled
|
||||||
|
- Host: removed Unicode encoded characters in cmake file to prevent Windows build failure
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.6}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- make `TAG` in `mempool.c` static to avoid link-time clash with other components (#187)
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.5}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### External Coexistence: allow with BT on advanced coex chips
|
||||||
|
- Aligned Kconfig with IDF change that relaxes `ESP_COEX_EXTERNAL_COEXIST_ENABLE` dependency
|
||||||
|
- On chips with `SOC_EXTERNAL_COEX_ADVANCE`, external coexistence now works alongside BT controller
|
||||||
|
- Updated compile-time checks in `slave_ext_coex.h` to match (includes `soc/soc_caps.h`)
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fixed CI to allow building ESP32 co-processor with ESP-IDF v5.5 for SPI-FD and UART transports: was running out of IRAM space
|
||||||
|
- fixed CI build failure when building co-processor with ESP-IDF release/v5.3
|
||||||
|
- added more ESP-IDF releases to CI for testing
|
||||||
|
|
||||||
|
### OTA: fix image size calculation for partition-based OTA
|
||||||
|
- Add 16-byte alignment padding before SHA256 hash in image size parser
|
||||||
|
- Previously sent 15 fewer bytes than actual image, causing hash mismatch
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.4}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fix build break on co-processor if using SPI-HD interface with 2 data lines
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Custom RPC callbacks: support user context pointer
|
||||||
|
|
||||||
|
- Allows passing per-callback context without global state
|
||||||
|
- User pointer is returned as-is on every invocation
|
||||||
|
|
||||||
|
##### API Changes
|
||||||
|
|
||||||
|
- `esp_hosted_register_custom_callback`
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Old
|
||||||
|
esp_err_t esp_hosted_register_custom_callback(
|
||||||
|
uint32_t msg_id,
|
||||||
|
void (*callback)(uint32_t msg_id, const uint8_t *data, size_t data_len));
|
||||||
|
|
||||||
|
// New
|
||||||
|
esp_err_t esp_hosted_register_custom_callback(
|
||||||
|
uint32_t msg_id,
|
||||||
|
void (*callback)(uint32_t msg_id, const uint8_t *data, size_t data_len, void *user),
|
||||||
|
void *user);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Others
|
||||||
|
|
||||||
|
- used common mempool code for both Host and Co-processor
|
||||||
|
- made ESP-Hosted mempool code private to fix build break
|
||||||
|
- added parameter checking for RPC calls
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Host: added NULL or validation checks for exposed user APIs
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed `esp_wifi_scan_get_ap_records` to set the actual AP number this API returns
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.2}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Add slave target strings to `Kconfig` (required by Arduino build)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add api to get the co-processor name and chip id to identify the co-processor
|
||||||
|
- API Added
|
||||||
|
- `esp_hosted_get_cp_info`
|
||||||
|
- Updated `examples/host_bt_controller_mac_addr` to request this information
|
||||||
|
- Extended RPC for GetCoprocessorFwVersion to include the co-processor name and chip id
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.12.1}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Allow disabling Wi-Fi and/or Bluetooth
|
||||||
|
|
||||||
|
- Added Co-processor option to disable Wi-Fi support (for Bluetooth-only support)
|
||||||
|
- Re-organised co-processor code: moved Wi-Fi, Wi-Fi Enterprise and Network Split code into individual files
|
||||||
|
- Added initial support for ESP32-H4 as co-processor
|
||||||
|
- only works with UART interface as ESP-Hosted Transport. SPI to be enabled later.
|
||||||
|
- Bluetooth not yet enabled in ESP-IDF
|
||||||
|
|
||||||
|
### Co-processor: External Coexistence
|
||||||
|
|
||||||
|
- Add support to manage co-processor external Wi-Fi coexistence from the host.
|
||||||
|
- APIs Added
|
||||||
|
- `esp_hosted_cp_ext_coex_set_work_mode`
|
||||||
|
- `esp_hosted_cp_ext_coex_set_gpio_pin`
|
||||||
|
- `esp_hosted_cp_ext_coex_set_grant_delay`
|
||||||
|
- `esp_hosted_cp_ext_coex_set_validate_high`
|
||||||
|
- `esp_hosted_cp_ext_coex_disable`
|
||||||
|
- Host Example Added
|
||||||
|
- examples/host_manage_copro_ext_coex
|
||||||
|
- Documentation
|
||||||
|
- examples/host_manage_copro_ext_coex/README.md
|
||||||
|
- Config
|
||||||
|
- Host
|
||||||
|
- ESP_HOSTED_CP_EXT_COEX
|
||||||
|
- ESP_HOSTED_CP_EXT_COEX_ADVANCE
|
||||||
|
- Slave
|
||||||
|
- ESP_HOSTED_CP_EXT_COEX
|
||||||
|
|
||||||
|
### Other Features
|
||||||
|
|
||||||
|
- Added support for Bluetooth-only Co-processors (like ESP32-H2)
|
||||||
|
- Allow ESP-Hosted component to be manually disabled through idf menuconfig
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- ESP Slave FW validation fails because OTA image validation depends on non-existent IDF 6.0+ APIs (GitHub ##165)
|
||||||
|
|
||||||
|
# $${\color{cyan} \text{2.12.0}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Checked incoming image validity during OTA update
|
||||||
|
- done for ESP-IDF v6.1.0 or greater
|
||||||
|
- Wi-Fi APIs
|
||||||
|
- `esp_wifi_set_scan_parameters()`
|
||||||
|
- `esp_wifi_get_scan_parameters()`
|
||||||
|
- Allow slave OTA only if correct SPI Flash Mode
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Assert if slave uses SDIO streaming and host as SDIO packet mode
|
||||||
|
- Guard `esp_hosted_coprocessor.h`, `host_power_save.h`, `interface.h` for cplusplus inclusion
|
||||||
|
- Replace assert with graceful error on mempool alloc failure
|
||||||
|
- Building with and without bt enabled
|
||||||
|
- Disable auto connect upon sta mode started
|
||||||
|
- Add `esp_eap_client_set_eap_methods()` as `weak` in `esp_wifi_weak.c`
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
- Added ESP32-P4-Eye board GPIOs at slave and host Kconfig
|
||||||
|
- Fix host wakeup GPIO config
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.7}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added Co-processor Memory Monitor: sets up a heap memory monitor on the co-processor that periodically checks the amount of heap memory remaining. Co-processor sends memory info events to the host at periodic intervals or when heap memory falls below memory thresholds set by the host.
|
||||||
|
- Added `examples/host_hosted_cp_meminfo` as an example:
|
||||||
|
- make a one time request of heap memory
|
||||||
|
- request periodic memory reports
|
||||||
|
- get a report only when heap memory falls below a threshold
|
||||||
|
|
||||||
|
## API Added
|
||||||
|
|
||||||
|
- `esp_hosted_set_mem_monitor`
|
||||||
|
|
||||||
|
## Event Added
|
||||||
|
|
||||||
|
- `ESP_HOSTED_EVENT_MEM_MONITOR`
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Added performance with ESP32-C3 as co-processor, using SPI-FD interface, to Performance document.
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.6}}$$
|
||||||
|
|
||||||
|
- Fix a build break on ESP-IDF master branch
|
||||||
|
- Add `ESP_HOSTED_WIFI_AUTO_CONNECT_ON_STA_START` to control whether WiFi station auto-connects on STA start on both host and slave sides. This allows disabling auto-connect to align behavior with standard ESP-IDF examples and avoids unintended connection attempts during initialization.
|
||||||
|
- Made FreeRTOS runtime stats logging optional
|
||||||
|
- Added option to allow slave to reuse application-created STA netif handle instead of creating its own handle
|
||||||
|
- Added option to disable sharing Bluetooth with Host, for cases where BT is only required on the co-processor
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.5}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Renamed `H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT` to `H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS` to clarify units are in milliseconds.
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.4}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ESP32-P4 C61 Core board support - Improvise
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- TCP iPerf stability with documented performance optimizations
|
||||||
|
|
||||||
|
## Tested
|
||||||
|
|
||||||
|
- Host power save and wake-up functionality
|
||||||
|
- Wake-up GPIOs:
|
||||||
|
- P4 Core Board – C61: IO04
|
||||||
|
- P4 Core Board – P4: IO06
|
||||||
|
- GPIOs disabled by default (`-1`) due to no physical connection; verified via jumper wiring and solder
|
||||||
|
- Network split scenarios
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- made UART Hosted interface more stable:
|
||||||
|
- flush the input after reset. Rx line may toggle while resetting the co-processor, causing Host UART to store invalid data.
|
||||||
|
- check that offset in received payload header is valid: discard packet for invalid offsets.
|
||||||
|
- check flags in received payload only after the payload is considered valid
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.2}}$$
|
||||||
|
|
||||||
|
Minor fix: On Timeout/Failure, Print RPC req str instead of RPCId
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.11.1}}$$
|
||||||
|
|
||||||
|
Minor fixes: const qualifier violations while building
|
||||||
|
|
||||||
|
# $${\color{cyan} \text{2.11.0}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- remove double freeing of buffer if `chan_arr[buf_handle->if_type]->rx()` fails. Underlying rx function will free the memory
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This version of ESP-Hosted onwards must be used with wifi-remote component v1.3.1 or greater. See the [Migration Guide](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/migration_guide.md) for more information.
|
||||||
|
|
||||||
|
# $${\color{cyan} \text{2.10.0}}$$
|
||||||
|
|
||||||
|
## Features: GPIO Expander
|
||||||
|
|
||||||
|
- **GPIO Expander**: Added feature to allow the host to control the GPIOs of the slave co-processor over the existing transport link. See [GPIO Expander Guide](./docs/gpio_expander.md).
|
||||||
|
- **GPIO Expander Example**: Added a new example `examples/host_gpio_expander` to demonstrate the usage of the GPIO expander feature.
|
||||||
|
|
||||||
|
## APIs Added
|
||||||
|
|
||||||
|
- `esp_hosted_cp_gpio_config`
|
||||||
|
- `esp_hosted_cp_gpio_reset_pin`
|
||||||
|
- `esp_hosted_cp_gpio_set_level`
|
||||||
|
- `esp_hosted_cp_gpio_get_level`
|
||||||
|
- `esp_hosted_cp_gpio_set_direction`
|
||||||
|
- `esp_hosted_cp_gpio_input_enable`
|
||||||
|
- `esp_hosted_cp_gpio_set_pull_mode`
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.7}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add example, [host_shuts_down_slave_to_power_save](https://components.espressif.com/components/espressif/esp_hosted/examples/host_shuts_down_slave_to_power_save)
|
||||||
|
- Use `EN` pin on coprocessor to power off/on
|
||||||
|
- Power down coprocessor when not in use
|
||||||
|
- Power on coprocessor when required
|
||||||
|
- Connect Wi-Fi on coprocessor wake up
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fix the memory leaks in hosted deinit -> init path
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.5 - 2.9.6}}$$
|
||||||
|
|
||||||
|
Using shorter, more manageable names for esp hosted events
|
||||||
|
Before adoption, concise the event names from full string COPROCESSOR to just CP in event names
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.4}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- enabled ESP-Hosted events. Host can register an event handler to receive these events from co-processor:
|
||||||
|
- INIT event, indicating the co-processor has started
|
||||||
|
- HEARTBEAT event, when enabled by the host
|
||||||
|
- TRANSPORT_FAILURE event, when ESP-Hosted encounters a transport failure
|
||||||
|
- host can use these events to determine if the co-processor rebooted (unexpected INIT event) or hanged (missing HEARTBEAT)
|
||||||
|
- added `examples/host_hosted_events` as an example to show how the host can use either event to reinitialise a Station connection to an AP
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fixed ESP-Hosted and SDIO issues that prevent transport reinitialisation
|
||||||
|
- fixed files to skip when running codespell during pre-commit
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- removed setting `scan_method` and `sort_method` in co-processor when station is connecting. Use the values sent by the Host in the Wi-Fi config.
|
||||||
|
- fixed support for ESP32-S2 as a co-processor
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.2}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Slave OTA Example
|
||||||
|
- Add version-aware OTA activation
|
||||||
|
- Conditionally call esp_slave_ota_activate() only for slave FW >= v2.6.0
|
||||||
|
- Improved Slave OTA Documentation
|
||||||
|
- Comprehensive code comments explaining OTA APIs and version checks
|
||||||
|
- Mermaid sequence diagram showing complete OTA verification flow
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.1}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Correct esptool command usage (`write_flash` instead of invalid `write-flash`)
|
||||||
|
- Update Wi-Fi bandwidth enums for newer ESP-IDF compatibility
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
|
||||||
|
- Better validation and user-readable error messages for slave OTA
|
||||||
|
- Detect empty or uninitialized LittleFS and partition OTA sources
|
||||||
|
- Clear guidance when invalid or missing slave firmware binaries are detected
|
||||||
|
|
||||||
|
# $${\color{green} \text{2.9.0}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fix slave OTA failures on back-to-back updates by removing the hard dependency on `CONFIG_ESPTOOLPY_FLASHMODE_QIO`.
|
||||||
|
- Previously, mandating QIO flash mode caused consecutive OTA operations to fail; this is now resolved by removing the forced flash mode setting.
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.5}}$$
|
||||||
|
|
||||||
|
## Features: Light Sleep Integration & Documentation
|
||||||
|
|
||||||
|
- **Light Sleep Documentation**: Added comprehensive [Light Sleep Integration Guide](https://www.google.com/search?q=https://github.com/espressif/esp-hosted-mcu/blob/main/docs/slave_light_sleep.md) detailing the handshake between host power states and slave light sleep.
|
||||||
|
- **Smart Wakeup Demo**: Added a new demo showcasing the slave waking the host MCU using specific network triggers (UDP packets).
|
||||||
|
- Example: `examples/host_network_split__power_save/host_wakeup_demo_using_udp_packet`
|
||||||
|
|
||||||
|
## Bug Fixes & Stability
|
||||||
|
|
||||||
|
- **Memory Leak Fixes**:
|
||||||
|
- Resolved memory leaks in the SDIO driver during unload/deinit by ensuring proper buffer cleanup and `sdio_slave_send_get_finished` usage.
|
||||||
|
- Fixed memory leaks in `esp_hosted_cli` by adding proper deregistration APIs for Hosted-specific commands.
|
||||||
|
- Cleanly handled timer memory removal in the Host Power Save component.
|
||||||
|
- **Concurrency & Race Conditions**:
|
||||||
|
- Added semaphore protection (mutex) in `host_power_save.c` to prevent race conditions when multiple threads attempt to wake the host simultaneously.
|
||||||
|
- **Timing & Reset Improvements**:
|
||||||
|
- Adjusted task delays in the host wakeup sequence to prevent the host from receiving incorrect or premature reset signals during the wake-up transition.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.4}}$$
|
||||||
|
|
||||||
|
## Features: Slave Auto Light sleep
|
||||||
|
|
||||||
|
- Auto Invoked when host triggers deep sleep
|
||||||
|
- Example implementation in example_light_sleep.c
|
||||||
|
|
||||||
|
# Known issue
|
||||||
|
|
||||||
|
There is memory leak when sdio driver unload is selected - working on the fix
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.3}}$$
|
||||||
|
|
||||||
|
Add up mutex protection for callback array for Peer Data Transfer
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.2}}$$
|
||||||
|
|
||||||
|
## Amend Peer Data Transfer example with custom msg id
|
||||||
|
|
||||||
|
Amend [Peer Data Transfer Example](https://components.espressif.com/components/espressif/esp_hosted/examples/host_peer_data_transfer):
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- User can register callback-based dispatch for their own msg ids, both at host and slave
|
||||||
|
- Configurable handler slots via Kconfig (default: 3)
|
||||||
|
|
||||||
|
API:
|
||||||
|
- esp_err_t esp_hosted_send_custom_data(uint32_t msg_id, const uint8_t *data, size_t data_len)
|
||||||
|
- esp_err_t esp_hosted_register_cu
|
||||||
|
stom_callback(uint32_t msg_id, void (*callback)(uint32_t msg_id, const uint8_t *data, size_t data_len));
|
||||||
|
|
||||||
|
Example (examples/host_peer_data_transfer):
|
||||||
|
- Uses animal sound theme (CAT→MEOW, DOG→WOOF, HUMAN→HELLO)
|
||||||
|
- Host sends CAT_MSG_ID, with byte stream. Slave sends back same stream with MEOW_MGD_ID and so on.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
- Host: CONFIG_ESP_HOSTED_MAX_CUSTOM_MSG_HANDLERS (Kconfig)
|
||||||
|
- Slave: CONFIG_ESP_HOSTED_MAX_CUSTOM_MSG_HANDLERS (Kconfig.projbuild)
|
||||||
|
- Ported as H_MAX_CUSTOM_MSG_HANDLERS on host side
|
||||||
|
|
||||||
|
## Allow to disable app_main() from slave
|
||||||
|
|
||||||
|
**Kconfig : `CONFIG_ESP_HOSTED_COPROCESSOR_APP_MAIN`** at coprocessor menuconfig
|
||||||
|
- **Default**: Enabled (for slave example from registry)
|
||||||
|
- **Purpose**: Controls whether ESP-Hosted provides its own `app_main()`
|
||||||
|
- **When to disable**:
|
||||||
|
- Using ESP-Hosted slave code base as a component in your application
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.1}}$$
|
||||||
|
|
||||||
|
## Example: [Peer Data Transfer Example](https://components.espressif.com/components/espressif/esp_hosted/examples/host_peer_data_transfer)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Supports sending and receiving arbitrary (preformatted) user data from/to host and slave
|
||||||
|
- Maximum payload size: 8166 bytes per packet
|
||||||
|
|
||||||
|
## APIs
|
||||||
|
|
||||||
|
- `esp_hosted_send_custom_data(data, length)`: Send raw binary data to coprocessor
|
||||||
|
- `esp_hosted_register_rx_callback_custom_data(callback)`: Register callback for receiving custom data
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.8.0}}$$ - Network Split (Shared IP)
|
||||||
|
|
||||||
|
**Network Split (Shared IP)**
|
||||||
|
|
||||||
|
This major update allows the **Host MCU** and the **ESP Slave** to share a **single IP address** while running independent network stacks. This is ideal for low-power products where the Slave handles background tasks while the Host sleeps.
|
||||||
|
|
||||||
|
- Disabled by default. Enable using `CONFIG_ESP_HOSTED_NETWORK_SPLIT_ENABLED` config
|
||||||
|
- **Documentation**: [Network Split Guide](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/feature_network_split.md).
|
||||||
|
|
||||||
|
## Example: [Network Split with Host Power Save Example](https://components.espressif.com/components/espressif/esp_hosted/examples/host_network_split__power_save)
|
||||||
|
|
||||||
|
## **Key Additions**
|
||||||
|
|
||||||
|
- Smart Traffic Routing: `nw_split_router.c` automatically directs traffic through function, `nw_split_filter_and_route_packet()`
|
||||||
|
- **Port-based (TCP/UDP)**: Uses `CONFIG_LWIP_TCP_LOCAL_PORT_RANGE` and `CONFIG_LWIP_UDP_LOCAL_PORT_RANGE` to decide if the Host or Slave handles a packet.
|
||||||
|
- **Reserved Ports**: Mandate packets on specific ports (e.g., 80, 443) to the Host via `CONFIG_ESP_HOSTED_HOST_RESERVED_PORTS_CONFIGURED`.
|
||||||
|
- **Non TCP/UDP**: Built-in handling for `ARP`, `ICMP`, and `DHCP` on coprocessor (configurable) to offload host for other priority work or deep sleep
|
||||||
|
- iperf Performance
|
||||||
|
- Demo of sharing same port: Port `5001` is shared smartly, allowing performance testing on either stack (at a time) without reconfiguring.
|
||||||
|
- Low-Power Support
|
||||||
|
- (Optionally) Deeply integrated with [Host Power Save](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/feature_host_power_save.md)
|
||||||
|
- Smart Wakeup demo
|
||||||
|
- The Slave can "wake up" the Host when it receives specific traffic or an MQTT message containing the `"wakeup-host"` string.
|
||||||
|
- **Collision Prevention**
|
||||||
|
- Added `esp_hosted_lwip_src_port_hook.h` to ensure the Host and Slave never try to use the same source port.
|
||||||
|
- **Supported Targets**
|
||||||
|
- **Slaves**: ESP32-C5, C6, S2, S3.
|
||||||
|
- **Hosts**: ESP32-P4, H2, and non ESP MCUs.
|
||||||
|
|
||||||
|
ESP Component Registry Release: [2.8.0](https://components.espressif.com/components/espressif/esp_hosted/versions/2.8.0)
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.7.4}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fixed co-processor to properly allow wifi init and deinit
|
||||||
|
- fixed registration of event handlers in co-processor
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.7.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fixed RPC Response for OTA commands to return errors in responses correctly
|
||||||
|
- fixed double free bug in host OTA example
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.7.2}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Stable workaround for ota writes to slave
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.7.1}}$$
|
||||||
|
|
||||||
|
- Add support for more PCBs:
|
||||||
|
- ESP32-P4 Core Board - with on-board C5
|
||||||
|
- ESP32-P4 Core Board - with on-board C6
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.7.0}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
Restructured the ESP-Hosted-MCU commits
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.8}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Clean up ESP-Hosted prints at host
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.7}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added Hosted API call to get co-processor Application Descriptor
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.6}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed sta connection to remove extra disconnected event if incoming station config is different from current station config
|
||||||
|
- IRAM size limitation when using UART transport only applies to ESP32, not to all SOCs.
|
||||||
|
- workaround a bug in `esp_wifi_get_protocol()` that can cause memory corruption. See this [ESP-IDF Issue](https://github.com/espressif/esp-idf/issues/17502).
|
||||||
|
- updated CI pipelines to build mqtt/tcp example from Registry Component on master branch
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.5}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add example showing concurrent use of a SD Card and ESP-Hosted.
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.4}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fix the `esp_wifi_deinit()` call from host
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Increase timing used to reset co-processors to work with a slower FreeRTOS clock tick
|
||||||
|
- Updated documentation on performance optimization
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.2}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- fixed bug in enabling `esp_eap_client_set_eap_methods` on co-processor based on ESP-IDF version
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.1}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
Minor fixes in Slave OTA example
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.6.0}}$$
|
||||||
|
|
||||||
|
- Added public OTA APIs for slave firmware updates
|
||||||
|
- Added host-triggered slave OTA example with support for HTTP, partition, and filesystem sources
|
||||||
|
- Support for LittleFS filesystem-based OTA updates
|
||||||
|
- Migration guide updated for 2.6.0
|
||||||
|
|
||||||
|
## APIs added
|
||||||
|
|
||||||
|
- `esp_hosted_ota_begin`
|
||||||
|
- `esp_hosted_ota_write`
|
||||||
|
- `esp_hosted_ota_end`
|
||||||
|
- `esp_hosted_ota_activate`
|
||||||
|
|
||||||
|
## APIs deprecated
|
||||||
|
|
||||||
|
- `esp_hosted_slave_ota` - Use the new [Host Performs Slave OTA Example](examples/host_performs_slave_ota/README.md) instead for more flexible OTA implementations with comprehensive documentation and multiple deployment methods
|
||||||
|
|
||||||
|
## Examples added
|
||||||
|
|
||||||
|
- `host_performs_slave_ota` - Host-triggered slave OTA example supporting HTTP URLs, partition sources and LittleFS filesystem sources
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.12}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add SPI (full and half duplex) and UART support for ESP32-C61
|
||||||
|
- Updated documentation on applying optimised Wi-Fi settings to sdkconfigs
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed build issues when raw throughput testing is enabled
|
||||||
|
- Fixed bug in co-processor causing SDIO to operate only in packet mode
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.11}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixes to use compatible version of `idf-build-apps` and constraints during CI pipeline builds
|
||||||
|
- Renamed CI pipelines to "sanity" and "regression"
|
||||||
|
- Prefix jobs with `sanity_` or `regression_` to make their names unique
|
||||||
|
- Enabled building of ESP-Hosted examples in regression pipeline
|
||||||
|
- Various bug fixes found in the process of fixing the CI pipelines
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.10}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Version, 2.5.8 - 2.5.10:
|
||||||
|
- Add staging branch workflow for safer component releases
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.7}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed build break when CLI Commands are enabled on coprocessor
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.6}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Updated co-processor and some example `idf_component.yml` files to set component dependencies based on the ESP-IDF version in use
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.5}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed build errors when using latest version of ESP-IDF
|
||||||
|
- Updated Wi-Fi Easy Connect (DPP) code to match current ESP-IDF master
|
||||||
|
- Adjusted CI pipeline
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.4}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added building with ESP-IDF v5.3 in CI
|
||||||
|
- Added building ESP-Hosted examples in CI
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed building with ESP32-H2 as host in CI (was skipping build)
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fix the ESP-IDF CI
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.2}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add support to get and set the BT Controller Mac Address
|
||||||
|
- To support set BT Controller Mac Address, BT Controller is now disabled by default on the co-processor, and host must enable the BT Controller. See [Initializing the Bluetooth Controller](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/bluetooth_design.md#31-initializing-the-bluetooth-controller) for details
|
||||||
|
- Updated all ESP-Hosted BT related examples to account for new BT Controller behaviour
|
||||||
|
|
||||||
|
## APIs added
|
||||||
|
|
||||||
|
- `esp_hosted_bt_controller_init`
|
||||||
|
- `esp_hosted_bt_controller_deinit`
|
||||||
|
- `esp_hosted_bt_controller_enable`
|
||||||
|
- `esp_hosted_bt_controller_disable`
|
||||||
|
- `esp_hosted_iface_mac_addr_set`
|
||||||
|
- `esp_hosted_iface_mac_addr_get`
|
||||||
|
- `esp_hosted_iface_mac_addr_len_get`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.1}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Added dependency on `esp_driver_gpio`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.5.0}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Remove dependency on deprecated `driver` component and added necessary dependencies instead
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.4.3}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add support for Wi-Fi Easy Connect (DPP)
|
||||||
|
- [Espressif documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_dpp.html) on Wi-Fi Easy Connect (DPP)
|
||||||
|
- [ESP-Hosted Enrollee Example](https://github.com/espressif/esp-hosted-mcu/tree/main/examples/host_wifi_easy_connect_dpp_enrollee) using DPP to securely onboard a ESP32P4 with C6 board to a network with the help of a QR code and an Android 10+ device
|
||||||
|
|
||||||
|
## APIs added
|
||||||
|
|
||||||
|
- `esp_supp_dpp_init`
|
||||||
|
- `esp_supp_dpp_deinit`
|
||||||
|
- `esp_supp_dpp_bootstrap_gen`
|
||||||
|
- `esp_supp_dpp_start_listen`
|
||||||
|
- `esp_supp_dpp_stop_listen`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.4.2}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fix ignored lwip hook header in slave example
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.4.1}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Reduced ESP32 bootloader size
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.4.0}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added support for Wi-Fi Enterprise
|
||||||
|
|
||||||
|
## APIs added
|
||||||
|
|
||||||
|
- `esp_wifi_sta_enterprise_enable`
|
||||||
|
- `esp_wifi_sta_enterprise_disable`
|
||||||
|
- `esp_eap_client_set_identity`
|
||||||
|
- `esp_eap_client_clear_identity`
|
||||||
|
- `esp_eap_client_set_username`
|
||||||
|
- `esp_eap_client_clear_username`
|
||||||
|
- `esp_eap_client_set_password`
|
||||||
|
- `esp_eap_client_clear_password`
|
||||||
|
- `esp_eap_client_set_new_password`
|
||||||
|
- `esp_eap_client_clear_new_password`
|
||||||
|
- `esp_eap_client_set_ca_cert`
|
||||||
|
- `esp_eap_client_clear_ca_cert`
|
||||||
|
- `esp_eap_client_set_certificate_and_key`
|
||||||
|
- `esp_eap_client_clear_certificate_and_key`
|
||||||
|
- `esp_eap_client_set_disable_time_check`
|
||||||
|
- `esp_eap_client_get_disable_time_check`
|
||||||
|
- `esp_eap_client_set_ttls_phase2_method`
|
||||||
|
- `esp_eap_client_set_suiteb_192bit_certification`
|
||||||
|
- `esp_eap_client_set_pac_file`
|
||||||
|
- `esp_eap_client_set_fast_params`
|
||||||
|
- `esp_eap_client_use_default_cert_bundle`
|
||||||
|
- `esp_wifi_set_okc_support`
|
||||||
|
- `esp_eap_client_set_domain_name`
|
||||||
|
- `esp_eap_client_set_eap_methods`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.3.3}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added SDIO support for ESP32-C61
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.3.2}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add host example to showcase transport config before `esp_hosted_init()`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.3.1}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed a build break caused by refactoring
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.3.0}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Refactored common and port specific code
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.2.4}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed SPI Full Duplex startup sequence
|
||||||
|
- Fixed incorrect Handshake GPIO assignment for C5 on Module
|
||||||
|
- Added valid CPU frequencies in ITWT Example for H2
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.2.3}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed itwt build break for IDF v5.3.1
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.2.2}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added support for Wi-Fi Power Save and ITWT
|
||||||
|
- Added ITWT example
|
||||||
|
- Updated copyright check to allow Unlicensed or CC0-1.0 files
|
||||||
|
|
||||||
|
## APIs added
|
||||||
|
|
||||||
|
- `esp_wifi_set_inactive_time()`
|
||||||
|
- `esp_wifi_get_inactive_time()`
|
||||||
|
- `esp_wifi_sta_twt_config()`
|
||||||
|
- `esp_wifi_sta_itwt_setup()`
|
||||||
|
- `esp_wifi_sta_itwt_teardown()`
|
||||||
|
- `esp_wifi_sta_itwt_suspend()`
|
||||||
|
- `esp_wifi_sta_itwt_get_flow_id_status()`
|
||||||
|
- `esp_wifi_sta_itwt_send_probe_req()`
|
||||||
|
- `esp_wifi_sta_itwt_set_target_wake_time_offset()`
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.2.1}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Allow external code to override Hosted BT Tx function by making it a `weak` reference
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.2.0}}$$
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Add support for fragmentation of packets from sdio host to slave
|
||||||
|
|
||||||
|
# $${\color{red} \text{2.1.11}}$$
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed SoftAP operation issues
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,184 @@
|
|||||||
|
if(CONFIG_ESP_HOSTED_ENABLED)
|
||||||
|
message(STATUS "Using Hosted Wi-Fi")
|
||||||
|
set(FG_root_dir ".")
|
||||||
|
set(host_dir "${FG_root_dir}/host")
|
||||||
|
|
||||||
|
set(srcs
|
||||||
|
"${host_dir}/api/src/esp_wifi_weak.c"
|
||||||
|
"${host_dir}/api/src/esp_hosted_api.c"
|
||||||
|
"${host_dir}/api/src/esp_hosted_transport_config.c"
|
||||||
|
"${host_dir}/api/src/esp_hosted_ota_api.c"
|
||||||
|
"${host_dir}/drivers/transport/transport_drv.c"
|
||||||
|
"${host_dir}/drivers/transport/transport_util.c"
|
||||||
|
"${host_dir}/drivers/serial/serial_ll_if.c"
|
||||||
|
"${host_dir}/utils/stats.c"
|
||||||
|
"${host_dir}/drivers/serial/serial_drv.c")
|
||||||
|
|
||||||
|
# only these directories are public. Others are private
|
||||||
|
set(pub_include
|
||||||
|
"${host_dir}"
|
||||||
|
"${host_dir}/api/include")
|
||||||
|
|
||||||
|
set(priv_include
|
||||||
|
"${host_dir}/drivers/transport"
|
||||||
|
"${host_dir}/drivers/transport/spi"
|
||||||
|
"${host_dir}/drivers/transport/sdio"
|
||||||
|
"${host_dir}/drivers/serial"
|
||||||
|
"${host_dir}/utils"
|
||||||
|
"${host_dir}/api/priv")
|
||||||
|
|
||||||
|
# rpc files - wrap -> slaveif -> core
|
||||||
|
set(rpc_dir "${host_dir}/drivers/rpc")
|
||||||
|
set(rpc_core_dir "${rpc_dir}/core")
|
||||||
|
set(rpc_slaveif_dir "${rpc_dir}/slaveif")
|
||||||
|
set(rpc_wrap_dir "${rpc_dir}/wrap")
|
||||||
|
|
||||||
|
list(APPEND srcs
|
||||||
|
"${rpc_core_dir}/rpc_core.c"
|
||||||
|
"${rpc_core_dir}/rpc_req.c"
|
||||||
|
"${rpc_core_dir}/rpc_rsp.c"
|
||||||
|
"${rpc_core_dir}/rpc_evt.c"
|
||||||
|
"${rpc_core_dir}/rpc_utils.c"
|
||||||
|
"${rpc_slaveif_dir}/rpc_slave_if.c"
|
||||||
|
"${rpc_wrap_dir}/rpc_wrap.c")
|
||||||
|
|
||||||
|
list(APPEND priv_include
|
||||||
|
"${rpc_core_dir}"
|
||||||
|
"${rpc_slaveif_dir}"
|
||||||
|
"${rpc_wrap_dir}")
|
||||||
|
|
||||||
|
# virtual serial
|
||||||
|
set(virt_serial_dir "${host_dir}/drivers/virtual_serial_if")
|
||||||
|
list(APPEND srcs "${virt_serial_dir}/serial_if.c")
|
||||||
|
list(APPEND priv_include "${virt_serial_dir}")
|
||||||
|
|
||||||
|
# slave and host common files
|
||||||
|
set(common_dir "${FG_root_dir}/common")
|
||||||
|
|
||||||
|
list(APPEND srcs
|
||||||
|
"${common_dir}/protobuf-c/protobuf-c/protobuf-c.c"
|
||||||
|
"${common_dir}/proto/esp_hosted_rpc.pb-c.c" )
|
||||||
|
|
||||||
|
list(APPEND priv_include
|
||||||
|
"${common_dir}"
|
||||||
|
"${common_dir}/log"
|
||||||
|
"${common_dir}/rpc"
|
||||||
|
"${common_dir}/transport"
|
||||||
|
"${common_dir}/protobuf-c"
|
||||||
|
"${common_dir}/proto" )
|
||||||
|
|
||||||
|
# mempool
|
||||||
|
if (CONFIG_ESP_HOSTED_USE_MEMPOOL)
|
||||||
|
list(APPEND srcs "${common_dir}/mempool/mempool_ll.c"
|
||||||
|
"${common_dir}/mempool/mempool.c")
|
||||||
|
endif()
|
||||||
|
list(APPEND priv_include "${common_dir}/mempool/include" )
|
||||||
|
|
||||||
|
# cli
|
||||||
|
list(APPEND srcs "${common_dir}/utils/esp_hosted_cli.c")
|
||||||
|
list(APPEND priv_include "${common_dir}/utils")
|
||||||
|
|
||||||
|
# bt (NimBLE)
|
||||||
|
### TODO config for HCI over UART
|
||||||
|
list(APPEND priv_include "${host_dir}/drivers/bt")
|
||||||
|
|
||||||
|
if(CONFIG_ESP_HOSTED_NIMBLE_HCI_VHCI OR CONFIG_ESP_HOSTED_BLUEDROID_HCI_VHCI)
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/bt/vhci_drv.c")
|
||||||
|
else()
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/bt/hci_stub_drv.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# power save
|
||||||
|
list(APPEND priv_include "${host_dir}/drivers/power_save")
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/power_save/power_save_drv.c")
|
||||||
|
|
||||||
|
# transport files
|
||||||
|
if(CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/transport/sdio/sdio_drv.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_SPI_HD_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/transport/spi_hd/spi_hd_drv.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_SPI_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/transport/spi/spi_drv.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_UART_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/drivers/transport/uart/uart_drv.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# port files
|
||||||
|
list(APPEND priv_include "${host_dir}/port/esp/freertos/include")
|
||||||
|
|
||||||
|
list(APPEND srcs
|
||||||
|
"${host_dir}/port/esp/freertos/src/port_esp_hosted_host_init.c"
|
||||||
|
"${host_dir}/port/esp/freertos/src/port_esp_hosted_host_os.c"
|
||||||
|
#"${host_dir}/port/esp/freertos/src/port_esp_hosted_host_ota.c"
|
||||||
|
"${host_dir}/port/esp/freertos/src/port_esp_hosted_host_transport_defaults.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/port/esp/freertos/src/port_esp_hosted_host_sdio.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_SPI_HD_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/port/esp/freertos/src/port_esp_hosted_host_spi_hd.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_SPI_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/port/esp/freertos/src/port_esp_hosted_host_spi.c")
|
||||||
|
elseif(CONFIG_ESP_HOSTED_UART_HOST_INTERFACE)
|
||||||
|
list(APPEND srcs "${host_dir}/port/esp/freertos/src/port_esp_hosted_host_uart.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# OpenThread utility functions
|
||||||
|
if(CONFIG_ESP_HOSTED_HOST_OT_ENABLE)
|
||||||
|
list(APPEND srcs "${host_dir}/port/esp/freertos/src/port_esp_hosted_host_ot_util.c")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${IDF_PATH}/components/esp_driver_sdio")
|
||||||
|
message(STATUS "Using new driver components (IDF >= 5.0)")
|
||||||
|
list(APPEND driver_requires esp_driver_sdmmc esp_driver_spi esp_driver_uart esp_driver_gpio)
|
||||||
|
else()
|
||||||
|
message(STATUS "Using legacy driver component (IDF <= 4.4)")
|
||||||
|
list(APPEND driver_requires driver)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
### to support ESP-Hosted events, make esp_event a public requirement
|
||||||
|
list(APPEND driver_requires esp_event)
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${srcs}
|
||||||
|
PRIV_REQUIRES soc esp_netif esp_timer driver esp_wifi bt esp_http_client console wpa_supplicant openthread
|
||||||
|
REQUIRES ${driver_requires}
|
||||||
|
INCLUDE_DIRS ${pub_include}
|
||||||
|
PRIV_INCLUDE_DIRS ${priv_include})
|
||||||
|
|
||||||
|
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE TRUE)
|
||||||
|
|
||||||
|
if(DEFINED ENV{ESP_HOSTED_CI_PEDANTIC})
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE
|
||||||
|
-Werror -Werror=deprecated-declarations -Werror=unused-variable
|
||||||
|
-Werror=unused-but-set-variable -Werror=unused-function
|
||||||
|
$<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE)
|
||||||
|
idf_component_optional_requires(PRIVATE sdmmc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Required if using ESP-IDF without commit 6b6065de509b5de39e4655fd425bf96f43b365f7:
|
||||||
|
# fix(driver_spi): fix p4 cache auto writeback during spi(dma) rx
|
||||||
|
# if(CONFIG_IDF_TARGET_ESP32P4 AND (CONFIG_ESP_HOSTED_SPI_HOST_INTERFACE OR CONFIG_ESP_HOSTED_SPI_HD_HOST_INTERFACE))
|
||||||
|
# # used to workaround SPI transfer issue
|
||||||
|
# idf_component_optional_requires(PRIVATE esp_mm)
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(CONFIG_ESP_HOSTED_NETWORK_SPLIT_ENABLED)
|
||||||
|
idf_component_get_property(lwip lwip COMPONENT_LIB)
|
||||||
|
if(TARGET ${lwip})
|
||||||
|
# Use generator expressions to only apply to non-INTERFACE targets
|
||||||
|
get_target_property(lwip_type ${lwip} TYPE)
|
||||||
|
if(NOT lwip_type STREQUAL "INTERFACE_LIBRARY")
|
||||||
|
#target_include_directories(${lwip} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/common")
|
||||||
|
#target_compile_definitions(${lwip} PRIVATE "-DESP_IDF_LWIP_HOOK_FILENAME=\"${CMAKE_CURRENT_SOURCE_DIR}/common/esp_hosted_lwip_src_port_hook.h\"")
|
||||||
|
|
||||||
|
# Some IDF release/v5.4 commits fail to attach hook file for udp.c, so mandate attach for every file in lwip build
|
||||||
|
message(STATUS "********** Configuring LWIP for network split port configs **********")
|
||||||
|
target_compile_options(${lwip} PRIVATE "-include" "${CMAKE_CURRENT_SOURCE_DIR}/common/esp_hosted_lwip_src_port_hook.h")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
# ESP-Hosted-MCU: Espressif SoCs as Communication Co-Processors
|
||||||
|
|
||||||
|
[](https://components.espressif.com/components/espressif/esp_hosted)
|
||||||
|
|
||||||
|
## 1 Introduction
|
||||||
|
|
||||||
|
ESP-Hosted-MCU is an open-source solution that allows you to use Espressif Chipsets and modules as a communication co-processor. This solution provides wireless connectivity (Wi-Fi and Bluetooth) to the host microprocessor or microcontroller, enabling it to communicate with other devices. Additionally, the user has complete control over the co-processor's resources.
|
||||||
|
|
||||||
|
This high-level block diagram shows ESP-Hosted's relationship with the host MCU and slave co-processor.
|
||||||
|
|
||||||
|
<img src="docs/images/ESP-Hosted-FG-MCU_design.svg" alt="ESP-Hosted">
|
||||||
|
|
||||||
|
For detailed design diagrams in Wi-Fi and Bluetooth, refer to the following design documents:
|
||||||
|
|
||||||
|
- [WiFi Design](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/wifi_design.md)
|
||||||
|
- [Bluetooth Design](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/bluetooth_design.md)
|
||||||
|
|
||||||
|
`esp-hosted-mcu` is dedicated for any host as MCU support. If you are interested in Linux as host, please refer to the [`esp-hosted`](https://github.com/espressif/esp-hosted) repository.
|
||||||
|
|
||||||
|
## 2 Architecture
|
||||||
|
|
||||||
|
##### Hosted Co-Processor
|
||||||
|
This is an ESP chip that provides Wi-Fi, Bluetooth, and other capabilities. It is also referred as `hosted-slave` interchangeably.
|
||||||
|
|
||||||
|
##### Host MCU
|
||||||
|
This can be any generic microcontroller (MCU). We demonstrate any ESP as host. Using port layer, any host can act as host MCU.
|
||||||
|
|
||||||
|
##### Communication
|
||||||
|
- Host extends the capabilities of the Hosted co-processor through Remote Procedure Calls (RPCs). The Host MCU sends these RPC commands to the Hosted co-processor using a reliable communication bus, like SPI, SDIO, or UART. The Hosted co-processor then handles the RPC and provides the requested functionality to the Host MCU.
|
||||||
|
- The data (network or Bluetooth) is packaged efficiently at the transport layer to minimize overhead and delays when passing between the Host and co-processor.
|
||||||
|
- This modular design allows any MCU to be used as the Host, and any ESP chip with Wi-Fi and/or Bluetooth to be used as the Hosted co-processor. The RPC calls can also be extended to provide any function required by the Host, as long as the co-processor can support it.
|
||||||
|
- The RPCs implemented are [listed in this document](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/implemented_rpcs.md), including the ESP-Hosted release version that implements the RPCs.
|
||||||
|
|
||||||
|
## 3 Solution Flexibility
|
||||||
|
|
||||||
|
- **Any MCU can be the host**
|
||||||
|
- You can evaluate ESP as an example host and then port ESP-Hosted to your desired MCU.
|
||||||
|
- **Any ESP chip can be the co-processor**
|
||||||
|
- Any Wi-Fi and/or Bluetooth capable ESP chipset can be chosen as co-processor
|
||||||
|
- Choose the co-processor device based on your product requirements. The [ESP Product Selector](https://www.espressif.com/en/products/socs) can help in this.
|
||||||
|
- **Flexible transport layer (SDIO, SPI, UART)**
|
||||||
|
- ESP-Hosted supports various communication interfaces between the host and the co-processor, allowing you to choose the most suitable one for your application.
|
||||||
|
- Any other new transport also could be added to the open source code
|
||||||
|
- **Complete control over co-processor's resources**
|
||||||
|
- The user is not limited to just using the co-processor for wireless connectivity. They have complete control over the co-processor's resources, allowing for a more flexible and powerful system.
|
||||||
|
- **Extensible RPC library**
|
||||||
|
- The Remote Procedure Call (RPC) used by ESP-Hosted can be extended to provide any function required by the Host, as long as the co-processor can support it. Currently, the essential [ESP-IDF](https://github.com/espressif/esp-idf) Wi-Fi functions have been implemented.
|
||||||
|
|
||||||
|
## 3.1 Features Supported by ESP-Hosted
|
||||||
|
|
||||||
|
See the [Features](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/features.md) document for features currently supported by ESP-Hosted.
|
||||||
|
|
||||||
|
## 4 Quick Demo with ESP32-P4-Function-EV-Board
|
||||||
|
|
||||||
|
Impatient to test? We've got you covered!
|
||||||
|
The [ESP32-P4-Function-EV-Board](https://www.espressif.com/en/products/socs/esp32-p4) can be used as a host MCU with an on-board [ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) as co-processor, already connected via SDIO as transport.
|
||||||
|
Prerequisite: You need to have an ESP32-P4-Function-EV-Board`
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> If you have already set up ESP-IDF (version 5.3 or later), you can skip to [5 Source Code and Dependencies](#5-source-code-and-dependencies).
|
||||||
|
|
||||||
|
### 4.1 Set-Up ESP-IDF
|
||||||
|
|
||||||
|
- Windows
|
||||||
|
- Install and setup ESP-IDF on Windows as documented in the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html).
|
||||||
|
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) to move to expected
|
||||||
|
|
||||||
|
- Linux or MacOS
|
||||||
|
- bash
|
||||||
|
```bash
|
||||||
|
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||||
|
```
|
||||||
|
- fish
|
||||||
|
```fish
|
||||||
|
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 Set-Up P4 with C6
|
||||||
|
The host, ESP32-P4, lacks native Wi-Fi/Bluetooth support. Our [Quick Demo](docs/esp32_p4_function_ev_board.md) will help you run iperf over P4--SDIO--C6.
|
||||||
|
|
||||||
|
### 4.3 Don't Have ESP32-P4-Function-EV-Board?
|
||||||
|
|
||||||
|
No worries if you don't have an ESP32-P4. In fact, most users don't. You can choose and use any two ESP chipsets/SoCs/Modules/DevKits. DevKits are convenient to use as they have GPIO headers already in place. From these two ESP chipsets, one would act as host and another as slave/co-processor. However, as these are not connected directly, you would need to manually connect some transport, which is explained later in the section [`Detailed Setup`](#7-detailed-setup).
|
||||||
|
|
||||||
|
## 5 Source Code and Dependencies
|
||||||
|
|
||||||
|
### 5.1 ESP-Hosted-MCU Source Code
|
||||||
|
|
||||||
|
- ESP-Hosted-MCU code can be found at Espressif Registry Component [`esp_hosted` (ESP-Hosted)](https://components.espressif.com/components/espressif/esp_hosted) or GitHub repo at [`esp-hosted-mcu`](https://github.com/espressif/esp-hosted-mcu/)
|
||||||
|
|
||||||
|
- ESP-Hosted repo clone is **not** required if you have ESP as host.
|
||||||
|
- Reason: [ESP component manager](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/tools/idf-component-manager.html) automatically clones esp-hosted component while building.
|
||||||
|
- However, For non-ESP host development, you can clone the repo using command:
|
||||||
|
```bash
|
||||||
|
git clone --recurse-submodules --depth 1 https://github.com/espressif/esp-hosted-mcu.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Dependencies
|
||||||
|
|
||||||
|
ESP-Hosted-MCU Solution is dependent on `ESP-IDF`, `esp_wifi_remote` and `protobuf-c`
|
||||||
|
|
||||||
|
###### ESP-IDF
|
||||||
|
- [`ESP-IDF`](https://github.com/espressif/esp-idf) is the development framework for Espressif SoCs supported on Windows, Linux and macOS
|
||||||
|
- ESP-Hosted-MCU solution is based on ESP-IDF as base software. ESP chipsets as host and slave always tried to design such a way that ESP-IDF components are reused.
|
||||||
|
- Although, We totally understand, host MCUs in case of non-ESP chipset may not desire to be dependent on ESP-IDF. The port layer is written to avoid suc dependencies. Some crucial ESP-IDF components could also be just copy-pasted to fast-track the non-ESP host development.
|
||||||
|
|
||||||
|
###### Wi-Fi Remote
|
||||||
|
- [`esp_wifi_remote`](https://components.espressif.com/components/espressif/esp_wifi_remote) i.e. 'Wi-Fi Remote' is very thin interface made up of ESP-IDF Wi-Fi APIs with empty weak definitions. Real definitions for these APIs are provided by ESP-Hosted-MCU
|
||||||
|
- Wi-Fi Remote Code can be found at either [GitHub Repo](https://github.com/espressif/esp-wifi-remote/) or [Espressif Registry Component](https://components.espressif.com/components/espressif/esp_wifi_remote)
|
||||||
|
|
||||||
|
###### Protobuf
|
||||||
|
- [`protobuf-c`](https://github.com/protobuf-c/protobuf-c) is data serialization framework provided by Google. RPC messages communicated in host and slave are protobuf encoded.
|
||||||
|
- It helps to avoid manual serialization or endian-ness conversion.
|
||||||
|
- Provides Flexibility for users to port the ESP-Hosted-MCU RPC framework in any protobuf supported programming language
|
||||||
|
- Code is checked-out as submodule at `common/protobuf-c`
|
||||||
|
|
||||||
|
##### 5.2.1 How Dependencies Work Together (short explanation)
|
||||||
|
- RPC Request - Response
|
||||||
|
- Wi-Fi Remote is an API layer or interface that provides the standard ESP-IDF Wi-Fi calls to the application (`esp_wifi_init()`, etc.)
|
||||||
|
- Wi-Fi Remote forwards the Wi-Fi calls to ESP-Hosted, as ESP-Hosted 'implements' the APIs provided by Wi-Fi Remote interface.
|
||||||
|
- ESP-Hosted host MCU creates RPC requests which are protobuf encoded and sends over the transport (SPI/SDIO etc) to the slave.
|
||||||
|
- Slave de-serialize the protobuf RPC request and response send back to host over transport, again with protobuf serialised.
|
||||||
|
- Responses received at transport returned to Wi-Fi Remote, which returns the responses to the calling app at host
|
||||||
|
- To the app, it is as if it made a standard ESP-IDF Wi-Fi API call.
|
||||||
|
- RPC Event
|
||||||
|
- Asynchronous Wi-Fi events when subscribed, are sent by slave to host.
|
||||||
|
- These events terminate in standard ESP-IDF event loop on the host
|
||||||
|
- Please note, Only RPC i.e. control packets are serialised. Data Packets are never serialised as they do not need endian conversion.
|
||||||
|
|
||||||
|
## 6 Decide the communication bus in between host and slave
|
||||||
|
|
||||||
|
The communication bus is required to be setup correctly between host and slave.
|
||||||
|
We refer this as `transport medium` or simply `transport`.
|
||||||
|
|
||||||
|
ESP-Hosted-MCU supports SPI/SDIO/UART transports. User can choose which transport to use. Choosing specific transport depends on factors: high performance, easy and quick to test, number of GPIOs used, or simply co-processor preference
|
||||||
|
|
||||||
|
Below is chart for the transport medium comparison.
|
||||||
|
|
||||||
|
Legends:
|
||||||
|
|
||||||
|
- `FD` : Full duplex communication
|
||||||
|
- `HD` : Half duplex communication
|
||||||
|
- `BT` : Bluetooth
|
||||||
|
- `+2` in column `Num of GPIOs`
|
||||||
|
- There are two GPIOs additional applicable for all the transports
|
||||||
|
- (1) Co-Processor reset: Host needs one additional pin to connect to `RST`/`EN` pin of co-processor, to reset on boot-up
|
||||||
|
- (2) Ground: Grounds of both chipsets need to be connected.
|
||||||
|
- If you use jumper cable connections, connect as many grounds as possible in between two boards for better noise cancellation.
|
||||||
|
- `Any_Slave`
|
||||||
|
- Co-processor supported: ESP32, ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-S2, ESP32-S3
|
||||||
|
- Classic ESP32 supports 'Classic BT', 'BLE 4.2' & 'BTDM'
|
||||||
|
- Rest all chipsets support BLE only. BLE version supported is 5.0+. Exact bluetooth versions could be referred from [ESP Product Selector Page](https://products.espressif.com/#/product-selector)
|
||||||
|
- `Dedicated platforms`
|
||||||
|
- Bluetooth uses dedicated platform, UART and Wi-Fi uses any other base transport
|
||||||
|
- In other platforms, Bluetooth and Wi-Fi reuse same platform and hence use less GPIOs and less complicated
|
||||||
|
- This transport combination allows Bluetooth to use dedicated uart transportt with additional 2 or 4 depending on hardware flow control.
|
||||||
|
- TBD : To be determined
|
||||||
|
- iperf : iperf2 with test results in Mbits/sec
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> For the shield box readings marked with (S), full network set up explained in [Shield Box Test Setup](shield-box-test-setup.md)
|
||||||
|
|
||||||
|
**Host can be any ESP chipset or any non-ESP MCU.**
|
||||||
|
|
||||||
|
###### Hosted Transports table
|
||||||
|
| Transport | Type | Num of GPIOs | Setup with | Co-processor supported | Host Tx iperf | Host Rx iperf | Remarks |
|
||||||
|
|:---------------:|:-----:|:------------:|:----------------:|:--------------:|:------------:|:-----------:|:--------------------------:|
|
||||||
|
| Standard SPI | FD | 6 | jumper or PCB | Any_Slave | udp: 24 tcp: 22 | udp: 25 tcp: 22| Simplest solution for quick test |
|
||||||
|
| 1-bit SPI | HD | 4 | jumper or PCB | Any_Slave <sub>[1]</sub> | udp: 22 tcp: 19 <sub>(O)</sub> | udp: 20 tcp: 17 <sub>(O)</sub> | 1-bit, half duplex |
|
||||||
|
| Dual SPI | HD | 5 | jumper or PCB | Any_Slave <sub>[1]</sub> | udp: 32 tcp: 26 <sub>(O)</sub> | udp: 33 tcp: 25 <sub>(O)</sub> | Better throughput, but half duplex |
|
||||||
|
| Quad SPI | HD | 7 | PCB only | Any_Slave <sub>[1]</sub> | udp: 41 tcp: 29 <sub>(O)</sub> | udp: 42 tcp: 28 <sub>(O)</sub> | Due to signal integrity, PCB is mandatory |
|
||||||
|
| SDIO 1-Bit | HD | 4 | jumper or PCB | ESP32, ESP32-C6, ESP32-C5, ESP32-C61 | TBD | TBD | Stepping stone for PCB based SDIO 4-bit |
|
||||||
|
| SDIO 4-Bit | HD | 6 | PCB only | ESP32, ESP32-C6, ESP32-C5, ESP32-C61 <sub>[3]</sub> | udp: 79.5 tcp: 53.4 <sub>(S)</sub> | udp: 68.1 tcp: 44 <sub>(S)</sub> | Highest performance |
|
||||||
|
| Only BT over UART | FD | 2 or 4 | jumper or PCB | Any_Slave | NA | NA | Dedicated Bluetooth over UART pins |
|
||||||
|
| UART | FD | 2 | jumper or PCB | Any_Slave | udp: 0.68 tcp: 0.67 <sub>(O)</sub> | udp: 0.68 tcp: 0.60 <sub>(O)</sub> | UART dedicated for BT & Wi-Fi <sub>[2]</sub> |
|
||||||
|
| Dedicated platforms | FD | Extra 2 or 4 | jumper or PCB | Any_Slave | NA | NA | UART dedicated for BT & Wi-Fi on any other transport |
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> - [1] 1-bit/Dual/Quad SPI is not supported on ESP32
|
||||||
|
> - [2] UART is suitable only for low throughput environments. Throughput was obtained with a baud rate of 921600. On the ESP32-P4 + C6 development board, a baud rate of 4 Mbits/s can be achieved, giving TCP/UDP throughput of around 3.3 MBits/s.
|
||||||
|
> - [3] SDIO 4-Bit performance figures are measured with ESP32-C6 in shield box with 40MHz bandwidth
|
||||||
|
> - (S) Shield box measurements
|
||||||
|
> - (O) Over-the-air measurements
|
||||||
|
> - FD Full duplex interface
|
||||||
|
> - HD Half duplex interface
|
||||||
|
|
||||||
|
With jumper cables, 'Standard SPI' and 'Dual SPI' solutions are easiest to evaluate, without much of hardware dependencies. SDIO 1-Bit can be tested with jumper cables, but it needs some additional hardware config, such as installation of external pull-up registers.
|
||||||
|
|
||||||
|
In case case of dedicated platforms, Bluetooth uses standard HCI over UART. In rest of cases, Bluetooth and Wi-Fi uses same transport and hence less GPIOs and less complicated. In shared mode, bluetooth runs as Hosted HCI (multiplexed mode)
|
||||||
|
|
||||||
|
## 7 ESP-Hosted-MCU Header
|
||||||
|
|
||||||
|
### 7.1 ESP Hosted header
|
||||||
|
|
||||||
|
Host and slave always populate below header at the start of every frame, irrespective of actual or dummy data in payload.
|
||||||
|
|
||||||
|
| Field | Type | Bits | Mandatory? | Description |
|
||||||
|
|-----------------------------------|----------|--------|------------|------------------------------------------------------------|
|
||||||
|
| if_type | uint8_t | 4 | M | Interface type |
|
||||||
|
| if_num | uint8_t | 4 | M | Interface number |
|
||||||
|
| flags | uint8_t | 8 | M | Flags for additional information |
|
||||||
|
| len | uint16_t | 16 | M | Length of the payload |
|
||||||
|
| offset | uint16_t | 16 | M | Offset for the payload |
|
||||||
|
| checksum | uint16_t | 16 | M | Checksum for error detection (0 if checksum disabled) |
|
||||||
|
| seq_num | uint16_t | 16 | O | Sequence number for tracking packets (Useful in debugging) |
|
||||||
|
| throttle_cmd | uint8_t | 0 or 2 | O | Flow control command |
|
||||||
|
| reserved2 | uint8_t | 6 or 8 | M | Reserved bits |
|
||||||
|
| reserved3 | uint8_t | 8 | M | Reserved byte (union field) |
|
||||||
|
| hci\_pkt\_type or priv\_pkt\_type | uint8_t | 8 | M | Packet type for HCI interface (union field) |
|
||||||
|
|
||||||
|
### 7.2 Interface Types
|
||||||
|
|
||||||
|
Start of header states which type of frame is being carried.
|
||||||
|
|
||||||
|
| Interface Type | Value | Description |
|
||||||
|
|------------------|-------|----------------------------------------------|
|
||||||
|
| ESP\_INVALID\_IF | 0 | Invalid interface |
|
||||||
|
| ESP\_STA\_IF | 1 | Station frame |
|
||||||
|
| ESP\_AP\_IF | 2 | SoftAP frame |
|
||||||
|
| ESP\_SERIAL\_IF | 3 | Control frame |
|
||||||
|
| ESP\_HCI\_IF | 4 | Bluetooth Hosted HCI frame |
|
||||||
|
| ESP\_PRIV\_IF | 5 | Private communication between slave and host |
|
||||||
|
| ESP\_TEST\_IF | 6 | Transport throughput test |
|
||||||
|
| ESP\_ETH\_IF | 7 | Invalid |
|
||||||
|
| ESP\_MAX\_IF | 8 | type mentioned in dummy or empty frame |
|
||||||
|
|
||||||
|
## 8 Detailed Setup
|
||||||
|
|
||||||
|
Once you decided the transport to use, this section should guide how to set this transport, with hardware connections, configurations and verification. Users can evaluate one transport first and then move to other.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> [Design Considerations](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/design_consideration.md) that could be referred to, before you stick to any transport option. Referring to these consideration would help to get you faster to solution, make your design stable and less error-prone.
|
||||||
|
|
||||||
|
|
||||||
|
Irrespective of transport chosen, following steps are needed, which are step-wise explained in each transport.
|
||||||
|
|
||||||
|
1. Set-up the hosted-transport
|
||||||
|
2. Slave Flashing
|
||||||
|
- Slave project creation
|
||||||
|
- Slave configuration
|
||||||
|
- Slave flashing
|
||||||
|
- Slave logs
|
||||||
|
3. Host flashing
|
||||||
|
- Host project integration with ESP-IDF example
|
||||||
|
- Host configuration
|
||||||
|
- Host flashing
|
||||||
|
- Host logs
|
||||||
|
|
||||||
|
- [**Standard SPI (Full duplex)**](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/spi_full_duplex.md)
|
||||||
|
|
||||||
|
- [**SPI - Dual / Quad Half Duplex**](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/spi_half_duplex.md)
|
||||||
|
|
||||||
|
- [**SDIO (1-Bit / 4-Bit)**](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/sdio.md)
|
||||||
|
|
||||||
|
- [**UART for Wi-Fi and Bluetooth**](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/uart.md)
|
||||||
|
|
||||||
|
## 9 Examples
|
||||||
|
Check [examples](https://github.com/espressif/esp-hosted-mcu/tree/main/examples) directory for sample applications using ESP-Hosted.
|
||||||
|
- `examples/host_bluedroid_ble_compatibility_test`
|
||||||
|
- host BlueDroid Bluetooth example to test the Bluetooth compatibility and mobile phones
|
||||||
|
- `examples/host_bluedroid_bt_hid_mouse_device`
|
||||||
|
- host BlueDroid Bluetooth example to show how to implement a Bluetooth HID device using the APIs provided by Classic Bluetooth HID profile
|
||||||
|
- `examples/host_bluedroid_host_only`
|
||||||
|
- host BlueDroid Bluetooth example Bluetooth Host using ESP-Hosted as HCI IO to the BT Controller
|
||||||
|
- `examples/host_nimble_bleprph_host_only_vhci`
|
||||||
|
- host NimBLE Bluetooth example without needing extra GPIOs for HCI transport
|
||||||
|
|
||||||
|
## 10 Troubleshooting
|
||||||
|
|
||||||
|
If you encounter issues with using ESP-Hosted, see the following guide:
|
||||||
|
|
||||||
|
- [Troubleshooting Guide](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/troubleshooting.md)
|
||||||
|
- [Migration Guide](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/migration_guide.md)
|
||||||
|
- if you are upgrading to ESP-Hosted version V2.5.2 (or later) from an earlier version, there has been a change in the operation of the Bluetooth Controller on the co-processor. See [Migrating to V2.5.2](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/migration_guide.md#migrating-to-v252) in the Migration Guide for more information.
|
||||||
|
|
||||||
|
## 11 References
|
||||||
|
|
||||||
|
- [ESP Product Selector Page](https://products.espressif.com)
|
||||||
|
- [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started)
|
||||||
|
- [ESP-IDF Wi-Fi API](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html)
|
||||||
|
- [ESP-IDF Iperf Example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf)
|
||||||
|
- [ESP-IDF NimBLE](https://github.com/espressif/esp-nimble)
|
||||||
|
- [ESP Component Registry](https://components.espressif.com)
|
||||||
|
- [Registry Component: esp\_wifi\_remote](https://components.espressif.com/components/espressif/esp_wifi_remote)
|
||||||
|
- [Registry Component: esp\_hosted](https://components.espressif.com/components/espressif/esp_hosted)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESP_HOSTED_HEADER__H
|
||||||
|
#define __ESP_HOSTED_HEADER__H
|
||||||
|
|
||||||
|
/* Add packet number to debug any drops or out-of-seq packets */
|
||||||
|
//#define ESP_PKT_NUM_DEBUG 1
|
||||||
|
|
||||||
|
struct esp_payload_header {
|
||||||
|
uint8_t if_type:4;
|
||||||
|
uint8_t if_num:4;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t offset;
|
||||||
|
uint16_t checksum;
|
||||||
|
uint16_t seq_num;
|
||||||
|
uint8_t throttle_cmd:2;
|
||||||
|
uint8_t reserved2:6;
|
||||||
|
#ifdef ESP_PKT_NUM_DEBUG
|
||||||
|
uint16_t pkt_num;
|
||||||
|
#endif
|
||||||
|
/* Position of union field has to always be last,
|
||||||
|
* this is required for hci_pkt_type */
|
||||||
|
union {
|
||||||
|
uint8_t reserved3;
|
||||||
|
uint8_t hci_pkt_type; /* Packet type for HCI interface */
|
||||||
|
uint8_t priv_pkt_type; /* Packet type for priv interface */
|
||||||
|
};
|
||||||
|
/* Do no add anything here */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* ESP Payload Header Flags */
|
||||||
|
#define MORE_FRAGMENT (1 << 0)
|
||||||
|
#define FLAG_WAKEUP_PKT (1 << 1)
|
||||||
|
#define FLAG_POWER_SAVE_STARTED (1 << 2)
|
||||||
|
#define FLAG_POWER_SAVE_STOPPED (1 << 3)
|
||||||
|
|
||||||
|
#define H_ESP_PAYLOAD_HEADER_OFFSET sizeof(struct esp_payload_header)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESP_HOSTED_INTERFACE_H__
|
||||||
|
#define __ESP_HOSTED_INTERFACE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_INVALID_IF,
|
||||||
|
ESP_STA_IF,
|
||||||
|
ESP_AP_IF,
|
||||||
|
ESP_SERIAL_IF,
|
||||||
|
ESP_HCI_IF,
|
||||||
|
ESP_PRIV_IF,
|
||||||
|
ESP_TEST_IF,
|
||||||
|
ESP_ETH_IF,
|
||||||
|
ESP_MAX_IF,
|
||||||
|
} esp_hosted_if_type_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ESP_HOSTED_LWIP_SRC_PORT_HOOK_H__
|
||||||
|
#define __ESP_HOSTED_LWIP_SRC_PORT_HOOK_H__
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_ESP_HOSTED_NETWORK_SPLIT_ENABLED)
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
/* ----------------------------------Slave (local) Port Config---------------------------------------- */
|
||||||
|
/* If configured, Any new UDP socket would automatically bind as local port within this specified UDP port range.
|
||||||
|
* Please note, Reserved ports (generally <1024) like DHCP, etc would still work as they generally are hardcoded
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ENSURE_PORT_RANGE(port, START, END) \
|
||||||
|
(((port) >= (START) && (port) <= (END)) ? \
|
||||||
|
(port) : \
|
||||||
|
(((port) % ((END) - (START) + 1)) + (START)))
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_START
|
||||||
|
#define TCP_LOCAL_PORT_RANGE_START CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_START
|
||||||
|
#define TCP_LOCAL_PORT_RANGE_END CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_END
|
||||||
|
#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ENSURE_PORT_RANGE(port, TCP_LOCAL_PORT_RANGE_START, TCP_LOCAL_PORT_RANGE_END)
|
||||||
|
#if CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_END == 0xffff
|
||||||
|
#define IS_LOCAL_TCP_PORT(port) (port>=TCP_LOCAL_PORT_RANGE_START)
|
||||||
|
#else
|
||||||
|
#define IS_LOCAL_TCP_PORT(port) (port>=TCP_LOCAL_PORT_RANGE_START && (port<=CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_END))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_START
|
||||||
|
#define TCP_REMOTE_PORT_RANGE_START CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_START
|
||||||
|
#define TCP_REMOTE_PORT_RANGE_END CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_END
|
||||||
|
#define TCP_ENSURE_REMOTE_PORT_RANGE(port) ENSURE_PORT_RANGE(port, TCP_REMOTE_PORT_RANGE_START, TCP_REMOTE_PORT_RANGE_END)
|
||||||
|
#if CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_END == 0xffff
|
||||||
|
#define IS_REMOTE_TCP_PORT(port) (port>=TCP_REMOTE_PORT_RANGE_START)
|
||||||
|
#else
|
||||||
|
#define IS_REMOTE_TCP_PORT(port) (port>=TCP_REMOTE_PORT_RANGE_START && (port<=CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_END))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_START
|
||||||
|
#define UDP_LOCAL_PORT_RANGE_START CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_START
|
||||||
|
#define UDP_LOCAL_PORT_RANGE_END CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_END
|
||||||
|
#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ENSURE_PORT_RANGE(port, UDP_LOCAL_PORT_RANGE_START, UDP_LOCAL_PORT_RANGE_END)
|
||||||
|
|
||||||
|
#if CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_END == 0xffff
|
||||||
|
#define IS_LOCAL_UDP_PORT(port) (port>=UDP_LOCAL_PORT_RANGE_START)
|
||||||
|
#else
|
||||||
|
#define IS_LOCAL_UDP_PORT(port) (port>=UDP_LOCAL_PORT_RANGE_START && (port<=CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_END))
|
||||||
|
#endif
|
||||||
|
#define DNS_PORT_ALLOWED(port) IS_LOCAL_UDP_PORT(port)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_START
|
||||||
|
#define UDP_REMOTE_PORT_RANGE_START CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_START
|
||||||
|
#define UDP_REMOTE_PORT_RANGE_END CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_END
|
||||||
|
#define UDP_ENSURE_REMOTE_PORT_RANGE(port) ENSURE_PORT_RANGE(port, UDP_REMOTE_PORT_RANGE_START, UDP_REMOTE_PORT_RANGE_END)
|
||||||
|
|
||||||
|
#if CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_END == 0xffff
|
||||||
|
#define IS_REMOTE_UDP_PORT(port) (port>=UDP_REMOTE_PORT_RANGE_START)
|
||||||
|
#else
|
||||||
|
#define IS_REMOTE_UDP_PORT(port) (port>=UDP_REMOTE_PORT_RANGE_START && (port<=CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_END))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* __ESP_HOSTED_LWIP_SOURCE_PORT_BINDING_HOOK_H__ */
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESP_HOSTED_LOG_H
|
||||||
|
#define __ESP_HOSTED_LOG_H
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#define ESP_PRIV_HEXDUMP(tag1, tag2, buff, buf_len, display_len, curr_level) \
|
||||||
|
if ( LOG_LOCAL_LEVEL >= curr_level) { \
|
||||||
|
int len_to_print = 0; \
|
||||||
|
len_to_print = display_len<buf_len? display_len: buf_len; \
|
||||||
|
ESP_LOG_LEVEL_LOCAL(curr_level, tag1, "%s: buf_len[%d], print_len[%d]", \
|
||||||
|
tag2, (int)buf_len, (int)len_to_print); \
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(tag2, buff, len_to_print, curr_level); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ESP_HEXLOGE(tag2, buff, buf_len, display_len) ESP_PRIV_HEXDUMP(TAG, tag2, buff, buf_len, display_len, ESP_LOG_ERROR)
|
||||||
|
#define ESP_HEXLOGW(tag2, buff, buf_len, display_len) ESP_PRIV_HEXDUMP(TAG, tag2, buff, buf_len, display_len, ESP_LOG_WARN)
|
||||||
|
#define ESP_HEXLOGI(tag2, buff, buf_len, display_len) ESP_PRIV_HEXDUMP(TAG, tag2, buff, buf_len, display_len, ESP_LOG_INFO)
|
||||||
|
#define ESP_HEXLOGD(tag2, buff, buf_len, display_len) ESP_PRIV_HEXDUMP(TAG, tag2, buff, buf_len, display_len, ESP_LOG_DEBUG)
|
||||||
|
#define ESP_HEXLOGV(tag2, buff, buf_len, display_len) ESP_PRIV_HEXDUMP(TAG, tag2, buff, buf_len, display_len, ESP_LOG_VERBOSE)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MEMPOOL_H__
|
||||||
|
#define __MEMPOOL_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#define MEMPOOL_OK 0
|
||||||
|
#define MEMPOOL_FAIL -1
|
||||||
|
|
||||||
|
#define MEMSET_REQUIRED 1
|
||||||
|
#define MEMSET_NOT_REQUIRED 0
|
||||||
|
|
||||||
|
typedef struct hosted_mempool_t hosted_mempool_t;
|
||||||
|
|
||||||
|
// memory capability requested by mempool
|
||||||
|
typedef enum {
|
||||||
|
HOSTED_MEM_CAP_NONE, // generic memory allocation
|
||||||
|
HOSTED_MEM_CAP_DMA, // memory allocated must be DMA capable
|
||||||
|
HOSTED_MEM_CAP_MAX
|
||||||
|
} hosted_mem_cap_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// pointer and size of preallocated memory to use. If NULL, mempool allocates internally
|
||||||
|
void *pre_allocated_mem;
|
||||||
|
size_t pre_allocated_mem_size;
|
||||||
|
|
||||||
|
size_t num_blocks;
|
||||||
|
size_t block_size;
|
||||||
|
int alignment_in_bytes;
|
||||||
|
|
||||||
|
// required functions to malloc, calloc, memset and free memory using capability based allocs
|
||||||
|
void * (*malloc)(size_t size, hosted_mem_cap_t cap);
|
||||||
|
void * (*calloc)(size_t num_elem, size_t size_elem, hosted_mem_cap_t cap);
|
||||||
|
void * (*memset)(void *s, int c, size_t n);
|
||||||
|
void (*free)(void *ptr);
|
||||||
|
} hosted_mempool_config_t;
|
||||||
|
|
||||||
|
hosted_mempool_t * hosted_mempool_create(hosted_mempool_config_t * config);
|
||||||
|
void hosted_mempool_destroy(struct hosted_mempool_t *mempool);
|
||||||
|
void * hosted_mempool_alloc(struct hosted_mempool_t *mempool,
|
||||||
|
size_t nbytes, uint8_t need_memset);
|
||||||
|
int hosted_mempool_free(struct hosted_mempool_t *mempool, void *mem);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "mempool.h"
|
||||||
|
#include "mempool_ll.h"
|
||||||
|
|
||||||
|
static const char *TAG = "HS_MP";
|
||||||
|
|
||||||
|
#define MEMPOOL_NAME_STR_SIZE 32
|
||||||
|
|
||||||
|
#define IS_MEMPOOL_ALIGNED(VAL, BYTES) (!((VAL) & (BYTES - 1)))
|
||||||
|
#define MEMPOOL_ALIGNED(VAL, BYTES) ((VAL) + (BYTES) - \
|
||||||
|
((VAL) & (BYTES - 1)))
|
||||||
|
|
||||||
|
typedef struct hosted_mempool_t {
|
||||||
|
struct os_mempool *pool;
|
||||||
|
uint8_t *heap;
|
||||||
|
uint8_t static_heap;
|
||||||
|
size_t num_blocks;
|
||||||
|
size_t block_size;
|
||||||
|
int alignment_bytes;
|
||||||
|
void * (*malloc)(size_t size, hosted_mem_cap_t cap);
|
||||||
|
void * (*calloc)(size_t num_elem, size_t size_elem, hosted_mem_cap_t cap);
|
||||||
|
void * (*memset)(void *s, int c, size_t n);
|
||||||
|
void (*free)(void *ptr);
|
||||||
|
struct mempool_ops_t *ops;
|
||||||
|
} hosted_mempool_t;
|
||||||
|
|
||||||
|
#define MEMPOOL_FREE(freefn, x) do { \
|
||||||
|
if (x) { \
|
||||||
|
freefn(x); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
/* For Statically allocated memory, pass as pre_allocated_mem.
|
||||||
|
* If NULL passed, will allocate from heap
|
||||||
|
*/
|
||||||
|
hosted_mempool_t * hosted_mempool_create(hosted_mempool_config_t * config)
|
||||||
|
{
|
||||||
|
if (!config ||
|
||||||
|
!config->malloc ||
|
||||||
|
!config->calloc ||
|
||||||
|
!config->memset ||
|
||||||
|
!config->free) {
|
||||||
|
ESP_LOGE(TAG, "NULL config, or required memory functions not provided");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hosted_mempool_t *new = NULL;
|
||||||
|
struct os_mempool *pool = NULL;
|
||||||
|
uint8_t *heap = NULL;
|
||||||
|
|
||||||
|
new = (hosted_mempool_t *)config->calloc(1, sizeof(hosted_mempool_t), HOSTED_MEM_CAP_NONE);
|
||||||
|
if (!new) {
|
||||||
|
ESP_LOGE(TAG, "hosted mempool init failed: no mem");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
new->ops = os_mempool_get_ops();
|
||||||
|
if (!new->ops) {
|
||||||
|
ESP_LOGE(TAG, "hosted mempool init failed: no mempool ops");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = (struct os_mempool *)config->calloc(1, sizeof(struct os_mempool), HOSTED_MEM_CAP_NONE);
|
||||||
|
if (!pool) {
|
||||||
|
ESP_LOGE(TAG, "pool init failed: no mem");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config->pre_allocated_mem) {
|
||||||
|
/* no pre-allocated mem, allocate new */
|
||||||
|
heap = (uint8_t *)config->malloc(MEMPOOL_ALIGNED(
|
||||||
|
OS_MEMPOOL_BYTES(config->num_blocks, config->block_size),
|
||||||
|
config->alignment_in_bytes),
|
||||||
|
HOSTED_MEM_CAP_DMA);
|
||||||
|
if (!heap) {
|
||||||
|
ESP_LOGE(TAG, "mempool create failed: no mem\n");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* preallocated memory for mem pool */
|
||||||
|
if (config->pre_allocated_mem_size < OS_MEMPOOL_BYTES(config->num_blocks,
|
||||||
|
config->block_size)) {
|
||||||
|
ESP_LOGE(TAG, "mempool create failed: insufficient memory");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_MEMPOOL_ALIGNED((unsigned long)config->pre_allocated_mem,
|
||||||
|
config->alignment_in_bytes)) {
|
||||||
|
ESP_LOGE(TAG, "mempool create failed: mempool start addr unaligned");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
heap = config->pre_allocated_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
char str[MEMPOOL_NAME_STR_SIZE] = {0};
|
||||||
|
snprintf(str, MEMPOOL_NAME_STR_SIZE, "hosted_%p", pool);
|
||||||
|
|
||||||
|
if (new->ops->mempool_init(pool, config->num_blocks, config->block_size, heap, str)) {
|
||||||
|
ESP_LOGE(TAG, "mempool_init failed");
|
||||||
|
goto free_buffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->heap = heap;
|
||||||
|
new->pool = pool;
|
||||||
|
new->num_blocks = config->num_blocks;
|
||||||
|
new->block_size = config->block_size;
|
||||||
|
|
||||||
|
if (config->pre_allocated_mem)
|
||||||
|
new->static_heap = 1;
|
||||||
|
|
||||||
|
// record the alignment
|
||||||
|
new->alignment_bytes = config->alignment_in_bytes;
|
||||||
|
|
||||||
|
// save the memory functions
|
||||||
|
new->malloc = config->malloc;
|
||||||
|
new->calloc = config->calloc;
|
||||||
|
new->memset = config->memset;
|
||||||
|
new->free = config->free;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
|
||||||
|
free_buffs:
|
||||||
|
MEMPOOL_FREE(config->free, new);
|
||||||
|
MEMPOOL_FREE(config->free, pool);
|
||||||
|
if (!config->pre_allocated_mem)
|
||||||
|
MEMPOOL_FREE(config->free, heap);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hosted_mempool_destroy(hosted_mempool_t *mempool)
|
||||||
|
{
|
||||||
|
if (!mempool)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if MEMPOOL_DEBUG
|
||||||
|
ESP_LOGI(MEM_TAG, "Destroy mempool %p num_blk[%lu] blk_size:[%lu]", mempool->pool, mempool->num_blocks, mempool->block_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mempool->ops->mempool_unregister(mempool->pool);
|
||||||
|
MEMPOOL_FREE(mempool->free, mempool->pool);
|
||||||
|
|
||||||
|
if (!mempool->static_heap)
|
||||||
|
MEMPOOL_FREE(mempool->free, mempool->heap);
|
||||||
|
|
||||||
|
MEMPOOL_FREE(mempool->free, mempool);
|
||||||
|
}
|
||||||
|
|
||||||
|
void * hosted_mempool_alloc(hosted_mempool_t *mempool,
|
||||||
|
size_t nbytes, uint8_t need_memset)
|
||||||
|
{
|
||||||
|
if (!mempool) {
|
||||||
|
ESP_LOGE(TAG, "mempool %p is NULL", mempool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mem = NULL;
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||||
|
assert(mempool->heap);
|
||||||
|
assert(mempool->pool);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(nbytes > mempool->block_size) {
|
||||||
|
ESP_LOGE(TAG, "Exp alloc bytes[%u] > mempool block size[%u]\n",
|
||||||
|
nbytes, mempool->block_size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem = mempool->ops->memblock_get(mempool->pool);
|
||||||
|
if (mem && need_memset)
|
||||||
|
mempool->memset(mem, 0, nbytes);
|
||||||
|
|
||||||
|
if (!mem) {
|
||||||
|
ESP_LOGE(TAG, "mempool %p alloc failed nbytes[%u]", mempool, nbytes);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hosted_mempool_free(hosted_mempool_t *mempool, void *mem)
|
||||||
|
{
|
||||||
|
if (!mem) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mempool) {
|
||||||
|
ESP_LOGE(TAG, "%s: mempool %p is NULL", __func__, mempool);
|
||||||
|
return MEMPOOL_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||||
|
assert(mempool->heap);
|
||||||
|
assert(mempool->pool);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return mempool->ops->memblock_put(mempool->pool, mem);
|
||||||
|
}
|
||||||
@@ -0,0 +1,516 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* NOTICE: File has been changed from original implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "mempool_ll.h"
|
||||||
|
#include "freertos/portable.h"
|
||||||
|
|
||||||
|
#if CONFIG_ESP_HOSTED_USE_MEMPOOL
|
||||||
|
|
||||||
|
SemaphoreHandle_t hosted_port_mutex;
|
||||||
|
#define OS_INIT_CRITICAL() (hosted_port_mutex = xSemaphoreCreateMutex())
|
||||||
|
#define OS_ENTER_CRITICAL() (xSemaphoreTake((hosted_port_mutex), portMAX_DELAY))
|
||||||
|
#define OS_EXIT_CRITICAL() (xSemaphoreGive((hosted_port_mutex)))
|
||||||
|
|
||||||
|
#define OS_MEM_TRUE_BLOCK_SIZE(bsize) OS_ALIGN(bsize, OS_ALIGNMENT)
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
|
||||||
|
#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) \
|
||||||
|
(((mp)->mp_flags & OS_MEMPOOL_F_EXT) ? \
|
||||||
|
OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size) : \
|
||||||
|
(OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size) + sizeof(os_membuf_t)))
|
||||||
|
#else
|
||||||
|
#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static STAILQ_HEAD(, os_mempool) g_os_mempool_list =
|
||||||
|
STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_POISON)
|
||||||
|
static uint32_t os_mem_poison = 0xde7ec7ed;
|
||||||
|
|
||||||
|
static_assert(sizeof(struct os_memblock) % 4 == 0, "sizeof(struct os_memblock) shall be aligned to 4");
|
||||||
|
static_assert(sizeof(os_mem_poison) == 4, "sizeof(os_mem_poison) shall be 4");
|
||||||
|
|
||||||
|
static void
|
||||||
|
os_mempool_poison(const struct os_mempool *mp, void *start)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
uint32_t *end;
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
sz = OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size);
|
||||||
|
p = start;
|
||||||
|
end = p + sz / 4;
|
||||||
|
p += sizeof(struct os_memblock) / 4;
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
*p = os_mem_poison;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
os_mempool_poison_check(const struct os_mempool *mp, void *start)
|
||||||
|
{
|
||||||
|
uint32_t *p;
|
||||||
|
uint32_t *end;
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
sz = OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size);
|
||||||
|
p = start;
|
||||||
|
end = p + sz / 4;
|
||||||
|
p += sizeof(struct os_memblock) / 4;
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
assert(*p == os_mem_poison);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define os_mempool_poison(mp, start)
|
||||||
|
#define os_mempool_poison_check(mp, start)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
|
||||||
|
#define OS_MEMPOOL_GUARD_PATTERN 0xBAFF1ED1
|
||||||
|
|
||||||
|
static void
|
||||||
|
os_mempool_guard(const struct os_mempool *mp, void *start)
|
||||||
|
{
|
||||||
|
uint32_t *tgt;
|
||||||
|
|
||||||
|
if ((mp->mp_flags & OS_MEMPOOL_F_EXT) == 0) {
|
||||||
|
tgt = (uint32_t *)((uintptr_t)start +
|
||||||
|
OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size));
|
||||||
|
*tgt = OS_MEMPOOL_GUARD_PATTERN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
os_mempool_guard_check(const struct os_mempool *mp, void *start)
|
||||||
|
{
|
||||||
|
uint32_t *tgt;
|
||||||
|
|
||||||
|
if ((mp->mp_flags & OS_MEMPOOL_F_EXT) == 0) {
|
||||||
|
tgt = (uint32_t *)((uintptr_t)start +
|
||||||
|
OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size));
|
||||||
|
assert(*tgt == OS_MEMPOOL_GUARD_PATTERN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define os_mempool_guard(mp, start)
|
||||||
|
#define os_mempool_guard_check(mp, start)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static os_error_t
|
||||||
|
os_mempool_init_internal(struct os_mempool *mp, uint16_t blocks,
|
||||||
|
uint32_t block_size, void *membuf, char *name,
|
||||||
|
uint8_t flags)
|
||||||
|
{
|
||||||
|
int true_block_size;
|
||||||
|
int i;
|
||||||
|
uint8_t *block_addr;
|
||||||
|
struct os_memblock *block_ptr;
|
||||||
|
|
||||||
|
/* Check for valid parameters */
|
||||||
|
if (!mp || (block_size == 0)) {
|
||||||
|
return OS_INVALID_PARM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!membuf) && (blocks != 0)) {
|
||||||
|
return OS_INVALID_PARM;
|
||||||
|
}
|
||||||
|
OS_INIT_CRITICAL();
|
||||||
|
|
||||||
|
if (membuf != NULL) {
|
||||||
|
/* Blocks need to be sized properly and memory buffer should be
|
||||||
|
* aligned
|
||||||
|
*/
|
||||||
|
if (((uintptr_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
|
||||||
|
return OS_MEM_NOT_ALIGNED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the memory pool structure */
|
||||||
|
mp->mp_block_size = block_size;
|
||||||
|
mp->mp_num_free = blocks;
|
||||||
|
mp->mp_min_free = blocks;
|
||||||
|
mp->mp_flags = flags;
|
||||||
|
mp->mp_num_blocks = blocks;
|
||||||
|
mp->mp_membuf_addr = (uintptr_t)membuf;
|
||||||
|
mp->name = name;
|
||||||
|
SLIST_FIRST(mp) = membuf;
|
||||||
|
|
||||||
|
if (blocks > 0) {
|
||||||
|
os_mempool_poison(mp, membuf);
|
||||||
|
os_mempool_guard(mp, membuf);
|
||||||
|
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
|
||||||
|
|
||||||
|
/* Chain the memory blocks to the free list */
|
||||||
|
block_addr = (uint8_t *)membuf;
|
||||||
|
block_ptr = (struct os_memblock *)block_addr;
|
||||||
|
for (i = 1; i < blocks; i++) {
|
||||||
|
block_addr += true_block_size;
|
||||||
|
os_mempool_poison(mp, block_addr);
|
||||||
|
os_mempool_guard(mp, block_addr);
|
||||||
|
SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
|
||||||
|
block_ptr = (struct os_memblock *)block_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last one in the list should be NULL */
|
||||||
|
SLIST_NEXT(block_ptr, mb_next) = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STAILQ_INSERT_TAIL(&g_os_mempool_list, mp, mp_list);
|
||||||
|
|
||||||
|
return OS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static os_error_t
|
||||||
|
os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
|
||||||
|
void *membuf, char *name)
|
||||||
|
{
|
||||||
|
return os_mempool_init_internal(mp, blocks, block_size, membuf, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static os_error_t
|
||||||
|
os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
|
||||||
|
uint32_t block_size, void *membuf, char *name)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = os_mempool_init_internal(&mpe->mpe_mp, blocks, block_size, membuf,
|
||||||
|
name, OS_MEMPOOL_F_EXT);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpe->mpe_put_cb = NULL;
|
||||||
|
mpe->mpe_put_arg = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static os_error_t
|
||||||
|
os_mempool_unregister(struct os_mempool *mp)
|
||||||
|
{
|
||||||
|
struct os_mempool *prev;
|
||||||
|
struct os_mempool *next;
|
||||||
|
struct os_mempool *cur;
|
||||||
|
|
||||||
|
/* Remove the mempool from the global stailq. This is done manually rather
|
||||||
|
* than with `STAILQ_REMOVE` to allow for a graceful failure if the mempool
|
||||||
|
* isn't found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
prev = NULL;
|
||||||
|
STAILQ_FOREACH(cur, &g_os_mempool_list, mp_list) {
|
||||||
|
if (cur == mp) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur == NULL) {
|
||||||
|
return OS_INVALID_PARM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev == NULL) {
|
||||||
|
STAILQ_REMOVE_HEAD(&g_os_mempool_list, mp_list);
|
||||||
|
} else {
|
||||||
|
next = STAILQ_NEXT(cur, mp_list);
|
||||||
|
if (next == NULL) {
|
||||||
|
g_os_mempool_list.stqh_last = &STAILQ_NEXT(prev, mp_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
STAILQ_NEXT(prev, mp_list) = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static os_error_t
|
||||||
|
os_mempool_clear(struct os_mempool *mp)
|
||||||
|
{
|
||||||
|
struct os_memblock *block_ptr;
|
||||||
|
int true_block_size;
|
||||||
|
uint8_t *block_addr;
|
||||||
|
uint16_t blocks;
|
||||||
|
|
||||||
|
if (!mp) {
|
||||||
|
return OS_INVALID_PARM;
|
||||||
|
}
|
||||||
|
|
||||||
|
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
|
||||||
|
|
||||||
|
/* cleanup the memory pool structure */
|
||||||
|
mp->mp_num_free = mp->mp_num_blocks;
|
||||||
|
mp->mp_min_free = mp->mp_num_blocks;
|
||||||
|
os_mempool_poison(mp, (void *)mp->mp_membuf_addr);
|
||||||
|
os_mempool_guard(mp, (void *)mp->mp_membuf_addr);
|
||||||
|
SLIST_FIRST(mp) = (void *)mp->mp_membuf_addr;
|
||||||
|
|
||||||
|
/* Chain the memory blocks to the free list */
|
||||||
|
block_addr = (uint8_t *)mp->mp_membuf_addr;
|
||||||
|
block_ptr = (struct os_memblock *)block_addr;
|
||||||
|
blocks = mp->mp_num_blocks;
|
||||||
|
|
||||||
|
while (blocks > 1) {
|
||||||
|
block_addr += true_block_size;
|
||||||
|
os_mempool_poison(mp, block_addr);
|
||||||
|
os_mempool_guard(mp, block_addr);
|
||||||
|
SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
|
||||||
|
block_ptr = (struct os_memblock *)block_addr;
|
||||||
|
--blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last one in the list should be NULL */
|
||||||
|
SLIST_NEXT(block_ptr, mb_next) = NULL;
|
||||||
|
|
||||||
|
return OS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
os_memblock_from(const struct os_mempool *mp, const void *block_addr)
|
||||||
|
{
|
||||||
|
uint32_t true_block_size;
|
||||||
|
uintptr_t baddr;
|
||||||
|
uintptr_t end;
|
||||||
|
|
||||||
|
baddr = (uintptr_t)block_addr;
|
||||||
|
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
|
||||||
|
end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
|
||||||
|
|
||||||
|
/* Check that the block is in the memory buffer range. */
|
||||||
|
if ((baddr < mp->mp_membuf_addr) || (baddr >= end)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All freed blocks should be on true block size boundaries! */
|
||||||
|
if (((baddr - mp->mp_membuf_addr) % true_block_size) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
os_mempool_is_sane(const struct os_mempool *mp)
|
||||||
|
{
|
||||||
|
struct os_memblock *block;
|
||||||
|
|
||||||
|
/* Verify that each block in the free list belongs to the mempool. */
|
||||||
|
SLIST_FOREACH(block, mp, mb_next) {
|
||||||
|
if (!os_memblock_from(mp, block)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
os_mempool_poison_check(mp, block);
|
||||||
|
os_mempool_guard_check(mp, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void *
|
||||||
|
os_memblock_get(struct os_mempool *mp)
|
||||||
|
{
|
||||||
|
struct os_memblock *block;
|
||||||
|
|
||||||
|
/* Check to make sure they passed in a memory pool (or something) */
|
||||||
|
block = NULL;
|
||||||
|
if (mp) {
|
||||||
|
OS_ENTER_CRITICAL();
|
||||||
|
/* Check for any free */
|
||||||
|
if (mp->mp_num_free) {
|
||||||
|
/* Get a free block */
|
||||||
|
block = SLIST_FIRST(mp);
|
||||||
|
|
||||||
|
/* Set new free list head */
|
||||||
|
SLIST_FIRST(mp) = SLIST_NEXT(block, mb_next);
|
||||||
|
|
||||||
|
/* Decrement number free by 1 */
|
||||||
|
mp->mp_num_free--;
|
||||||
|
if (mp->mp_min_free > mp->mp_num_free) {
|
||||||
|
mp->mp_min_free = mp->mp_num_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OS_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
if (block) {
|
||||||
|
os_mempool_poison_check(mp, block);
|
||||||
|
os_mempool_guard_check(mp, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static os_error_t
|
||||||
|
os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr)
|
||||||
|
{
|
||||||
|
struct os_memblock *block;
|
||||||
|
|
||||||
|
os_mempool_guard_check(mp, block_addr);
|
||||||
|
os_mempool_poison(mp, block_addr);
|
||||||
|
|
||||||
|
block = (struct os_memblock *)block_addr;
|
||||||
|
OS_ENTER_CRITICAL();
|
||||||
|
|
||||||
|
/* Chain current free list pointer to this block; make this block head */
|
||||||
|
SLIST_NEXT(block, mb_next) = SLIST_FIRST(mp);
|
||||||
|
SLIST_FIRST(mp) = block;
|
||||||
|
|
||||||
|
/* XXX: Should we check that the number free <= number blocks? */
|
||||||
|
/* Increment number free */
|
||||||
|
mp->mp_num_free++;
|
||||||
|
|
||||||
|
OS_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return OS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static os_error_t
|
||||||
|
os_memblock_put(struct os_mempool *mp, void *block_addr)
|
||||||
|
{
|
||||||
|
struct os_mempool_ext *mpe;
|
||||||
|
os_error_t ret;
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||||
|
struct os_memblock *block;
|
||||||
|
int sr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make sure parameters are valid */
|
||||||
|
if ((mp == NULL) || (block_addr == NULL)) {
|
||||||
|
ret = OS_INVALID_PARM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||||
|
/* Check that the block we are freeing is a valid block! */
|
||||||
|
assert(os_memblock_from(mp, block_addr));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for duplicate free.
|
||||||
|
*/
|
||||||
|
OS_ENTER_CRITICAL();
|
||||||
|
SLIST_FOREACH(block, mp, mb_next) {
|
||||||
|
assert(block != (struct os_memblock *)block_addr);
|
||||||
|
}
|
||||||
|
OS_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* If this is an extended mempool with a put callback, call the callback
|
||||||
|
* instead of freeing the block directly.
|
||||||
|
*/
|
||||||
|
if (mp->mp_flags & OS_MEMPOOL_F_EXT) {
|
||||||
|
mpe = (struct os_mempool_ext *)mp;
|
||||||
|
if (mpe->mpe_put_cb != NULL) {
|
||||||
|
ret = mpe->mpe_put_cb(mpe, block_addr, mpe->mpe_put_arg);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No callback; free the block. */
|
||||||
|
ret = os_memblock_put_from_cb(mp, block_addr);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static struct os_mempool *
|
||||||
|
os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
|
||||||
|
{
|
||||||
|
struct os_mempool *cur;
|
||||||
|
|
||||||
|
if (mp == NULL) {
|
||||||
|
cur = STAILQ_FIRST(&g_os_mempool_list);
|
||||||
|
} else {
|
||||||
|
cur = STAILQ_NEXT(mp, mp_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur == NULL) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
omi->omi_block_size = cur->mp_block_size;
|
||||||
|
omi->omi_num_blocks = cur->mp_num_blocks;
|
||||||
|
omi->omi_num_free = cur->mp_num_free;
|
||||||
|
omi->omi_min_free = cur->mp_min_free;
|
||||||
|
omi->omi_name[0] = '\0';
|
||||||
|
strncat(omi->omi_name, cur->name, sizeof(omi->omi_name) - 1);
|
||||||
|
|
||||||
|
return (cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct os_mempool *
|
||||||
|
os_mempool_get(const char *mempool_name, struct os_mempool_info *info)
|
||||||
|
{
|
||||||
|
struct os_mempool *mp;
|
||||||
|
|
||||||
|
mp = STAILQ_FIRST(&g_os_mempool_list);
|
||||||
|
while (mp) {
|
||||||
|
if (strcmp(mempool_name, mp->name) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mp = STAILQ_NEXT(mp, mp_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp != NULL && info != NULL) {
|
||||||
|
info->omi_block_size = mp->mp_block_size;
|
||||||
|
info->omi_num_blocks = mp->mp_num_blocks;
|
||||||
|
info->omi_num_free = mp->mp_num_free;
|
||||||
|
info->omi_min_free = mp->mp_min_free;
|
||||||
|
info->omi_name[0] = '\0';
|
||||||
|
strncat(info->omi_name, mp->name, sizeof(info->omi_name) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct mempool_ops_t opts = {
|
||||||
|
.mempool_init = os_mempool_init,
|
||||||
|
.mempool_unregister = os_mempool_unregister,
|
||||||
|
.memblock_get = os_memblock_get,
|
||||||
|
.memblock_put = os_memblock_put,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mempool_ops_t * os_mempool_get_ops(void)
|
||||||
|
{
|
||||||
|
return &opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_ESP_HOSTED_USE_MEMPOOL
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* NOTICE: File has been changed from original implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OS_MEMPOOL_H_
|
||||||
|
#define _OS_MEMPOOL_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "sys/queue.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/portmacro.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
#if CONFIG_ESP_HOSTED_USE_MEMPOOL
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name
|
||||||
|
|
||||||
|
#define OS_ALIGN(__n, __a) ( \
|
||||||
|
(((__n) & ((__a) - 1)) == 0) ? \
|
||||||
|
(__n) : \
|
||||||
|
((__n) + ((__a) - ((__n) & ((__a) - 1)))) \
|
||||||
|
)
|
||||||
|
#define OS_ALIGNMENT 4
|
||||||
|
|
||||||
|
enum os_error {
|
||||||
|
OS_OK = 0,
|
||||||
|
OS_ENOMEM = 1,
|
||||||
|
OS_EINVAL = 2,
|
||||||
|
OS_INVALID_PARM = 3,
|
||||||
|
OS_MEM_NOT_ALIGNED = 4,
|
||||||
|
OS_BAD_MUTEX = 5,
|
||||||
|
OS_TIMEOUT = 6,
|
||||||
|
OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */
|
||||||
|
OS_ERR_PRIV = 8, /* Privileged access error */
|
||||||
|
OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */
|
||||||
|
OS_ENOENT = 10, /* No such thing */
|
||||||
|
OS_EBUSY = 11, /* Resource busy */
|
||||||
|
OS_ERROR = 12, /* Generic Error */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum os_error os_error_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A memory block structure. This simply contains a pointer to the free list
|
||||||
|
* chain and is only used when the block is on the free list. When the block
|
||||||
|
* has been removed from the free list the entire memory block is usable by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
struct os_memblock {
|
||||||
|
/** Next memory block in the list. */
|
||||||
|
SLIST_ENTRY(os_memblock) mb_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* XXX: Change this structure so that we keep the first address in the pool? */
|
||||||
|
/* XXX: add memory debug structure and associated code */
|
||||||
|
/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
|
||||||
|
SLIST_HEAD(,os_memblock) mp_head; */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory pool
|
||||||
|
*/
|
||||||
|
struct os_mempool {
|
||||||
|
/** Size of the memory blocks, in bytes. */
|
||||||
|
uint32_t mp_block_size;
|
||||||
|
/** The number of memory blocks. */
|
||||||
|
uint16_t mp_num_blocks;
|
||||||
|
/** The number of free blocks left */
|
||||||
|
uint16_t mp_num_free;
|
||||||
|
/** The lowest number of free blocks seen */
|
||||||
|
uint16_t mp_min_free;
|
||||||
|
/** Bitmap of OS_MEMPOOL_F_[...] values. */
|
||||||
|
uint8_t mp_flags;
|
||||||
|
/** Address of memory buffer used by pool */
|
||||||
|
uintptr_t mp_membuf_addr;
|
||||||
|
/** Next memory pool in the list. */
|
||||||
|
STAILQ_ENTRY(os_mempool) mp_list;
|
||||||
|
/** Head of the list of memory blocks. */
|
||||||
|
SLIST_HEAD(,os_memblock);
|
||||||
|
/** Name for memory block */
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates an extended mempool. Address can be safely cast to
|
||||||
|
* (struct os_mempool_ext *).
|
||||||
|
*/
|
||||||
|
#define OS_MEMPOOL_F_EXT 0x01
|
||||||
|
|
||||||
|
struct os_mempool_ext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block put callback function. If configured, this callback gets executed
|
||||||
|
* whenever a block is freed to the corresponding extended mempool. Note: The
|
||||||
|
* os_memblock_put() function calls this callback instead of freeing the block
|
||||||
|
* itself. Therefore, it is the callback's responsibility to free the block
|
||||||
|
* via a call to os_memblock_put_from_cb().
|
||||||
|
*
|
||||||
|
* @param ome The extended mempool that a block is being
|
||||||
|
* freed back to.
|
||||||
|
* @param data The block being freed.
|
||||||
|
* @param arg Optional argument configured along with the
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* @return Indicates whether the block was successfully
|
||||||
|
* freed. A non-zero value should only be
|
||||||
|
* returned if the block was not successfully
|
||||||
|
* released back to its pool.
|
||||||
|
*/
|
||||||
|
typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
/** Extended memory pool. */
|
||||||
|
struct os_mempool_ext {
|
||||||
|
/** Standard memory pool. */
|
||||||
|
struct os_mempool mpe_mp;
|
||||||
|
|
||||||
|
/** Callback that is executed immediately when a block is freed. */
|
||||||
|
os_mempool_put_fn *mpe_put_cb;
|
||||||
|
|
||||||
|
/** Optional argument passed to the callback function. */
|
||||||
|
void *mpe_put_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Length of the name of memory pool */
|
||||||
|
#define OS_MEMPOOL_INFO_NAME_LEN (32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information describing a memory pool, used to return OS information
|
||||||
|
* to the management layer.
|
||||||
|
*/
|
||||||
|
struct os_mempool_info {
|
||||||
|
/** Size of the memory blocks in the pool */
|
||||||
|
int omi_block_size;
|
||||||
|
/** Number of memory blocks in the pool */
|
||||||
|
int omi_num_blocks;
|
||||||
|
/** Number of free memory blocks */
|
||||||
|
int omi_num_free;
|
||||||
|
/** Minimum number of free memory blocks ever */
|
||||||
|
int omi_min_free;
|
||||||
|
/** Name of the memory pool */
|
||||||
|
char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To calculate size of the memory buffer needed for the pool. NOTE: This size
|
||||||
|
* is NOT in bytes! The size is the number of os_membuf_t elements required for
|
||||||
|
* the memory pool.
|
||||||
|
*/
|
||||||
|
#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
|
||||||
|
/** Leave extra 4 bytes of guard area at the end. */
|
||||||
|
#define OS_MEMPOOL_BLOCK_SZ(sz) ((sz) + sizeof(os_membuf_t))
|
||||||
|
#else
|
||||||
|
/** Size of a memory pool block. */
|
||||||
|
#define OS_MEMPOOL_BLOCK_SZ(sz) (sz)
|
||||||
|
#endif
|
||||||
|
#if (OS_ALIGNMENT == 4)
|
||||||
|
typedef uint32_t os_membuf_t;
|
||||||
|
#elif (OS_ALIGNMENT == 8)
|
||||||
|
typedef uint64_t os_membuf_t;
|
||||||
|
#elif (OS_ALIGNMENT == 16)
|
||||||
|
typedef __uint128_t os_membuf_t;
|
||||||
|
#else
|
||||||
|
#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`"
|
||||||
|
#endif /* OS_ALIGNMENT == * */
|
||||||
|
|
||||||
|
/** The total size of a memory pool, including alignment. */
|
||||||
|
#define OS_MEMPOOL_SIZE(n,blksize) (((OS_MEMPOOL_BLOCK_SZ(blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
|
||||||
|
|
||||||
|
/** Calculates the number of bytes required to initialize a memory pool. */
|
||||||
|
#define OS_MEMPOOL_BYTES(n,blksize) \
|
||||||
|
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
|
||||||
|
|
||||||
|
struct mempool_ops_t {
|
||||||
|
os_error_t (*mempool_init)(struct os_mempool *mp, uint16_t blocks, uint32_t block_size, void *membuf, char *name);
|
||||||
|
os_error_t (*mempool_unregister)(struct os_mempool *mp);
|
||||||
|
void * (*memblock_get)(struct os_mempool *mp);
|
||||||
|
os_error_t (*memblock_put)(struct os_mempool *mp, void *block_addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mempool_ops_t * os_mempool_get_ops(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CONFIG_ESP_HOSTED_USE_MEMPOOL
|
||||||
|
|
||||||
|
#endif /* _OS_MEMPOOL_H_ */
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# About Proto Files
|
||||||
|
|
||||||
|
|
||||||
|
## Protobuf Submodule
|
||||||
|
|
||||||
|
[protobuf-c](https://github.com/protobuf-c/protobuf-c) is open source code used as submodule in ESP-Hosted-FG in directory `../protobuf-c/`
|
||||||
|
If this directory is empty, please run
|
||||||
|
```sh
|
||||||
|
$ cd esp-hosted
|
||||||
|
$ git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `esp_hosted_rpc.proto`
|
||||||
|
- This is Ready-To-Use protobuf file which has messages for Request / Response / Events to communicate between Host and ESP
|
||||||
|
- User can add his own message field in `.proto` file and generate respective C files using 'protoc'
|
||||||
|
|
||||||
|
- `esp_hosted_rpc.pb-c.c` & `esp_hosted_rpc.pb-c.h`
|
||||||
|
- Ready-To-Use Source Generated files using `esp_hosted_rpc.proto`
|
||||||
|
- These files also cached which was generated with current `esp_hosted_rpc.proto` file for easy use (No need to generate again)
|
||||||
|
- If any addition or modifications `esp_hosted_rpc.proto` done, these files need to be re-generated
|
||||||
|
|
||||||
|
|
||||||
|
## Generate esp_hosted_rpc.pb-c.c & esp_hosted_rpc.pb-c.h
|
||||||
|
|
||||||
|
If you want to add or modify existing set of RPC procedures supported, you need to modify `esp_hosted_rpc.proto` as needed and build it to generate new set of `esp_hosted_rpc.pb-c.c` & `esp_hosted_rpc.pb-c.h`.
|
||||||
|
For this, third party software for protobuf C compiler is needed to be installed
|
||||||
|
- Debian/Ubuntu
|
||||||
|
- sudo apt install protobuf-c-compiler
|
||||||
|
- Mac OS
|
||||||
|
- brew install protobuf protobuf-c
|
||||||
|
- Windows
|
||||||
|
- check https://github.com/protobuf-c/protobuf-c
|
||||||
|
|
||||||
|
`protoc --c_out` always needs the `protoc-gen-c` plugin from protobuf-c, so both protoc and protobuf-c must be present (on macOS these are separate Homebrew formulas, hence both are listed above).
|
||||||
|
|
||||||
|
This software might only be needed on development environment, Once esp_hosted_rpc.pb-c.c & esp_hosted_rpc.pb-c.h files are generated, could also be uninstalled (no more needed).
|
||||||
|
|
||||||
|
##### Steps to generate
|
||||||
|
```sh
|
||||||
|
$ cd <path/to/esp_hosted_fg>/common/proto
|
||||||
|
$ protoc esp_hosted_rpc.proto --c_out=.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add new RPC message
|
||||||
|
To send an new RPC request/response
|
||||||
|
<TBD>
|
||||||
|
1. Add C function in `host/host_common/commands.c`
|
||||||
|
2. Create python binding in `host/linux/host_control/python_support/commands_map_py_to_c.py` and its python function in `host/linux/host_control/python_support/commands_lib.py`.
|
||||||
|
3. Add ESP side C function in `esp/esp_driver/network_adapter/main/slave_commands.c`, respective to python function, to handle added message field.
|
||||||
|
|
||||||
|
User can test added functionality using `host/linux/host_control/python_support/test.py`.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# from git-sh-setup.sh
|
||||||
|
require_clean_work_tree () {
|
||||||
|
git rev-parse --verify HEAD >/dev/null || exit 1
|
||||||
|
git update-index -q --ignore-submodules --refresh
|
||||||
|
err=0
|
||||||
|
|
||||||
|
if ! git diff-files --quiet --ignore-submodules
|
||||||
|
then
|
||||||
|
echo >&2 "Cannot $0: You have unstaged changes."
|
||||||
|
err=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff-index --cached --quiet --ignore-submodules HEAD --
|
||||||
|
then
|
||||||
|
if [ $err = 0 ]
|
||||||
|
then
|
||||||
|
echo >&2 "Cannot $0: Your index contains uncommitted changes."
|
||||||
|
else
|
||||||
|
echo >&2 "Additionally, your index contains uncommitted changes."
|
||||||
|
fi
|
||||||
|
err=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $err = 1 ]
|
||||||
|
then
|
||||||
|
test -n "$2" && echo >&2 "$2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
require_clean_work_tree
|
||||||
|
|
||||||
|
if ! which doxygen >/dev/null; then
|
||||||
|
echo "Error: doxygen is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOXYGEN_VERSION="$(doxygen --version)"
|
||||||
|
|
||||||
|
DOC_BRANCH="gh-pages"
|
||||||
|
ORIG_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
ORIG_COMMIT="$(git describe --match=NeVeRmAtCh --always --abbrev=40 --dirty)"
|
||||||
|
|
||||||
|
TOP="$(pwd)"
|
||||||
|
export GIT_DIR="$TOP/.git"
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp --tmpdir=$TOP -d)"
|
||||||
|
HTMLDIR="$TMPDIR/_build/html"
|
||||||
|
INDEX_FILE="$GIT_DIR/index.${DOC_BRANCH}"
|
||||||
|
|
||||||
|
rm -f "$INDEX_FILE"
|
||||||
|
|
||||||
|
trap "{ cd $TOP; git checkout --force ${ORIG_BRANCH}; rm -f $INDEX_FILE; rm -rf $TMPDIR; }" EXIT
|
||||||
|
|
||||||
|
cd "$TMPDIR"
|
||||||
|
git reset --hard HEAD
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
mkdir _build
|
||||||
|
cd _build
|
||||||
|
../configure
|
||||||
|
make html
|
||||||
|
|
||||||
|
if ! git checkout "${DOC_BRANCH}"; then
|
||||||
|
git checkout --orphan "${DOC_BRANCH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
touch "$HTMLDIR/.nojekyll"
|
||||||
|
|
||||||
|
GIT_INDEX_FILE="$INDEX_FILE" GIT_WORK_TREE="$HTMLDIR" \
|
||||||
|
git add --no-ignore-removal .
|
||||||
|
GIT_INDEX_FILE="$INDEX_FILE" GIT_WORK_TREE="$HTMLDIR" \
|
||||||
|
git commit -m "Rebuild html documentation from commit ${ORIG_COMMIT} using Doxygen ${DOXYGEN_VERSION}"
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
*~
|
||||||
|
.*swp
|
||||||
|
*.la
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
*.lo
|
||||||
|
*.log
|
||||||
|
*.o
|
||||||
|
*.tar.gz
|
||||||
|
*.trs
|
||||||
|
.deps/
|
||||||
|
.dirstamp
|
||||||
|
.libs/
|
||||||
|
/Doxyfile
|
||||||
|
/Makefile
|
||||||
|
/Makefile.in
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache
|
||||||
|
/build-aux
|
||||||
|
/config.*
|
||||||
|
/configure
|
||||||
|
/doxygen-doc
|
||||||
|
/html
|
||||||
|
/libtool
|
||||||
|
/protobuf-c-*-coverage.info
|
||||||
|
/protobuf-c-*-coverage/
|
||||||
|
/stamp-h1
|
||||||
|
/stamp-html
|
||||||
|
/test-suite.log
|
||||||
|
TAGS
|
||||||
|
protobuf-c/libprotobuf-c.pc
|
||||||
|
protoc-c/protoc-c
|
||||||
|
protoc-c/protoc-gen-c
|
||||||
|
t/generated-code/test-generated-code
|
||||||
|
t/generated-code2/cxx-generate-packed-data
|
||||||
|
t/generated-code2/test-full-cxx-output.inc
|
||||||
|
t/generated-code2/test-generated-code2
|
||||||
|
t/generated-code3/test-generated-code3
|
||||||
|
t/version/version
|
||||||
|
*.pb-c.c
|
||||||
|
*.pb-c.h
|
||||||
|
*.pb.cc
|
||||||
|
*.pb.h
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
## Contributing
|
||||||
|
|
||||||
|
The most recently released `protobuf-c` version is kept on the `master` branch, while the `next` branch is used for commits targeted at the next release. Please base patches and pull requests against the `next` branch. __Do not open pull requests against master!__
|
||||||
|
|
||||||
|
Copyright to all contributions are retained by the original author, but must be licensed under the terms of the [BSD-2-Clause](http://opensource.org/licenses/BSD-2-Clause) license.
|
||||||
@@ -0,0 +1,564 @@
|
|||||||
|
protobuf-c (1.4.1)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.4.1
|
||||||
|
|
||||||
|
[ Todd C. Miller ]
|
||||||
|
* Only shift unsigned values to avoid implementation-specific behavior
|
||||||
|
(#506, #508).
|
||||||
|
* Fix regression with zero-length messages introduced in protobuf-c PR 500.
|
||||||
|
* Fix a clang analyzer 14 warning about a possible NULL deref (#512, #514).
|
||||||
|
|
||||||
|
[ steed717 ]
|
||||||
|
* Fix unsigned integer overflow (#499, #513).
|
||||||
|
|
||||||
|
protobuf-c (1.4.0)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.4.0.
|
||||||
|
|
||||||
|
[ Ilya Lipnitsky ]
|
||||||
|
* c_message.cc: Resolve name conflict between certain enums and oneofs
|
||||||
|
(#427).
|
||||||
|
* protobuf-c.h: Fix Windows DLL export issue with the
|
||||||
|
protobuf_c_empty_string symbol (#428).
|
||||||
|
* Standardize pkg-config for use by autotools and cmake, fix cmake tests
|
||||||
|
(#425).
|
||||||
|
* protobuf-c.c: Cast %lu args to unsigned long int (#429).
|
||||||
|
* protoc-c: Remove leading underscores from structs (#430).
|
||||||
|
* protoc-c: Fix shared lib build on windows, migrate from Travis CI to
|
||||||
|
GitHub Actions (#459).
|
||||||
|
* protobuf-c: Don't use ProtobufCWireType internally (#463).
|
||||||
|
* protoc-c: Add custom options support (#466).
|
||||||
|
* protobuf-c.c: Fix packed repeated bool parsing (#467).
|
||||||
|
|
||||||
|
[ Markus Engel ]
|
||||||
|
* Pack nested messages inline (#431).
|
||||||
|
|
||||||
|
[ Daniel Axtens ]
|
||||||
|
* Travis CI: Test on other platforms (#438).
|
||||||
|
|
||||||
|
[ Adam Cozzette ]
|
||||||
|
* Update the generator to fully qualify std::string (#443).
|
||||||
|
|
||||||
|
[ Piotr Pietraszkiewicz ]
|
||||||
|
* Install MSVC debug symbols alongside the protobuf-c.lib file (#456).
|
||||||
|
|
||||||
|
[ ihsinme ]
|
||||||
|
* Fix invalid unsigned arithmetic (#455).
|
||||||
|
|
||||||
|
[ Wolfram Rösler ]
|
||||||
|
* Avoid "unused function parameter" compiler warning (#453).
|
||||||
|
|
||||||
|
protobuf-c (1.3.3)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.3.3.
|
||||||
|
|
||||||
|
* Fix build failure on protobuf 2.x (#398).
|
||||||
|
|
||||||
|
[ msshapira ]
|
||||||
|
* CMake: Fix support for MSVC static build (#350).
|
||||||
|
|
||||||
|
[ Adam Cozzette ]
|
||||||
|
* Fix some test assertions in test-generated-code2.c (#392).
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* protobuf-c.c: Make zigzag encoding more compact (#400).
|
||||||
|
|
||||||
|
[ Markus Engel ]
|
||||||
|
* CMake: Fix endianness check.
|
||||||
|
|
||||||
|
protobuf-c (1.3.2)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.3.2.
|
||||||
|
|
||||||
|
* Use protobuf 3.7.1 in the Travis-CI environment (#368).
|
||||||
|
|
||||||
|
* Fix test suite build failure on newer versions of protobuf (#369).
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* Fix proto3 repeated scalar field default packing behavior (#330, #377).
|
||||||
|
|
||||||
|
[ Adam Cozzette ]
|
||||||
|
* Fix out-of-bounds read in scan_length_prefixed_data() (#375, #376).
|
||||||
|
|
||||||
|
[ Jurriaan Bremer ]
|
||||||
|
* Fix -Wdeclaration-after-statement warning in parse_oneof_member() (#360).
|
||||||
|
|
||||||
|
[ Hayri Ugur Koltuk ]
|
||||||
|
* Fix SIGSEGV in protobuf_c_message_check() on messages with unpopulated
|
||||||
|
oneof members (#358).
|
||||||
|
|
||||||
|
[ Italo Guerrieri ]
|
||||||
|
* Do not allow tag values of 0 in protobuf messages, as these are not
|
||||||
|
allowed by proto2 or proto3 (#299).
|
||||||
|
|
||||||
|
protobuf-c (1.3.1)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.3.1.
|
||||||
|
|
||||||
|
* Restore protobuf-2.x compatibility (#284, #285).
|
||||||
|
|
||||||
|
* Use xenial and protobuf 3.6.1 in the Travis-CI environment (#332).
|
||||||
|
|
||||||
|
* Convert uses of protobuf's scoped_ptr.h to C++11 std::unique_ptr, needed
|
||||||
|
to compile against protobuf 3.6.1 (#320, #333).
|
||||||
|
|
||||||
|
* Use AX_CXX_COMPILE_STDCXX macro to enable C++11 support in old compilers
|
||||||
|
(#312, #317, #327, #334).
|
||||||
|
|
||||||
|
[ Fredrik Gustafsson ]
|
||||||
|
* Add std:: to some types (#294, #305, #309).
|
||||||
|
|
||||||
|
[ Sam Collinson ]
|
||||||
|
* Check the return value of int_range_lookup before using as an array index;
|
||||||
|
it can return -1 (#315).
|
||||||
|
|
||||||
|
[ Matthias Dittrich ]
|
||||||
|
* Fix compilation on mingw by using explicit protoc --plugin=NAME=PATH syntax
|
||||||
|
in Makefile.am (#289, #290).
|
||||||
|
|
||||||
|
protobuf-c (1.3.0)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.3.0.
|
||||||
|
|
||||||
|
* Add test case for the issue in #220 (#254).
|
||||||
|
|
||||||
|
* Fix issue #251, "Bad enums with multiple oneofs" (#256).
|
||||||
|
|
||||||
|
* Add warning flags to my_CFLAGS (#257).
|
||||||
|
|
||||||
|
* Fix namespace errors when compiled with latest protobuf (#280).
|
||||||
|
|
||||||
|
* Bump minimum required header version for proto3 syntax (#282).
|
||||||
|
|
||||||
|
[ Paolo Borelli ]
|
||||||
|
* Turn the compiler into a protoc plugin (#206). This allows the protobuf-c
|
||||||
|
compiler to be invoked as "protoc --c_out=...". For backwards
|
||||||
|
compatibility, we still ship a protoc-c command, but it's a symlink to the
|
||||||
|
protoc-gen-c binary.
|
||||||
|
|
||||||
|
* proto3 support (#228).
|
||||||
|
|
||||||
|
* Remove leftover FIXME comment (#258).
|
||||||
|
|
||||||
|
* Fix proto3 "is zeroish" evaluation (#264).
|
||||||
|
|
||||||
|
* Small cleanup in oneof handling (#265).
|
||||||
|
|
||||||
|
* Rework is_zeroish one more time (#267).
|
||||||
|
|
||||||
|
* proto3: make strings default to "" instead of NULL (#274).
|
||||||
|
|
||||||
|
[ Tomek Wasilczyk ]
|
||||||
|
* Fix -Wsign-compare warnings (#213).
|
||||||
|
|
||||||
|
* Fix ISO C90 -Wdeclaration-after-statement warnings (#214).
|
||||||
|
|
||||||
|
* Fix bigendian -Wunused-label warning (#215).
|
||||||
|
|
||||||
|
[ Ilya Lipnitsky ]
|
||||||
|
* protoc-c/c_message.cc: Force int size on oneof enums (#221). Fixes wrong
|
||||||
|
enum generation and handling for onceof cases (#220).
|
||||||
|
|
||||||
|
[ Adnan ]
|
||||||
|
* Fix cmake build if built as part of an external project (#231).
|
||||||
|
|
||||||
|
[ Gregory Detal ]
|
||||||
|
* Remove .pb.{cc,h} in distdir instead of top_distdir in order to prevent
|
||||||
|
removing files from other projects when protobuf-c is included as an
|
||||||
|
autotools subproject (#232).
|
||||||
|
|
||||||
|
[ Ben Farnham ]
|
||||||
|
* Relax autoconf constraint from v2.64 to v2.63 so that it works on older
|
||||||
|
Linux distros (#233).
|
||||||
|
|
||||||
|
[ Thomas Köckerbauer ]
|
||||||
|
* rm argument fix for Solaris (#234).
|
||||||
|
|
||||||
|
* Add 'const' qualifier to 'init_value' variable in generated files (#236).
|
||||||
|
|
||||||
|
[ Richard Kettlewell ]
|
||||||
|
* Document and extend the effect of passing NULL to ..._free_unpacked
|
||||||
|
functions (#255).
|
||||||
|
|
||||||
|
[ Alex Milich ]
|
||||||
|
* CMake: Workaround for static builds that use MSVC (#243).
|
||||||
|
|
||||||
|
[ Josh Junon ]
|
||||||
|
* CMake: Allow protobuf-c to be included via include_subdirectory (#245).
|
||||||
|
|
||||||
|
[ Alexei Kasatkin ]
|
||||||
|
* CMake: Windows fixes (#266).
|
||||||
|
|
||||||
|
protobuf-c (1.2.1)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.2.1.
|
||||||
|
|
||||||
|
[ Paolo Borelli ]
|
||||||
|
* protoc-c: Generate code that uses the universal zero initializer {0} when
|
||||||
|
initializing a oneof union (#187, #205).
|
||||||
|
|
||||||
|
protobuf-c (1.2.0)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.2.0.
|
||||||
|
|
||||||
|
[ Ilya Lipnitsky ]
|
||||||
|
* Implement the "optimize_for = CODE_SIZE" option (#183).
|
||||||
|
|
||||||
|
* Eliminate undefined behavior in zigzag functions (#198).
|
||||||
|
|
||||||
|
* Pack negative enum values correctly (#199).
|
||||||
|
|
||||||
|
[ Peter Leschev ]
|
||||||
|
* Fix protobuf_c_message_get_packed_size() on 16-bit systems (#196, #197).
|
||||||
|
|
||||||
|
[ Diego Elio Pettenò ]
|
||||||
|
* Update link to Autotools Mythbuster to canonical site (#201).
|
||||||
|
|
||||||
|
[ Zex Li ]
|
||||||
|
* Skip test suite when cross-compiling (#184).
|
||||||
|
|
||||||
|
protobuf-c (1.1.1)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.1.1.
|
||||||
|
|
||||||
|
* Use protobuf 2.6.1 in the Travis-CI environment.
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* Munge C block comment delimiters in protobuf comments, preventing syntax
|
||||||
|
errors in generated header files (Issue #180, #185).
|
||||||
|
|
||||||
|
* Add static qualifier to ProtobufCEnumValue and ProtobufCEnumValueIndex
|
||||||
|
variables in generated output.
|
||||||
|
|
||||||
|
[ Oleg Efimov ]
|
||||||
|
* Fix -Wpointer-sign compiler diagnostics in the test suite.
|
||||||
|
|
||||||
|
* Check for NULL pointers in protobuf_c_message_free_unpacked()
|
||||||
|
(Issue #177).
|
||||||
|
|
||||||
|
* Exclude protoc-c and downloaded protobuf sources from Coveralls report.
|
||||||
|
|
||||||
|
[ Andrey Myznikov ]
|
||||||
|
* Fix incorrect 'short_name' field values in ProtobufCServiceDescriptor
|
||||||
|
variables in generated output.
|
||||||
|
|
||||||
|
protobuf-c (1.1.0)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.1.0.
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* Fix a bug when merging optional byte fields.
|
||||||
|
|
||||||
|
* Documentation updates.
|
||||||
|
|
||||||
|
* Implement oneof support (Issue #174). Protobuf 2.6.0 or newer is now
|
||||||
|
required to build protobuf-c.
|
||||||
|
|
||||||
|
* Print leading comments for enum, message, and field definitions into
|
||||||
|
generated header files (Issue #175).
|
||||||
|
|
||||||
|
protobuf-c (1.0.2)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Release 1.0.2.
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* Fix a build failure with Protobuf 2.6.0 related to aliased enum constants
|
||||||
|
(Issue #163).
|
||||||
|
|
||||||
|
* Protobuf 2.5.0 or newer is now required to build protobuf-c (Issue #166).
|
||||||
|
This is due to the fix for #163.
|
||||||
|
|
||||||
|
[ Alexei Kasatkin ]
|
||||||
|
* Eliminate void pointer arithmetic (Issue #167).
|
||||||
|
|
||||||
|
* Always define PROTOBUF_C__DEPRECATED, even on compilers that are not GCC
|
||||||
|
(Issue #167).
|
||||||
|
|
||||||
|
* Work around the lack of the 'inline' keyword in Microsoft compilers
|
||||||
|
(Issue #167).
|
||||||
|
|
||||||
|
* Add a CMakeLists.txt file as a fallback build system for Windows
|
||||||
|
(Issue #168).
|
||||||
|
|
||||||
|
[ Natanael Copa ]
|
||||||
|
* Fix a build failure in the test suite that occurred with a parallel make
|
||||||
|
running on a system with a large number of CPUs (Issue #156, #169).
|
||||||
|
|
||||||
|
protobuf-c (1.0.1)
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Explicitly set the .data field of ProtobufCBinaryData's to NULL when
|
||||||
|
unpacking a zero length byte string (Issue #157).
|
||||||
|
|
||||||
|
protobuf-c (1.0.0)
|
||||||
|
|
||||||
|
[ Andrei Nigmatulin ]
|
||||||
|
* Append "u", "ull", and "ll" integer literal suffixes for uint32, uint64,
|
||||||
|
and int64 default values in generated code, in order to avoid "integer
|
||||||
|
constant is so large that it is unsigned" compiler warnings.
|
||||||
|
(Issue #136.)
|
||||||
|
|
||||||
|
* Revert the problematic hash-based required field detection.
|
||||||
|
(Related to Issue #60, #79, #137.)
|
||||||
|
|
||||||
|
* Replace the 'packed' member of ProtobufCFieldDescriptor with a 'flags'
|
||||||
|
word. Define flags for packed and deprecated fields. (Issue #138.)
|
||||||
|
|
||||||
|
[ Dave Benson ]
|
||||||
|
* Treat a "length-prefixed" wire-type message for a repeated field as
|
||||||
|
packed-repeated whenever it makes sense (for all types other than
|
||||||
|
messages, strings, and bytes).
|
||||||
|
|
||||||
|
* Switch to New BSD license.
|
||||||
|
|
||||||
|
* Add protobuf_c_message_check().
|
||||||
|
|
||||||
|
* Compile error in packing 64-bit versions on some platforms
|
||||||
|
(srobbins99: Issue #68 Comment 1).
|
||||||
|
|
||||||
|
* Fix for memory error if the required-field check fails. See Issue #63
|
||||||
|
for demo (w/ nice test case by dror.harari).
|
||||||
|
|
||||||
|
* Add PROTOBUF_C_{MAJOR,MINOR} for compile-time checks and
|
||||||
|
protobuf_c_{major,minor} for checks about the running library
|
||||||
|
(Issue #53).
|
||||||
|
|
||||||
|
* Use a small constant-size hash-table instead of alloca() for detecting
|
||||||
|
required fields, and it also prevents us from using too much stack, etc.
|
||||||
|
(Related to Issue #60, #79).
|
||||||
|
|
||||||
|
* Add a macro to ensure enums are the size of ints (Issue #69).
|
||||||
|
|
||||||
|
[ Ilya Lipnitskiy ]
|
||||||
|
* Travis-CI integration.
|
||||||
|
|
||||||
|
* Add source .proto filename to generated files.
|
||||||
|
|
||||||
|
* Add protobuf-c version to protoc-c --version output (Issue #52).
|
||||||
|
|
||||||
|
* For embedded submessage fields, merge multiple instances of the same
|
||||||
|
field, per the protobuf documentation (Issue #91).
|
||||||
|
|
||||||
|
* Don't print unpack errors by default.
|
||||||
|
|
||||||
|
* Optionally allow running the test suite under valgrind with ./configure
|
||||||
|
--enable-valgrind-tests. (Based on valgrind-tests.m4 from gnulib.)
|
||||||
|
|
||||||
|
[ Kevin Lyda ]
|
||||||
|
* Autoconf portability fixes.
|
||||||
|
|
||||||
|
* Add doxygen detection and make targets to the build system.
|
||||||
|
|
||||||
|
* Doxygen documentation for the libprotobuf-c public API (Issue #132).
|
||||||
|
|
||||||
|
[ Nick Galbreath ]
|
||||||
|
* Prevent possible overflow on 64-bit systems (Issue #106).
|
||||||
|
|
||||||
|
[ Robert Edmonds ]
|
||||||
|
* Remove CMake (Issue #87).
|
||||||
|
|
||||||
|
* Modernize the build system.
|
||||||
|
- Don't generate any diagnostics when building the build system with
|
||||||
|
modern autotools (Issue #89).
|
||||||
|
|
||||||
|
- Use the PKG_CHECK_MODULES macro to locate protobuf.
|
||||||
|
|
||||||
|
- Use the AC_C_BIGENDIAN macro to detect endianness, rather than custom
|
||||||
|
code.
|
||||||
|
|
||||||
|
- Use the automake silent-rules option so the build output is actually
|
||||||
|
readable.
|
||||||
|
|
||||||
|
- Generate our own pkg-config .pc files.
|
||||||
|
|
||||||
|
* Reorganize the source tree. This affects the public protobuf-c header
|
||||||
|
path, which is now <protobuf-c/protobuf-c.h>. A compatibility symlink from
|
||||||
|
<google/protobuf-c/> to <protobuf-c/> has been installed so that existing
|
||||||
|
code will continue to compile. New code should at some point begin using
|
||||||
|
the new include path, i.e., "#include <protobuf-c/protobuf-c.h>" rather
|
||||||
|
than "#include <google/protobuf-c/protobuf-c.h>".
|
||||||
|
|
||||||
|
* The RPC code has been split out into a separate project, protobuf-c-rpc.
|
||||||
|
|
||||||
|
* Fix a potential use of an unitialized value in protobuf_c_message_unpack()
|
||||||
|
and several memory leaks in protoc-c, discovered by a commercial static code
|
||||||
|
analysis tool.
|
||||||
|
|
||||||
|
* Bump the libprotobuf-c SONAME.
|
||||||
|
|
||||||
|
* Begin versioning the library's symbols. (Based on ld-version-script.m4
|
||||||
|
from gnulib.)
|
||||||
|
|
||||||
|
* Preserve case in enum value names generated by protoc-c (Issue #129).
|
||||||
|
Reported by Oleg Efimov.
|
||||||
|
|
||||||
|
* Add library functions protobuf_c_version() and protobuf_c_version_string()
|
||||||
|
for retrieving the version of the compiled library, and header macros
|
||||||
|
PROTOBUF_C_VERSION and PROTOBUF_C_VERSION_STRING for retrieving the
|
||||||
|
version of the header file. This replaces the interfaces for retrieving
|
||||||
|
the protobuf-c version numbers in Issue #53.
|
||||||
|
|
||||||
|
* Add a version guard that ensures that the output of protoc-c is only
|
||||||
|
compiled against a protobuf-c header file from the exact same protobuf-c
|
||||||
|
release.
|
||||||
|
|
||||||
|
* Add a --enable-code-coverage option to configure, which enables a
|
||||||
|
"make check-code-coverage" build target. This generates a code coverage
|
||||||
|
report and requires the lcov tool to be installed.
|
||||||
|
|
||||||
|
* Remove the old DocBook documentation in doc/c-code-generator.{html,xml}.
|
||||||
|
Relevant material has been updated and incorporated into the Doxygen
|
||||||
|
documentation in the protobuf-c header file.
|
||||||
|
|
||||||
|
* Remove the protobuf_c_default_allocator and protobuf_c_system_allocator
|
||||||
|
global variables from the exported library interface. All exported library
|
||||||
|
functions that need to perform dynamic memory allocation receive a
|
||||||
|
user-provided ProtobufCAllocator* parameter. If this parameter is NULL,
|
||||||
|
the system's default memory allocator will be used.
|
||||||
|
|
||||||
|
Client code that previously passed "&protobuf_c_system_allocator" to
|
||||||
|
protobuf-c library functions taking a ProtobufCAllocator* argument should
|
||||||
|
be updated to pass "NULL" instead.
|
||||||
|
|
||||||
|
Client code that previously overrode protobuf_c_default_allocator with
|
||||||
|
custom allocation functions and passed NULL as the ProtobufCAllocator*
|
||||||
|
argument to protobuf-c library functions should be updated to instead
|
||||||
|
enclose the custom allocation functions in a ProtobufCAllocator struct and
|
||||||
|
pass this object to protobuf-c library functions taking a
|
||||||
|
ProtobufCAllocator* parameter.
|
||||||
|
|
||||||
|
* Update copyright and license statements throughout. The original
|
||||||
|
protobuf code released by Google was relicensed from Apache-2.0 to
|
||||||
|
BSD-3-Clause. Dave Benson also converted his license from BSD-3-Clause
|
||||||
|
to BSD-2-Clause.
|
||||||
|
|
||||||
|
[ Tomasz Wasilczyk ]
|
||||||
|
* Don't export protobuf_c_message_init_generic() as an external symbol.
|
||||||
|
|
||||||
|
* Don't use C++ style comments in C code.
|
||||||
|
|
||||||
|
* Fix -Wcast-align warnings when compiled with clang.
|
||||||
|
|
||||||
|
protobuf-c (0.15)
|
||||||
|
- make protobuf_c_message_init() into a function (Issue #49, daveb)
|
||||||
|
- Fix for freeing memory after unpacking bytes w/o a default-value.
|
||||||
|
(Andrei Nigmatulin)
|
||||||
|
- minor windows portability issues (use ProtobufC_FD) (Pop Stelian)
|
||||||
|
- --with-endianness={little,big} (Pop Stelian)
|
||||||
|
- bug setting up values of has_idle in public dispatch,
|
||||||
|
make protobuf_c_dispatch_run() use only public members (daveb)
|
||||||
|
- provide cmake support and some Windows compatibility (Nikita Manovich)
|
||||||
|
|
||||||
|
protobuf-c (0.14)
|
||||||
|
- build fix (missing dependency in test directory)
|
||||||
|
- add generation / installation of pkg-config files. (Bobby Powers)
|
||||||
|
- support for packed repeated fields (Dave Benson)
|
||||||
|
- bug in protobuf_c_dispatch_close_fd(), which usually only
|
||||||
|
showed up in later function calls.
|
||||||
|
- support for deprecated fields -- enable a GCC warning
|
||||||
|
if a field has the "deprecated" option enabled. (Andrei Nigmatulin)
|
||||||
|
- hackery to try to avoid touching inttypes.h on windows (Issue #41)
|
||||||
|
- fix for protobuf_c_message_unpack() to issue error if any
|
||||||
|
"required" field is missing in input stream. (Andrei Nigmatulin)
|
||||||
|
|
||||||
|
protobuf-c (0.13)
|
||||||
|
- Fix for when the number of connections gets too great in RPC.
|
||||||
|
(Leszek Swirski) (issue #32)
|
||||||
|
- Add --disable-protoc to only build libprotobuf-c (daveb)
|
||||||
|
- Bug fixes for protobuf_c_enum_descriptor_get_value_by_name()
|
||||||
|
and protobuf_c_service_descriptor_get_method_by_name()
|
||||||
|
- if descriptor->message_init != NULL, use it from unpack()
|
||||||
|
as an optimization (daveb)
|
||||||
|
- implement protobuf_c_{client,server}_set_error_handler()
|
||||||
|
|
||||||
|
protobuf-c (0.12)
|
||||||
|
- for field names which are reserved words, use the real name
|
||||||
|
given in the protobuf-c file, not the mangled name which
|
||||||
|
is the name of the member in the C structure. (Andrei Nigmatulin)
|
||||||
|
- add protobuf_c_message_init() function; add virtual function
|
||||||
|
that implements it efficiently. (Andrei Nigmatulin)
|
||||||
|
- bug fix for sfixed32, fixed32, float wire-types on
|
||||||
|
big-endian platforms (Robert Edmonds)
|
||||||
|
- compile with the latest protobuf (the header file wire_format_inl.h
|
||||||
|
is now wire_format.h) (Robert Edmonds)
|
||||||
|
|
||||||
|
protobuf-c (0.11)
|
||||||
|
- allow CFLAGS=-DPRINT_UNPACK_ERRORS=0 to suppress
|
||||||
|
unpack warnings from being printed at compile time (Andrei Nigmatulin)
|
||||||
|
- give error if an unknown wire-type is encountered (Andrei Nigmatulin)
|
||||||
|
- fix technically possible overflows during unpack of very
|
||||||
|
large messages (Andrei Nigmatulin)
|
||||||
|
- [UNFINISHED] windows RPC work
|
||||||
|
- use automake's "foreign" mode from within configure.ac
|
||||||
|
and add version information to the library (Robert Edmonds)
|
||||||
|
- ProtobufCServiceDescriptor::method_indices_by_name: missing
|
||||||
|
const. (Issue 21)
|
||||||
|
- Update to support new UnknownFields API. (fix by dcreager) (Issue 20)
|
||||||
|
|
||||||
|
protobuf-c (0.10)
|
||||||
|
- build issue on platforms which don't compute library dependencies
|
||||||
|
automatically.
|
||||||
|
- fix for certain types of corrupt messages (Landon Fuller) (issue 16)
|
||||||
|
|
||||||
|
protobuf-c (0.9)
|
||||||
|
- build issue: needed $(EXEEXT) in dependency lists for cygwin
|
||||||
|
- bug fix: protobuf_c_service_get_method_by_name() was not correct b/c
|
||||||
|
the service's methods were not sorted by name (the header file
|
||||||
|
used to incorrectly state that they were).
|
||||||
|
Now we correctly implement protobuf_c_service_get_method_by_name()
|
||||||
|
(using a bsearch indexed by separate array).
|
||||||
|
- generated source incompatibility: we added a new
|
||||||
|
member to ProtobufCServiceDescriptor (method_indices_by_name).
|
||||||
|
You will have to run the latest protobuf
|
||||||
|
to generate those structures.
|
||||||
|
- rename rpc-client's "autoretry" mechanism to "autoreconnect".
|
||||||
|
- bug fixes using TCP clients with the RPC system.
|
||||||
|
- handle allocation failures more gracefully (Jason Lunz) (issue 15)
|
||||||
|
|
||||||
|
protobuf-c (0.8)
|
||||||
|
- Destroy function typedef for Services was omitting a "*"
|
||||||
|
- service_machgen_invoke was broken. (issue 12)
|
||||||
|
- add RPC system (BETA)
|
||||||
|
- don't segfault when packing NULL strings and messages. (issue 13)
|
||||||
|
|
||||||
|
protobuf-c (0.7)
|
||||||
|
- memory leak: unknown fields were not being freed by free_unpacked()
|
||||||
|
- lowercase field names consistently when composing
|
||||||
|
default_value names. (issue 11)
|
||||||
|
- remove spurious semicolon (issue 10)
|
||||||
|
|
||||||
|
protobuf-c (0.6)
|
||||||
|
- Warning suppression for -Wcast-qual and -Wshadow.
|
||||||
|
- Support for default values of all types allowed by core protobuf.
|
||||||
|
- Generate message__init functions, for when the static initializer
|
||||||
|
isn't convenient.
|
||||||
|
- add some reserved fields at the end of the various descriptors
|
||||||
|
|
||||||
|
protobuf-c (0.5)
|
||||||
|
- License now included in major files.
|
||||||
|
- Use little-endian optimizations; fix a bug therein.
|
||||||
|
- Include 'make deb' target.
|
||||||
|
|
||||||
|
protobuf-c (0.4)
|
||||||
|
- Update to work with protobuf 2.0.1.
|
||||||
|
|
||||||
|
protobuf-c (0.2)
|
||||||
|
protobuf-c (0.3)
|
||||||
|
- Minor pedantic concerns about generated code.
|
||||||
|
|
||||||
|
protobuf-c (0.1)
|
||||||
|
- Lots of test code (and bug fixes).
|
||||||
|
|
||||||
|
protobuf-c (0.0)
|
||||||
|
- Initial release.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,193 @@
|
|||||||
|
<doxygenlayout version="1.0">
|
||||||
|
<!-- Generated by doxygen 1.8.7 -->
|
||||||
|
<!-- Navigation index tabs for HTML output -->
|
||||||
|
<navindex>
|
||||||
|
<tab type="mainpage" visible="yes" title=""/>
|
||||||
|
<tab type="pages" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="modules" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="namespaces" visible="yes" title="">
|
||||||
|
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="classes" visible="yes" title="">
|
||||||
|
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||||
|
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="files" visible="yes" title="">
|
||||||
|
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="globals" visible="yes" title="" intro=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="examples" visible="yes" title="" intro=""/>
|
||||||
|
</navindex>
|
||||||
|
|
||||||
|
<!-- Layout definition for a class page -->
|
||||||
|
<class>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||||
|
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||||
|
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||||
|
<memberdecl>
|
||||||
|
<nestedclasses visible="yes" title=""/>
|
||||||
|
<publictypes title=""/>
|
||||||
|
<services title=""/>
|
||||||
|
<interfaces title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicmethods title=""/>
|
||||||
|
<publicstaticmethods title=""/>
|
||||||
|
<publicattributes title=""/>
|
||||||
|
<publicstaticattributes title=""/>
|
||||||
|
<protectedtypes title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<protectedmethods title=""/>
|
||||||
|
<protectedstaticmethods title=""/>
|
||||||
|
<protectedattributes title=""/>
|
||||||
|
<protectedstaticattributes title=""/>
|
||||||
|
<packagetypes title=""/>
|
||||||
|
<packagemethods title=""/>
|
||||||
|
<packagestaticmethods title=""/>
|
||||||
|
<packageattributes title=""/>
|
||||||
|
<packagestaticattributes title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<privatetypes title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<privatemethods title=""/>
|
||||||
|
<privatestaticmethods title=""/>
|
||||||
|
<privateattributes title=""/>
|
||||||
|
<privatestaticattributes title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
<related title="" subtitle=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title=""/>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<services title=""/>
|
||||||
|
<interfaces title=""/>
|
||||||
|
<constructors title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<related title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<allmemberslink visible="yes"/>
|
||||||
|
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
<!-- Layout definition for a namespace page -->
|
||||||
|
<namespace>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<memberdecl>
|
||||||
|
<nestednamespaces visible="yes" title=""/>
|
||||||
|
<constantgroups visible="yes" title=""/>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title=""/>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</namespace>
|
||||||
|
|
||||||
|
<!-- Layout definition for a file page -->
|
||||||
|
<file>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||||
|
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||||
|
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||||
|
<sourcelink visible="yes"/>
|
||||||
|
<memberdecl>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<namespaces visible="yes" title=""/>
|
||||||
|
<constantgroups visible="yes" title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title=""/>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection/>
|
||||||
|
</file>
|
||||||
|
|
||||||
|
<!-- Layout definition for a group page -->
|
||||||
|
<group>
|
||||||
|
<detaileddescription title=""/>
|
||||||
|
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||||
|
<memberdecl>
|
||||||
|
<nestedgroups visible="yes" title=""/>
|
||||||
|
<dirs visible="yes" title=""/>
|
||||||
|
<files visible="yes" title=""/>
|
||||||
|
<namespaces visible="yes" title=""/>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<enumvalues title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<memberdef>
|
||||||
|
<pagedocs/>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<enumvalues title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Layout definition for a directory page -->
|
||||||
|
<directory>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<directorygraph visible="yes"/>
|
||||||
|
<memberdecl>
|
||||||
|
<dirs visible="yes"/>
|
||||||
|
<files visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title=""/>
|
||||||
|
</directory>
|
||||||
|
</doxygenlayout>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The code generated by the protoc-gen-c code generator and by the
|
||||||
|
protoc-c compiler is owned by the owner of the input files used when
|
||||||
|
generating it. This code is not standalone and requires a support
|
||||||
|
library to be linked with it. This support library is covered by the
|
||||||
|
above license.
|
||||||
@@ -0,0 +1,382 @@
|
|||||||
|
bin_PROGRAMS =
|
||||||
|
check_PROGRAMS =
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
lib_LTLIBRARIES =
|
||||||
|
nobase_include_HEADERS =
|
||||||
|
pkgconfig_DATA =
|
||||||
|
BUILT_SOURCES =
|
||||||
|
TESTS =
|
||||||
|
CLEANFILES =
|
||||||
|
DISTCLEANFILES =
|
||||||
|
EXTRA_DIST =
|
||||||
|
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
EXTRA_DIST += LICENSE
|
||||||
|
EXTRA_DIST += README.md
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-include $(top_builddir)/config.h \
|
||||||
|
-I${top_srcdir}/protobuf-c \
|
||||||
|
-I${top_builddir} \
|
||||||
|
-I${top_srcdir}
|
||||||
|
AM_CFLAGS = ${my_CFLAGS}
|
||||||
|
AM_LDFLAGS =
|
||||||
|
|
||||||
|
# code coverage
|
||||||
|
|
||||||
|
AM_CFLAGS += ${CODE_COVERAGE_CFLAGS}
|
||||||
|
AM_LDFLAGS += ${CODE_COVERAGE_LDFLAGS}
|
||||||
|
CODE_COVERAGE_LCOV_OPTIONS = --no-external
|
||||||
|
CODE_COVERAGE_IGNORE_PATTERN = "$(abs_top_builddir)/t/*"
|
||||||
|
@CODE_COVERAGE_RULES@
|
||||||
|
|
||||||
|
#
|
||||||
|
# libprotobuf-c
|
||||||
|
#
|
||||||
|
|
||||||
|
LIBPROTOBUF_C_CURRENT=1
|
||||||
|
LIBPROTOBUF_C_REVISION=0
|
||||||
|
LIBPROTOBUF_C_AGE=0
|
||||||
|
|
||||||
|
lib_LTLIBRARIES += \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
|
||||||
|
nobase_include_HEADERS += \
|
||||||
|
protobuf-c/protobuf-c.h \
|
||||||
|
protobuf-c/protobuf-c.proto
|
||||||
|
|
||||||
|
protobuf_c_libprotobuf_c_la_SOURCES = \
|
||||||
|
protobuf-c/protobuf-c.c \
|
||||||
|
protobuf-c/protobuf-c.h
|
||||||
|
|
||||||
|
protobuf_c_libprotobuf_c_la_LDFLAGS = $(AM_LDFLAGS) \
|
||||||
|
-version-info $(LIBPROTOBUF_C_CURRENT):$(LIBPROTOBUF_C_REVISION):$(LIBPROTOBUF_C_AGE) \
|
||||||
|
-no-undefined
|
||||||
|
|
||||||
|
if HAVE_LD_VERSION_SCRIPT
|
||||||
|
protobuf_c_libprotobuf_c_la_LDFLAGS += \
|
||||||
|
-Wl,--version-script=$(top_srcdir)/protobuf-c/libprotobuf-c.sym
|
||||||
|
else
|
||||||
|
protobuf_c_libprotobuf_c_la_LDFLAGS += \
|
||||||
|
-export-symbols-regex "^(protobuf_c_[a-z].*)"
|
||||||
|
endif
|
||||||
|
EXTRA_DIST += protobuf-c/libprotobuf-c.sym
|
||||||
|
|
||||||
|
pkgconfig_DATA += protobuf-c/libprotobuf-c.pc
|
||||||
|
CLEANFILES += protobuf-c/libprotobuf-c.pc
|
||||||
|
EXTRA_DIST += protobuf-c/libprotobuf-c.pc.in
|
||||||
|
|
||||||
|
#
|
||||||
|
# protoc-gen-c
|
||||||
|
#
|
||||||
|
|
||||||
|
if BUILD_COMPILER
|
||||||
|
|
||||||
|
bin_PROGRAMS += protoc-c/protoc-gen-c
|
||||||
|
protoc_c_protoc_gen_c_SOURCES = \
|
||||||
|
protoc-c/c_bytes_field.cc \
|
||||||
|
protoc-c/c_bytes_field.h \
|
||||||
|
protoc-c/c_enum.cc \
|
||||||
|
protoc-c/c_enum.h \
|
||||||
|
protoc-c/c_enum_field.cc \
|
||||||
|
protoc-c/c_enum_field.h \
|
||||||
|
protoc-c/c_extension.cc \
|
||||||
|
protoc-c/c_extension.h \
|
||||||
|
protoc-c/c_field.cc \
|
||||||
|
protoc-c/c_field.h \
|
||||||
|
protoc-c/c_file.cc \
|
||||||
|
protoc-c/c_file.h \
|
||||||
|
protoc-c/c_generator.cc \
|
||||||
|
protoc-c/c_generator.h \
|
||||||
|
protoc-c/c_helpers.cc \
|
||||||
|
protoc-c/c_helpers.h \
|
||||||
|
protoc-c/c_message.cc \
|
||||||
|
protoc-c/c_message.h \
|
||||||
|
protoc-c/c_message_field.cc \
|
||||||
|
protoc-c/c_message_field.h \
|
||||||
|
protoc-c/c_primitive_field.cc \
|
||||||
|
protoc-c/c_primitive_field.h \
|
||||||
|
protoc-c/c_service.cc \
|
||||||
|
protoc-c/c_service.h \
|
||||||
|
protoc-c/c_string_field.cc \
|
||||||
|
protoc-c/c_string_field.h \
|
||||||
|
protobuf-c/protobuf-c.pb.cc \
|
||||||
|
protobuf-c/protobuf-c.pb.h \
|
||||||
|
protoc-c/main.cc
|
||||||
|
protoc_c_protoc_gen_c_CXXFLAGS = \
|
||||||
|
$(AM_CXXFLAGS) \
|
||||||
|
$(protobuf_CFLAGS)
|
||||||
|
protoc_c_protoc_gen_c_LDADD = \
|
||||||
|
$(protobuf_LIBS) \
|
||||||
|
-lprotoc
|
||||||
|
|
||||||
|
protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h: @PROTOC@ $(top_srcdir)/protobuf-c/protobuf-c.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ -I$(top_srcdir) --cpp_out=$(top_builddir) $(top_srcdir)/protobuf-c/protobuf-c.proto
|
||||||
|
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
protobuf-c/protobuf-c.pb.cc \
|
||||||
|
protobuf-c/protobuf-c.pb.h
|
||||||
|
#
|
||||||
|
# protoc-c compat link
|
||||||
|
#
|
||||||
|
|
||||||
|
install-exec-hook:
|
||||||
|
rm -f $(DESTDIR)$(bindir)/protoc-c
|
||||||
|
ln -s protoc-gen-c $(DESTDIR)$(bindir)/protoc-c
|
||||||
|
|
||||||
|
#
|
||||||
|
# protobuf-c tests
|
||||||
|
#
|
||||||
|
|
||||||
|
if CROSS_COMPILING
|
||||||
|
#
|
||||||
|
# skip tests on cross-compiling
|
||||||
|
#
|
||||||
|
else
|
||||||
|
|
||||||
|
LOG_COMPILER = $(VALGRIND)
|
||||||
|
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/generated-code/test-generated-code \
|
||||||
|
t/generated-code2/test-generated-code2 \
|
||||||
|
t/version/version
|
||||||
|
|
||||||
|
TESTS += \
|
||||||
|
t/generated-code/test-generated-code \
|
||||||
|
t/generated-code2/test-generated-code2 \
|
||||||
|
t/version/version
|
||||||
|
|
||||||
|
t_generated_code_test_generated_code_SOURCES = \
|
||||||
|
t/generated-code/test-generated-code.c \
|
||||||
|
t/test.pb-c.c
|
||||||
|
t_generated_code_test_generated_code_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
|
||||||
|
t_generated_code2_test_generated_code2_SOURCES = \
|
||||||
|
t/generated-code2/test-generated-code2.c \
|
||||||
|
t/test-full.pb-c.c \
|
||||||
|
t/test-optimized.pb-c.c
|
||||||
|
t_generated_code2_test_generated_code2_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
|
||||||
|
noinst_PROGRAMS += \
|
||||||
|
t/generated-code2/cxx-generate-packed-data
|
||||||
|
|
||||||
|
t_generated_code2_cxx_generate_packed_data_SOURCES = \
|
||||||
|
t/generated-code2/cxx-generate-packed-data.cc \
|
||||||
|
t/test-full.pb.cc \
|
||||||
|
protobuf-c/protobuf-c.pb.cc
|
||||||
|
$(t_generated_code2_cxx_generate_packed_data_OBJECTS): t/test-full.pb.h
|
||||||
|
t_generated_code2_cxx_generate_packed_data_CXXFLAGS = \
|
||||||
|
$(AM_CXXFLAGS) \
|
||||||
|
$(protobuf_CFLAGS)
|
||||||
|
t_generated_code2_cxx_generate_packed_data_LDADD = \
|
||||||
|
$(protobuf_LIBS)
|
||||||
|
|
||||||
|
t/test.pb-c.c t/test.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test.proto
|
||||||
|
|
||||||
|
t/test-optimized.pb-c.c t/test-optimized.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-optimized.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-optimized.proto
|
||||||
|
|
||||||
|
t/test-full.pb-c.c t/test-full.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-full.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-full.proto
|
||||||
|
|
||||||
|
t/test-full.pb.cc t/test-full.pb.h: @PROTOC@ $(top_srcdir)/t/test-full.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ -I$(top_srcdir) --cpp_out=$(top_builddir) $(top_srcdir)/t/test-full.proto
|
||||||
|
|
||||||
|
t/generated-code2/test-full-cxx-output.inc: t/generated-code2/cxx-generate-packed-data$(EXEEXT)
|
||||||
|
$(AM_V_GEN)$(top_builddir)/t/generated-code2/cxx-generate-packed-data$(EXEEXT) > $(top_builddir)/t/generated-code2/test-full-cxx-output.inc
|
||||||
|
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/test.pb-c.c t/test.pb-c.h \
|
||||||
|
t/test-full.pb-c.c t/test-full.pb-c.h \
|
||||||
|
t/test-optimized.pb-c.c t/test-optimized.pb-c.h \
|
||||||
|
t/test-full.pb.cc t/test-full.pb.h \
|
||||||
|
t/generated-code2/test-full-cxx-output.inc
|
||||||
|
|
||||||
|
if BUILD_PROTO3
|
||||||
|
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/generated-code3/test-generated-code3
|
||||||
|
|
||||||
|
TESTS += \
|
||||||
|
t/generated-code3/test-generated-code3
|
||||||
|
|
||||||
|
t_generated_code3_test_generated_code3_CPPFLAGS = \
|
||||||
|
-DPROTO3
|
||||||
|
|
||||||
|
t_generated_code3_test_generated_code3_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
|
||||||
|
t_generated_code3_test_generated_code3_SOURCES = \
|
||||||
|
t/generated-code/test-generated-code.c \
|
||||||
|
t/test-proto3.pb-c.c
|
||||||
|
|
||||||
|
t/test-proto3.pb-c.c t/test-proto3.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-proto3.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-proto3.proto
|
||||||
|
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/test-proto3.pb-c.c t/test-proto3.pb-c.h
|
||||||
|
|
||||||
|
endif # BUILD_PROTO3
|
||||||
|
|
||||||
|
t_version_version_SOURCES = \
|
||||||
|
t/version/version.c
|
||||||
|
t_version_version_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
|
||||||
|
# Issue #204
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue204/issue204
|
||||||
|
TESTS += \
|
||||||
|
t/issue204/issue204
|
||||||
|
t_issue204_issue204_SOURCES = \
|
||||||
|
t/issue204/issue204.c \
|
||||||
|
t/issue204/issue204.pb-c.c
|
||||||
|
t_issue204_issue204_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue204/issue204.pb-c.c t/issue204/issue204.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue204/issue204.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue204/issue204.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue204/issue204.pb-c.c t/issue204/issue204.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue204/issue204.proto
|
||||||
|
|
||||||
|
# Issue #220
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue220/issue220
|
||||||
|
TESTS += \
|
||||||
|
t/issue220/issue220
|
||||||
|
t_issue220_issue220_SOURCES = \
|
||||||
|
t/issue220/issue220.c \
|
||||||
|
t/issue220/issue220.pb-c.c
|
||||||
|
t_issue220_issue220_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue220/issue220.pb-c.c t/issue220/issue220.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue220/issue220.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue220/issue220.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue220/issue220.pb-c.c t/issue220/issue220.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue220/issue220.proto
|
||||||
|
|
||||||
|
# Issue #251
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue251/issue251
|
||||||
|
TESTS += \
|
||||||
|
t/issue251/issue251
|
||||||
|
t_issue251_issue251_SOURCES = \
|
||||||
|
t/issue251/issue251.c \
|
||||||
|
t/issue251/issue251.pb-c.c
|
||||||
|
t_issue251_issue251_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue251/issue251.pb-c.c t/issue251/issue251.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue251/issue251.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue251/issue251.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue251/issue251.pb-c.c t/issue251/issue251.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue251/issue251.proto
|
||||||
|
|
||||||
|
# Issue #330
|
||||||
|
if BUILD_PROTO3
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue330/issue330
|
||||||
|
TESTS += \
|
||||||
|
t/issue330/issue330
|
||||||
|
t_issue330_issue330_SOURCES = \
|
||||||
|
t/issue330/issue330.c \
|
||||||
|
t/issue330/issue330.pb-c.c
|
||||||
|
t_issue330_issue330_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue330/issue330.pb-c.c t/issue330/issue330.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue330/issue330.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue330/issue330.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue330/issue330.pb-c.c t/issue330/issue330.pb-c.h
|
||||||
|
|
||||||
|
t_issue330_issue330_SOURCES += \
|
||||||
|
t/issue389/issue389.pb-c.c # Tack onto issue330 since there is no need for a separate binary here
|
||||||
|
t/issue389/issue389.pb-c.c t/issue389/issue389.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue389/issue389.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue389/issue389.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue389/issue389.pb-c.c t/issue389/issue389.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue389/issue389.proto
|
||||||
|
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue440/issue440
|
||||||
|
TESTS += \
|
||||||
|
t/issue440/issue440
|
||||||
|
t_issue440_issue440_SOURCES = \
|
||||||
|
t/issue440/issue440.c \
|
||||||
|
t/issue440/issue440.pb-c.c
|
||||||
|
t_issue440_issue440_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue440/issue440.pb-c.c t/issue440/issue440.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue440/issue440.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue440/issue440.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue440/issue440.pb-c.c t/issue440/issue440.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue440/issue440.proto
|
||||||
|
endif # BUILD_PROTO3
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue330/issue330.proto
|
||||||
|
|
||||||
|
# Issue #375
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue375/issue375
|
||||||
|
TESTS += \
|
||||||
|
t/issue375/issue375
|
||||||
|
t_issue375_issue375_SOURCES = \
|
||||||
|
t/issue375/issue375.c \
|
||||||
|
t/issue375/issue375.pb-c.c
|
||||||
|
t_issue375_issue375_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue375/issue375.pb-c.c t/issue375/issue375.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue375/issue375.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue375/issue375.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue375/issue375.pb-c.c t/issue375/issue375.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue375/issue375.proto
|
||||||
|
|
||||||
|
endif # CROSS_COMPILING
|
||||||
|
|
||||||
|
endif # BUILD_COMPILER
|
||||||
|
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/test.proto \
|
||||||
|
t/test-full.proto \
|
||||||
|
t/test-optimized.proto \
|
||||||
|
t/test-proto3.proto \
|
||||||
|
t/generated-code2/common-test-arrays.h
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
CLEANFILES += $(BUILT_SOURCES)
|
||||||
|
|
||||||
|
dist-hook:
|
||||||
|
rm -f `find $(distdir) -name '*.pb-c.[ch]' -o -name '*.pb.cc' -o -name '*.pb.h'`
|
||||||
|
|
||||||
|
install-data-hook:
|
||||||
|
$(MKDIR_P) $(DESTDIR)$(includedir)/google/protobuf-c
|
||||||
|
cd $(DESTDIR)$(includedir)/google/protobuf-c && rm -f protobuf-c.h
|
||||||
|
cd $(DESTDIR)$(includedir)/google/protobuf-c && $(LN_S) ../../protobuf-c/protobuf-c.h protobuf-c.h
|
||||||
|
|
||||||
|
#
|
||||||
|
# documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
if HAVE_DOXYGEN
|
||||||
|
stamp-html: $(DOXYGEN_INPUT_FILES) $(top_builddir)/Doxyfile $(top_srcdir)/DoxygenLayout.xml $(include_HEADERS) $(nobase_include_HEADERS)
|
||||||
|
$(AM_V_GEN) $(DOXYGEN)
|
||||||
|
@touch $@
|
||||||
|
html-local: stamp-html
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -rf $(top_builddir)/html $(top_builddir)/stamp-html
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXTRA_DIST += Doxyfile.in
|
||||||
|
EXTRA_DIST += DoxygenLayout.xml
|
||||||
|
EXTRA_DIST += build-cmake/CMakeLists.txt
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
[](https://github.com/protobuf-c/protobuf-c/actions) [](https://coveralls.io/r/protobuf-c/protobuf-c)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is `protobuf-c`, a C implementation of the [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) data serialization format. It includes `libprotobuf-c`, a pure C library that implements protobuf encoding and decoding, and `protoc-c`, a code generator that converts Protocol Buffer `.proto` files to C descriptor code, based on the original `protoc`. `protobuf-c` formerly included an RPC implementation; that code has been split out into the [protobuf-c-rpc](https://github.com/protobuf-c/protobuf-c-rpc) project.
|
||||||
|
|
||||||
|
`protobuf-c` was originally written by Dave Benson and maintained by him through version 0.15 but is now being maintained by a new team. Thanks, Dave!
|
||||||
|
|
||||||
|
## Mailing list
|
||||||
|
|
||||||
|
`protobuf-c`'s mailing list is hosted on a [Google Groups forum](https://groups.google.com/forum/#!forum/protobuf-c). Subscribe by sending an email to [protobuf-c+subscribe@googlegroups.com](mailto:protobuf-c+subscribe@googlegroups.com).
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
`protobuf-c` requires a C compiler, a C++ compiler, [protobuf](https://github.com/google/protobuf), and `pkg-config` to be installed.
|
||||||
|
|
||||||
|
./configure && make && make install
|
||||||
|
|
||||||
|
If building from a git checkout, the `autotools` (`autoconf`, `automake`, `libtool`) must also be installed, and the build system must be generated by running the `autogen.sh` script.
|
||||||
|
|
||||||
|
./autogen.sh && ./configure && make && make install
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
If you want to execute test cases individually, please run the following command after running `./configure` once:
|
||||||
|
|
||||||
|
make check
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
See the [online Doxygen documentation here](https://protobuf-c.github.io/protobuf-c) or [the Wiki](https://github.com/protobuf-c/protobuf-c/wiki) for a detailed reference. The Doxygen documentation can be built from the source tree by running:
|
||||||
|
|
||||||
|
make html
|
||||||
|
|
||||||
|
## Synopsis
|
||||||
|
|
||||||
|
Use the `protoc` command to generate `.pb-c.c` and `.pb-c.h` output files from your `.proto` input file. The `--c_out` options instructs `protoc` to use the protobuf-c plugin.
|
||||||
|
|
||||||
|
protoc --c_out=. example.proto
|
||||||
|
|
||||||
|
Include the `.pb-c.h` file from your C source code.
|
||||||
|
|
||||||
|
#include "example.pb-c.h"
|
||||||
|
|
||||||
|
Compile your C source code together with the `.pb-c.c` file. Add the output of the following command to your compile flags.
|
||||||
|
|
||||||
|
pkg-config --cflags 'libprotobuf-c >= 1.0.0'
|
||||||
|
|
||||||
|
Link against the `libprotobuf-c` support library. Add the output of the following command to your link flags.
|
||||||
|
|
||||||
|
pkg-config --libs 'libprotobuf-c >= 1.0.0'
|
||||||
|
|
||||||
|
If using autotools, the `PKG_CHECK_MODULES` macro can be used to detect the presence of `libprotobuf-c`. Add the following line to your `configure.ac` file:
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([PROTOBUF_C], [libprotobuf-c >= 1.0.0])
|
||||||
|
|
||||||
|
This will place compiler flags in the `PROTOBUF_C_CFLAGS` variable and linker flags in the `PROTOBUF_C_LDFLAGS` variable. Read [more information here](https://autotools.io/pkgconfig/pkg_check_modules.html) about the `PKG_CHECK_MODULES` macro.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
`protobuf-c` follows the [Semantic Versioning Specification](http://semver.org/) as of version 1.0.0.
|
||||||
|
|
||||||
|
Note that as of version of 1.0.0, the header files generated by the `protoc-c` compiler contain version guards to prevent incompatibilities due to version skew between the `.pb-c.h` files generated by `protoc-c` and the public `protobuf-c.h` include file supplied by the `libprotobuf-c` support library. While we will try not to make changes to `protobuf-c` that will require triggering the version guard often, such as releasing a new major version of `protobuf-c`, this cannot be guaranteed. Thus, it's a good idea to recompile your `.pb-c.c` and `.pb-c.h` files from their source `.proto` files with `protoc-c` as part of your build system, with proper source file dependency tracking, rather than shipping potentially stale `.pb-c.c` and `.pb-c.h` files that may not be compatible with the `libprotobuf-c` headers installed on the system in project artifacts like repositories and release tarballs. (Note that the output of the `protoc-c` code generator is not standalone, as the output of some other tools that generate C code is, such as `flex` and `bison`.)
|
||||||
|
|
||||||
|
Major API/ABI changes may occur between major version releases, by definition. It is not recommended to export the symbols in the code generated by `protoc-c` in a stable library interface, as this will embed the `protobuf-c` ABI into your library's ABI. Nor is it recommended to install generated `.pb-c.h` files into a public header file include path as part of a library API, as this will tie clients of your library's API to particular versions of `libprotobuf-c`.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Please send patches to the [protobuf-c mailing list](https://groups.google.com/forum/#!forum/protobuf-c) or by opening a GitHub pull request.
|
||||||
|
|
||||||
|
The most recently released `protobuf-c` version is kept on the `master` branch, while the `next` branch is used for commits targeted at the next release. Please base patches and pull requests against the `next` branch, not the `master` branch.
|
||||||
|
|
||||||
|
Copyright to all contributions are retained by the original author, but must be licensed under the terms of the [BSD-2-Clause](http://opensource.org/licenses/BSD-2-Clause) license. Please add a `Signed-off-by` header to your commit message (`git commit -s`) to indicate that you are licensing your contribution under these terms.
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
----------------------
|
||||||
|
--- IMPORTANT TODO ---
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
--- NEEDED TESTS ---
|
||||||
|
--------------------
|
||||||
|
- test:
|
||||||
|
- service method lookups
|
||||||
|
- out-of-order fields in messages (ie if the number isn't ascending)
|
||||||
|
- gaps in numbers: check that the number of ranges is correct
|
||||||
|
- default values
|
||||||
|
- message unpack alloc failures when allocating new slab
|
||||||
|
- message unpack alloc failures when allocating unknown field buffers
|
||||||
|
- packed message corruption.
|
||||||
|
- meta-todo: get a list of all the unpack errors together to check off
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
--- DOCUMENTATION ---
|
||||||
|
---------------------
|
||||||
|
Document:
|
||||||
|
- services
|
||||||
|
- check over documentation again
|
||||||
|
|
||||||
|
--------------------------
|
||||||
|
--- LOW PRIORITY STUFF ---
|
||||||
|
--------------------------
|
||||||
|
- support Group (whatever it is)
|
||||||
|
- proper support for extensions
|
||||||
|
- slot for ranges in descriptor
|
||||||
|
- extends is implemented as c-style function
|
||||||
|
whose name is built from the package, the base message type-name
|
||||||
|
and the member. which takes the base message and returns the
|
||||||
|
value, if it is found in "unknown_values".
|
||||||
|
boolean package__extension_member_name__get(Message *message,
|
||||||
|
type *out);
|
||||||
|
void package__extension_member_name__set_raw(type in,
|
||||||
|
ProtobufCUnknownValue *to_init);
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
--- EXTREMELY LOW PRIORITY STUFF ---
|
||||||
|
------------------------------------
|
||||||
|
- stop using qsort in the code generator: find some c++ish way to do it
|
||||||
|
|
||||||
|
----------------------------------------------
|
||||||
|
--- ISSUES WE ARE PROBABLY GOING TO IGNORE ---
|
||||||
|
----------------------------------------------
|
||||||
|
- strings may not contain NULs
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
--- IDEAS TO CONSIDER ---
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
- optimization: structures without repeated members could skip
|
||||||
|
the ScannedMember phase
|
||||||
|
|
||||||
|
- optimization: a way to ignore unknown-fields when unpacking
|
||||||
|
|
||||||
|
- optimization: certain functions are not well setup for WORDSIZE==64;
|
||||||
|
especially the int64 routines are inefficient that way.
|
||||||
|
The best might be an internal #define WORDSIZE (sizeof(long)*8)"
|
||||||
|
except w/ a real constant there, one that the preprocessor can use.
|
||||||
|
I think the functions in protobuf-c.c are already tagged.
|
||||||
|
|
||||||
|
- lifetime functions for messages:
|
||||||
|
message__new()
|
||||||
|
return a new message using an allocator with standard allocation policy
|
||||||
|
message__unpack_onto(...)
|
||||||
|
unpack onto an initialized message
|
||||||
|
message__clear(...)
|
||||||
|
clears all allocations, does not free the message itself
|
||||||
|
message__free(...)
|
||||||
|
free the message.
|
||||||
|
[yeah, right: after typing it out, i see it's way too complicated]
|
||||||
|
|
||||||
|
- switching to pure C.
|
||||||
|
- Rewrite the code-generator in C, including the parser.
|
||||||
|
- This would have the huge advantage that we could use ".proto" files
|
||||||
|
directly, instead of having to invoke the compilers.
|
||||||
|
- keep in a separate c file for static linking optimziation purposes
|
||||||
|
- need alignment tests
|
||||||
|
- the CAVEATS should discuss our structure-packing assumptions
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
exec autoreconf -fvi
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!CMakeLists.txt
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
SET(PACKAGE protobuf-c)
|
||||||
|
SET(PACKAGE_NAME protobuf-c)
|
||||||
|
SET(PACKAGE_VERSION 1.4.1)
|
||||||
|
SET(PACKAGE_URL https://github.com/protobuf-c/protobuf-c)
|
||||||
|
SET(PACKAGE_DESCRIPTION "Protocol Buffers implementation in C")
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.10 FATAL_ERROR)
|
||||||
|
|
||||||
|
PROJECT(protobuf-c)
|
||||||
|
|
||||||
|
#options
|
||||||
|
option(BUILD_PROTO3 "BUILD_PROTO3" ON)
|
||||||
|
option(BUILD_PROTOC "Build protoc-gen-c" ON)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
option(BUILD_TESTS "Build tests" ON)
|
||||||
|
else()
|
||||||
|
option(BUILD_TESTS "Build tests" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
INCLUDE(TestBigEndian)
|
||||||
|
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
|
||||||
|
|
||||||
|
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||||
|
ADD_DEFINITIONS(-DPACKAGE_VERSION="${PACKAGE_VERSION}")
|
||||||
|
ADD_DEFINITIONS(-DPACKAGE_STRING="${PACKAGE_STRING}")
|
||||||
|
if (${WORDS_BIGENDIAN})
|
||||||
|
ADD_DEFINITIONS(-DWORDS_BIGENDIAN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
IF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
ADD_DEFINITIONS(-DPROTOBUF_C_USE_SHARED_LIB)
|
||||||
|
ENDIF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# using Visual Studio C++
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4267 /wd4244")
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4244")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
get_filename_component(MAIN_DIR ${CMAKE_CURRENT_SOURCE_DIR} PATH)
|
||||||
|
SET(TEST_DIR ${MAIN_DIR}/t)
|
||||||
|
|
||||||
|
MESSAGE(${MAIN_DIR})
|
||||||
|
|
||||||
|
SET (PC_SOURCES
|
||||||
|
${MAIN_DIR}/protobuf-c/protobuf-c.c
|
||||||
|
${MAIN_DIR}/protobuf-c/protobuf-c.h)
|
||||||
|
|
||||||
|
ADD_LIBRARY(protobuf-c ${PC_SOURCES})
|
||||||
|
set_target_properties(protobuf-c PROPERTIES COMPILE_PDB_NAME protobuf-c)
|
||||||
|
IF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(protobuf-c PRIVATE -DPROTOBUF_C_EXPORT)
|
||||||
|
ENDIF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${MAIN_DIR})
|
||||||
|
INCLUDE_DIRECTORIES(${MAIN_DIR}/protobuf-c)
|
||||||
|
|
||||||
|
IF(BUILD_PROTOC)
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}) # for generated files
|
||||||
|
|
||||||
|
if (MSVC AND NOT BUILD_SHARED_LIBS)
|
||||||
|
SET(Protobuf_USE_STATIC_LIBS ON)
|
||||||
|
endif (MSVC AND NOT BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
FIND_PACKAGE(Protobuf REQUIRED)
|
||||||
|
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
|
||||||
|
|
||||||
|
if (BUILD_PROTO3)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_PROTO3)
|
||||||
|
endif()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
if (MSVC AND NOT BUILD_SHARED_LIBS)
|
||||||
|
# In case we are building static libraries, link also the runtime library statically
|
||||||
|
# so that MSVCR*.DLL is not required at runtime.
|
||||||
|
# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
|
||||||
|
# This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd
|
||||||
|
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
|
||||||
|
foreach(flag_var
|
||||||
|
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_C_FLAGS_MINSIZEREL CMAKE_FLAGS_RELWITHDEBINFO)
|
||||||
|
if(${flag_var} MATCHES "/MD")
|
||||||
|
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||||
|
endif(${flag_var} MATCHES "/MD")
|
||||||
|
endforeach(flag_var)
|
||||||
|
endif (MSVC AND NOT BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
IF(BUILD_PROTOC)
|
||||||
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
|
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
ADD_CUSTOM_COMMAND(OUTPUT protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h
|
||||||
|
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
||||||
|
ARGS --cpp_out ${CMAKE_BINARY_DIR} -I${MAIN_DIR} ${MAIN_DIR}/protobuf-c/protobuf-c.proto)
|
||||||
|
FILE(GLOB PROTOC_GEN_C_SRC ${MAIN_DIR}/protoc-c/*.h ${MAIN_DIR}/protoc-c/*.cc )
|
||||||
|
ADD_EXECUTABLE(protoc-gen-c ${PROTOC_GEN_C_SRC} protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h)
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(protoc-gen-c ${PROTOBUF_PROTOC_LIBRARY} ${PROTOBUF_LIBRARY})
|
||||||
|
|
||||||
|
IF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(protoc-gen-c PRIVATE -DPROTOBUF_USE_DLLS)
|
||||||
|
GET_FILENAME_COMPONENT(PROTOBUF_DLL_DIR ${PROTOBUF_PROTOC_EXECUTABLE} DIRECTORY)
|
||||||
|
FILE(GLOB PROTOBUF_DLLS ${PROTOBUF_DLL_DIR}/*.dll)
|
||||||
|
FILE(COPY ${PROTOBUF_DLLS} DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
ENDIF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
IF(CMAKE_HOST_UNIX)
|
||||||
|
ADD_CUSTOM_COMMAND(TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
COMMAND ln -sf protoc-gen-c protoc-c
|
||||||
|
DEPENDS protoc-gen-c)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FUNCTION(GENERATE_TEST_SOURCES PROTO_FILE SRC HDR)
|
||||||
|
ADD_CUSTOM_COMMAND(OUTPUT ${SRC} ${HDR}
|
||||||
|
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
||||||
|
ARGS --plugin=$<TARGET_FILE:protoc-gen-c> -I${MAIN_DIR} ${PROTO_FILE} --c_out=${CMAKE_BINARY_DIR}
|
||||||
|
DEPENDS protoc-gen-c)
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
|
||||||
|
IF(BUILD_TESTS)
|
||||||
|
ENABLE_TESTING()
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/test.proto t/test.pb-c.c t/test.pb-c.h)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(test-generated-code ${TEST_DIR}/generated-code/test-generated-code.c t/test.pb-c.c t/test.pb-c.h )
|
||||||
|
TARGET_LINK_LIBRARIES(test-generated-code protobuf-c)
|
||||||
|
|
||||||
|
|
||||||
|
ADD_CUSTOM_COMMAND(OUTPUT t/test-full.pb.cc t/test-full.pb.h
|
||||||
|
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
||||||
|
ARGS --cpp_out ${CMAKE_BINARY_DIR} -I${MAIN_DIR} ${TEST_DIR}/test-full.proto)
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/test-full.proto t/test-full.pb-c.c t/test-full.pb-c.h)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(cxx-generate-packed-data ${TEST_DIR}/generated-code2/cxx-generate-packed-data.cc t/test-full.pb.h t/test-full.pb.cc protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h)
|
||||||
|
TARGET_LINK_LIBRARIES(cxx-generate-packed-data ${PROTOBUF_LIBRARY})
|
||||||
|
IF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(cxx-generate-packed-data PRIVATE -DPROTOBUF_USE_DLLS)
|
||||||
|
ENDIF (MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/t/generated-code2)
|
||||||
|
ADD_CUSTOM_COMMAND(OUTPUT t/generated-code2/test-full-cxx-output.inc
|
||||||
|
COMMAND ${CMAKE_BINARY_DIR}/cxx-generate-packed-data ">t/generated-code2/test-full-cxx-output.inc"
|
||||||
|
DEPENDS cxx-generate-packed-data
|
||||||
|
)
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/test-optimized.proto t/test-optimized.pb-c.c t/test-optimized.pb-c.h)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(test-generated-code2 ${TEST_DIR}/generated-code2/test-generated-code2.c t/generated-code2/test-full-cxx-output.inc t/test-full.pb-c.h t/test-full.pb-c.c t/test-optimized.pb-c.h t/test-optimized.pb-c.c)
|
||||||
|
TARGET_LINK_LIBRARIES(test-generated-code2 protobuf-c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/issue220/issue220.proto t/issue220/issue220.pb-c.c t/issue220/issue220.pb-c.h)
|
||||||
|
ADD_EXECUTABLE(test-issue220 ${TEST_DIR}/issue220/issue220.c t/issue220/issue220.pb-c.c t/issue220/issue220.pb-c.h)
|
||||||
|
TARGET_LINK_LIBRARIES(test-issue220 protobuf-c)
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/issue251/issue251.proto t/issue251/issue251.pb-c.c t/issue251/issue251.pb-c.h)
|
||||||
|
ADD_EXECUTABLE(test-issue251 ${TEST_DIR}/issue251/issue251.c t/issue251/issue251.pb-c.c t/issue251/issue251.pb-c.h)
|
||||||
|
TARGET_LINK_LIBRARIES(test-issue251 protobuf-c)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(test-version ${TEST_DIR}/version/version.c)
|
||||||
|
TARGET_LINK_LIBRARIES(test-version protobuf-c)
|
||||||
|
|
||||||
|
GENERATE_TEST_SOURCES(${TEST_DIR}/test-proto3.proto t/test-proto3.pb-c.c t/test-proto3.pb-c.h)
|
||||||
|
ADD_EXECUTABLE(test-generated-code3 ${TEST_DIR}/generated-code/test-generated-code.c t/test-proto3.pb-c.c t/test-proto3.pb-c.h)
|
||||||
|
TARGET_COMPILE_DEFINITIONS(test-generated-code3 PUBLIC -DPROTO3)
|
||||||
|
TARGET_LINK_LIBRARIES(test-generated-code3 protobuf-c)
|
||||||
|
|
||||||
|
ENDIF() # BUILD_TESTS
|
||||||
|
|
||||||
|
# https://github.com/protocolbuffers/protobuf/issues/5107
|
||||||
|
IF(CMAKE_HOST_UNIX)
|
||||||
|
FIND_PACKAGE(Threads REQUIRED)
|
||||||
|
TARGET_LINK_LIBRARIES(protoc-gen-c ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
IF(BUILD_TESTS)
|
||||||
|
TARGET_LINK_LIBRARIES(cxx-generate-packed-data ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
INSTALL(TARGETS protoc-gen-c RUNTIME DESTINATION bin)
|
||||||
|
ENDIF() # BUILD_PROTOC
|
||||||
|
|
||||||
|
INSTALL(TARGETS protobuf-c LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin)
|
||||||
|
INSTALL(FILES ${MAIN_DIR}/protobuf-c/protobuf-c.h ${MAIN_DIR}/protobuf-c/protobuf-c.proto DESTINATION include/protobuf-c)
|
||||||
|
INSTALL(FILES ${MAIN_DIR}/protobuf-c/protobuf-c.h DESTINATION include)
|
||||||
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/protobuf-c.pdb DESTINATION lib OPTIONAL)
|
||||||
|
|
||||||
|
IF(CMAKE_HOST_UNIX)
|
||||||
|
INSTALL(CODE "EXECUTE_PROCESS (COMMAND ln -sf protoc-gen-c protoc-c WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin)")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
INCLUDE(GNUInstallDirs)
|
||||||
|
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
|
SET(exec_prefix \${prefix})
|
||||||
|
SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
|
||||||
|
SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
|
||||||
|
SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
CONFIGURE_FILE(${MAIN_DIR}/protobuf-c/libprotobuf-c.pc.in libprotobuf-c.pc @ONLY)
|
||||||
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/libprotobuf-c.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
|
|
||||||
|
IF(BUILD_TESTS)
|
||||||
|
INCLUDE(Dart)
|
||||||
|
|
||||||
|
SET(DART_TESTING_TIMEOUT 5)
|
||||||
|
ADD_TEST(test-generated-code test-generated-code)
|
||||||
|
ADD_TEST(test-generated-code2 test-generated-code2)
|
||||||
|
ADD_TEST(test-generated-code3 test-generated-code3)
|
||||||
|
ADD_TEST(test-issue220 test-issue220)
|
||||||
|
ADD_TEST(test-issue251 test-issue251)
|
||||||
|
ADD_TEST(test-version test-version)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
INCLUDE(CPack)
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
AC_PREREQ(2.63)
|
||||||
|
|
||||||
|
AC_INIT([protobuf-c],
|
||||||
|
[1.4.1],
|
||||||
|
[https://github.com/protobuf-c/protobuf-c/issues],
|
||||||
|
[protobuf-c],
|
||||||
|
[https://github.com/protobuf-c/protobuf-c])
|
||||||
|
PACKAGE_DESCRIPTION="Protocol Buffers implementation in C"
|
||||||
|
AC_SUBST(PACKAGE_DESCRIPTION)
|
||||||
|
|
||||||
|
AC_CONFIG_SRCDIR([protobuf-c/protobuf-c.c])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules subdir-objects])
|
||||||
|
AC_PROG_CC_STDC
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MKDIR_P
|
||||||
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
AM_SILENT_RULES([yes])
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
AC_CONFIG_FILES([Makefile protobuf-c/libprotobuf-c.pc])
|
||||||
|
|
||||||
|
my_CFLAGS="\
|
||||||
|
-Wall \
|
||||||
|
-Wchar-subscripts \
|
||||||
|
-Wdeclaration-after-statement \
|
||||||
|
-Wformat-security \
|
||||||
|
-Wmissing-declarations \
|
||||||
|
-Wmissing-prototypes \
|
||||||
|
-Wnested-externs \
|
||||||
|
-Wpointer-arith \
|
||||||
|
-Wshadow \
|
||||||
|
-Wsign-compare \
|
||||||
|
-Wstrict-prototypes \
|
||||||
|
-Wtype-limits \
|
||||||
|
"
|
||||||
|
#AX_CHECK_COMPILE_FLAG(["-Wc90-c99-compat"],
|
||||||
|
# [my_CFLAGS="$my_CFLAGS -Wc90-c99-compat"])
|
||||||
|
AX_CHECK_COMPILE_FLAG(["-Wc99-c11-compat"],
|
||||||
|
[my_CFLAGS="$my_CFLAGS -Wc99-c11-compat"])
|
||||||
|
AX_CHECK_COMPILE_FLAG(["-Werror=incompatible-pointer-types"],
|
||||||
|
[my_CFLAGS="$my_CFLAGS -Werror=incompatible-pointer-types"])
|
||||||
|
AX_CHECK_COMPILE_FLAG(["-Werror=int-conversion"],
|
||||||
|
[my_CFLAGS="$my_CFLAGS -Werror=int-conversion"])
|
||||||
|
AX_CHECK_COMPILE_FLAG(["-Wnull-dereference"],
|
||||||
|
[my_CFLAGS="$my_CFLAGS -Wnull-dereference"])
|
||||||
|
AC_SUBST([my_CFLAGS])
|
||||||
|
|
||||||
|
AC_CHECK_PROGS([DOXYGEN], [doxygen])
|
||||||
|
AM_CONDITIONAL([HAVE_DOXYGEN],
|
||||||
|
[test -n "$DOXYGEN"])
|
||||||
|
AM_COND_IF([HAVE_DOXYGEN],
|
||||||
|
[AC_CONFIG_FILES([Doxyfile])
|
||||||
|
DOXYGEN_INPUT="${srcdir}/protobuf-c"
|
||||||
|
AC_SUBST(DOXYGEN_INPUT)
|
||||||
|
])
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG
|
||||||
|
if test -n "$PKG_CONFIG"; then
|
||||||
|
# Horrible hack for systems where the pkg-config install directory is simply wrong!
|
||||||
|
if $PKG_CONFIG --variable=pc_path pkg-config 2>/dev/null | grep -q /libdata/; then
|
||||||
|
PKG_INSTALLDIR(['${prefix}/libdata/pkgconfig'])
|
||||||
|
else
|
||||||
|
PKG_INSTALLDIR
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
proto3_supported="no"
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([protoc],
|
||||||
|
AS_HELP_STRING([--disable-protoc], [Disable building protoc_c (also disables tests)]))
|
||||||
|
if test "x$enable_protoc" != "xno"; then
|
||||||
|
AC_LANG_PUSH([C++])
|
||||||
|
|
||||||
|
AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([protobuf], [protobuf >= 3.0.0],
|
||||||
|
[proto3_supported=yes],
|
||||||
|
[PKG_CHECK_MODULES([protobuf], [protobuf >= 2.6.0])]
|
||||||
|
)
|
||||||
|
|
||||||
|
save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$save_CPPFLAGS $protobuf_CFLAGS"
|
||||||
|
AC_CHECK_HEADERS([google/protobuf/compiler/command_line_interface.h],
|
||||||
|
[],
|
||||||
|
[AC_MSG_ERROR([required protobuf header file not found])])
|
||||||
|
CPPFLAGS="$save_CPPFLAGS"
|
||||||
|
|
||||||
|
AC_ARG_VAR([PROTOC], [protobuf compiler command])
|
||||||
|
AC_PATH_PROG([PROTOC], [protoc], [],
|
||||||
|
[`$PKG_CONFIG --variable=exec_prefix protobuf`/bin:$PATH])
|
||||||
|
if test -z "$PROTOC"; then
|
||||||
|
AC_MSG_ERROR([Please install the protobuf compiler from https://code.google.com/p/protobuf/.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROTOBUF_VERSION="$($PROTOC --version)"
|
||||||
|
|
||||||
|
else
|
||||||
|
PROTOBUF_VERSION="not required, not building compiler"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL([BUILD_COMPILER], [test "x$enable_protoc" != "xno"])
|
||||||
|
AM_CONDITIONAL([BUILD_PROTO3], [test "x$proto3_supported" != "xno"])
|
||||||
|
AM_CONDITIONAL([CROSS_COMPILING], [test "x$cross_compiling" != "xno"])
|
||||||
|
|
||||||
|
AM_COND_IF([BUILD_PROTO3], [AC_DEFINE([HAVE_PROTO3], [1], [Support proto3 syntax])])
|
||||||
|
|
||||||
|
gl_LD_VERSION_SCRIPT
|
||||||
|
|
||||||
|
gl_VALGRIND_TESTS
|
||||||
|
|
||||||
|
MY_CODE_COVERAGE
|
||||||
|
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
AC_MSG_RESULT([
|
||||||
|
$PACKAGE $VERSION
|
||||||
|
|
||||||
|
CC: ${CC}
|
||||||
|
CFLAGS: ${CFLAGS}
|
||||||
|
CXX: ${CXX}
|
||||||
|
CXXFLAGS: ${CXXFLAGS}
|
||||||
|
LDFLAGS: ${LDFLAGS}
|
||||||
|
LIBS: ${LIBS}
|
||||||
|
|
||||||
|
prefix: ${prefix}
|
||||||
|
sysconfdir: ${sysconfdir}
|
||||||
|
libdir: ${libdir}
|
||||||
|
includedir: ${includedir}
|
||||||
|
pkgconfigdir: ${pkgconfigdir}
|
||||||
|
|
||||||
|
bigendian: ${ac_cv_c_bigendian}
|
||||||
|
protobuf version: ${PROTOBUF_VERSION}
|
||||||
|
])
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
libtool.m4
|
||||||
|
ltoptions.m4
|
||||||
|
ltsugar.m4
|
||||||
|
ltversion.m4
|
||||||
|
lt~obsolete.m4
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check whether the given FLAG works with the current language's compiler
|
||||||
|
# or gives an error. (Warnings, however, are ignored)
|
||||||
|
#
|
||||||
|
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
||||||
|
# success/failure.
|
||||||
|
#
|
||||||
|
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
||||||
|
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
||||||
|
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
||||||
|
# force the compiler to issue an error when a bad flag is given.
|
||||||
|
#
|
||||||
|
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||||
|
#
|
||||||
|
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
||||||
|
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
||||||
|
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the
|
||||||
|
# Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
# option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
|
# gives unlimited permission to copy, distribute and modify the configure
|
||||||
|
# scripts that are the output of Autoconf when processing the Macro. You
|
||||||
|
# need not follow the terms of the GNU General Public License when using
|
||||||
|
# or distributing such scripts, even though portions of the text of the
|
||||||
|
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||||
|
# all other use of the material that constitutes the Autoconf Macro.
|
||||||
|
#
|
||||||
|
# This special exception to the GPL applies to versions of the Autoconf
|
||||||
|
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||||
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
|
#serial 5
|
||||||
|
|
||||||
|
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||||
|
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||||
|
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||||
|
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
||||||
|
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||||
|
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
||||||
|
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
||||||
|
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||||
|
[AS_VAR_SET(CACHEVAR,[no])])
|
||||||
|
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
||||||
|
AS_VAR_IF(CACHEVAR,yes,
|
||||||
|
[m4_default([$2], :)],
|
||||||
|
[m4_default([$3], :)])
|
||||||
|
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||||
|
])dnl AX_CHECK_COMPILE_FLAGS
|
||||||
@@ -0,0 +1,948 @@
|
|||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 10
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
switch="-std=gnu++${alternative}"
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test x$ac_success = xyes; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_separators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++17
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201703L
|
||||||
|
|
||||||
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace cxx17
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_constexpr_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr int foo = [](){return 42;}();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test::nested_namespace::definitions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fold_expression
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
int multiply(Args... args)
|
||||||
|
{
|
||||||
|
return (args * ... * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool all(Args... args)
|
||||||
|
{
|
||||||
|
return (args && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_auto_brace_init_list
|
||||||
|
{
|
||||||
|
|
||||||
|
auto foo = {5};
|
||||||
|
auto bar {5};
|
||||||
|
|
||||||
|
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||||
|
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_typename_in_template_template_parameter
|
||||||
|
{
|
||||||
|
|
||||||
|
template<template<typename> typename X> struct D;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
int f1()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int f2()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto unused = f1();
|
||||||
|
|
||||||
|
switch (f1())
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
f1();
|
||||||
|
[[fallthrough]];
|
||||||
|
case 42:
|
||||||
|
f1();
|
||||||
|
}
|
||||||
|
return f1();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_aggregate_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct base1
|
||||||
|
{
|
||||||
|
int b1, b2 = 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct base2
|
||||||
|
{
|
||||||
|
base2() {
|
||||||
|
b3 = 42;
|
||||||
|
}
|
||||||
|
int b3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : base1, base2
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||||
|
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_general_range_based_for_loop
|
||||||
|
{
|
||||||
|
|
||||||
|
struct iter
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int& operator* ()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int& operator* () const
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter& operator++()
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sentinel
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return i.i == s.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return !(i == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
iter begin() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel end() const
|
||||||
|
{
|
||||||
|
return {5};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
range r {};
|
||||||
|
|
||||||
|
for (auto i : r)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto v = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_capture_asterisk_this_by_value
|
||||||
|
{
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int foo()
|
||||||
|
{
|
||||||
|
return [*this]()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_enum_class_construction
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class byte : unsigned char
|
||||||
|
{};
|
||||||
|
|
||||||
|
byte foo {42};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr_if
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool cond>
|
||||||
|
int f ()
|
||||||
|
{
|
||||||
|
if constexpr(cond)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_selection_statement_with_initializer
|
||||||
|
{
|
||||||
|
|
||||||
|
int f()
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f2()
|
||||||
|
{
|
||||||
|
if (auto i = f(); i > 0)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (auto i = f(); i + 4)
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_template_argument_deduction_for_class_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct pair
|
||||||
|
{
|
||||||
|
pair (T1 p1, T2 p2)
|
||||||
|
: m1 {p1},
|
||||||
|
m2 {p2}
|
||||||
|
{}
|
||||||
|
|
||||||
|
T1 m1;
|
||||||
|
T2 m2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto p = pair{13, 42u};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_non_type_auto_template_parameters
|
||||||
|
{
|
||||||
|
|
||||||
|
template <auto n>
|
||||||
|
struct B
|
||||||
|
{};
|
||||||
|
|
||||||
|
B<5> b1;
|
||||||
|
B<'a'> b2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_structured_bindings
|
||||||
|
{
|
||||||
|
|
||||||
|
int arr[2] = { 1, 2 };
|
||||||
|
std::pair<int, int> pr = { 1, 2 };
|
||||||
|
|
||||||
|
auto f1() -> int(&)[2]
|
||||||
|
{
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2() -> std::pair<int, int>&
|
||||||
|
{
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int x1 : 2;
|
||||||
|
volatile double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
S f3()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ x1, y1 ] = f1();
|
||||||
|
auto& [ xr1, yr1 ] = f1();
|
||||||
|
auto [ x2, y2 ] = f2();
|
||||||
|
auto& [ xr2, yr2 ] = f2();
|
||||||
|
const auto [ x3, y3 ] = f3();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_exception_spec_type_system
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Good {};
|
||||||
|
struct Bad {};
|
||||||
|
|
||||||
|
void g1() noexcept;
|
||||||
|
void g2();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Bad
|
||||||
|
f(T*, T*);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
Good
|
||||||
|
f(T1*, T2*);
|
||||||
|
|
||||||
|
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_inline_variables
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> void f(T)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class T> inline T g(T)
|
||||||
|
{
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void f<>(int)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<> int g<>(int)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx17
|
||||||
|
|
||||||
|
#endif // __cplusplus < 201703L
|
||||||
|
|
||||||
|
]])
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# MY_CODE_COVERAGE()
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Defines CODE_COVERAGE_CFLAGS and CODE_COVERAGE_LDFLAGS which should be
|
||||||
|
# included in the CFLAGS and LIBS/LDFLAGS variables of every build target
|
||||||
|
# (program or library) which should be built with code coverage support.
|
||||||
|
# Also defines CODE_COVERAGE_RULES which should be substituted in your
|
||||||
|
# Makefile; and $enable_code_coverage which can be used in subsequent
|
||||||
|
# configure output. CODE_COVERAGE_ENABLED is defined and substituted, and
|
||||||
|
# corresponds to the value of the --enable-code-coverage option, which
|
||||||
|
# defaults to being disabled.
|
||||||
|
#
|
||||||
|
# Usage example:
|
||||||
|
# configure.ac:
|
||||||
|
# MY_CODE_COVERAGE
|
||||||
|
#
|
||||||
|
# Makefile.am:
|
||||||
|
# @CODE_COVERAGE_RULES@
|
||||||
|
# my_program_LIBS = … $(CODE_COVERAGE_LDFLAGS) …
|
||||||
|
# my_program_CFLAGS = … $(CODE_COVERAGE_CFLAGS) …
|
||||||
|
#
|
||||||
|
# This results in a “check-code-coverage” rule being added to any Makefile.am
|
||||||
|
# which includes “@CODE_COVERAGE_RULES@” (assuming the module has been
|
||||||
|
# configured with --enable-code-coverage). Running `make check-code-coverage`
|
||||||
|
# in that directory will run the module’s test suite (`make check`) and build
|
||||||
|
# a code coverage report detailing the code which was touched, then print the
|
||||||
|
# URI for the report.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright © 2012, 2014 Philip Withnall
|
||||||
|
# Copyright © 2012 Xan Lopez
|
||||||
|
# Copyright © 2012 Christian Persch
|
||||||
|
# Copyright © 2012 Paolo Borelli
|
||||||
|
# Copyright © 2012 Dan Winship
|
||||||
|
#
|
||||||
|
# Derived from Makefile.decl in GLib, originally licenced under LGPLv2.1+.
|
||||||
|
# This file is licenced under LGPLv2.1+.
|
||||||
|
|
||||||
|
AC_DEFUN([MY_CODE_COVERAGE],[
|
||||||
|
dnl Check for --enable-code-coverage
|
||||||
|
AC_MSG_CHECKING([whether to build with code coverage support])
|
||||||
|
AC_ARG_ENABLE([code-coverage], AS_HELP_STRING([--enable-code-coverage], [Whether to enable code coverage support]),, enable_code_coverage=no)
|
||||||
|
AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
|
||||||
|
AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
|
||||||
|
AC_MSG_RESULT($enable_code_coverage)
|
||||||
|
|
||||||
|
AS_IF([ test "$enable_code_coverage" = "yes" ], [
|
||||||
|
dnl Check if gcc is being used
|
||||||
|
AS_IF([ test "$GCC" = "no" ], [
|
||||||
|
AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_CHECK_PROG([LCOV], [lcov], [lcov])
|
||||||
|
AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
|
||||||
|
|
||||||
|
AS_IF([ test -z "$LCOV" ], [
|
||||||
|
AC_MSG_ERROR([The lcov program was not found. Please install lcov!])
|
||||||
|
])
|
||||||
|
|
||||||
|
AS_IF([ test -z "$GENHTML" ], [
|
||||||
|
AC_MSG_ERROR([The genhtml program was not found. Please install lcov!])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Build the code coverage flags
|
||||||
|
CODE_COVERAGE_CFLAGS="-O0 -g --coverage"
|
||||||
|
CODE_COVERAGE_LDFLAGS="--coverage"
|
||||||
|
|
||||||
|
AC_SUBST([CODE_COVERAGE_CFLAGS])
|
||||||
|
AC_SUBST([CODE_COVERAGE_LDFLAGS])
|
||||||
|
|
||||||
|
dnl Strip optimisation flags
|
||||||
|
changequote({,})
|
||||||
|
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
|
||||||
|
changequote([,])
|
||||||
|
])
|
||||||
|
|
||||||
|
CODE_COVERAGE_RULES='
|
||||||
|
# Code coverage
|
||||||
|
#
|
||||||
|
# Optional:
|
||||||
|
# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
|
||||||
|
# (Default: $(top_builddir))
|
||||||
|
# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
|
||||||
|
# by lcov for code coverage. (Default:
|
||||||
|
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
|
||||||
|
# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
|
||||||
|
# reports to be created. (Default:
|
||||||
|
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
|
||||||
|
# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the lcov instance.
|
||||||
|
# (Default: empty)
|
||||||
|
# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
|
||||||
|
# instance. (Default: empty)
|
||||||
|
# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
|
||||||
|
#
|
||||||
|
# The generated report will be titled using the $(PACKAGE_NAME) and
|
||||||
|
# $(PACKAGE_VERSION). In order to add the current git hash to the title,
|
||||||
|
# use the git-version-gen script, available online.
|
||||||
|
|
||||||
|
# Optional variables
|
||||||
|
CODE_COVERAGE_DIRECTORY ?= $(abs_top_builddir)
|
||||||
|
CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
|
||||||
|
CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
|
||||||
|
CODE_COVERAGE_LCOV_OPTIONS ?=
|
||||||
|
CODE_COVERAGE_GENHTML_OPTIONS ?=
|
||||||
|
CODE_COVERAGE_IGNORE_PATTERN ?=
|
||||||
|
|
||||||
|
code_coverage_quiet = $(code_coverage_quiet_$(V))
|
||||||
|
code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
|
||||||
|
code_coverage_quiet_0 = --quiet
|
||||||
|
|
||||||
|
# Use recursive makes in order to ignore errors during check
|
||||||
|
check-code-coverage:
|
||||||
|
ifeq ($(CODE_COVERAGE_ENABLED),yes)
|
||||||
|
-$(MAKE) $(AM_MAKEFLAGS) -k check
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
|
||||||
|
else
|
||||||
|
@echo "Need to reconfigure with --enable-code-coverage"
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Capture code coverage data
|
||||||
|
code-coverage-capture: code-coverage-capture-hook
|
||||||
|
ifeq ($(CODE_COVERAGE_ENABLED),yes)
|
||||||
|
$(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_OPTIONS)
|
||||||
|
$(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)"
|
||||||
|
-@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
|
||||||
|
LANG=C $(GENHTML) $(code_coverage_quiet) --prefix $(CODE_COVERAGE_DIRECTORY) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
|
||||||
|
@echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
|
||||||
|
else
|
||||||
|
@echo "Need to reconfigure with --enable-code-coverage"
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Hook rule executed before code-coverage-capture, overridable by the user
|
||||||
|
code-coverage-capture-hook:
|
||||||
|
|
||||||
|
ifeq ($(CODE_COVERAGE_ENABLED),yes)
|
||||||
|
clean: code-coverage-clean
|
||||||
|
code-coverage-clean:
|
||||||
|
-$(LCOV) --directory $(CODE_COVERAGE_DIRECTORY) -z
|
||||||
|
-rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
|
||||||
|
-find . -name "*.gcda" -o -name "*.gcov" -delete
|
||||||
|
endif
|
||||||
|
|
||||||
|
GITIGNOREFILES ?=
|
||||||
|
GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
|
||||||
|
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS ?=
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
|
||||||
|
|
||||||
|
.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
|
||||||
|
'
|
||||||
|
|
||||||
|
AC_SUBST([CODE_COVERAGE_RULES])
|
||||||
|
m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])])
|
||||||
|
])
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# ld-version-script.m4 serial 3
|
||||||
|
dnl Copyright (C) 2008-2014 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Simon Josefsson
|
||||||
|
|
||||||
|
# FIXME: The test below returns a false positive for mingw
|
||||||
|
# cross-compiles, 'local:' statements does not reduce number of
|
||||||
|
# exported symbols in a DLL. Use --disable-ld-version-script to work
|
||||||
|
# around the problem.
|
||||||
|
|
||||||
|
# gl_LD_VERSION_SCRIPT
|
||||||
|
# --------------------
|
||||||
|
# Check if LD supports linker scripts, and define automake conditional
|
||||||
|
# HAVE_LD_VERSION_SCRIPT if so.
|
||||||
|
AC_DEFUN([gl_LD_VERSION_SCRIPT],
|
||||||
|
[
|
||||||
|
AC_ARG_ENABLE([ld-version-script],
|
||||||
|
AS_HELP_STRING([--enable-ld-version-script],
|
||||||
|
[enable linker version script (default is enabled when possible)]),
|
||||||
|
[have_ld_version_script=$enableval], [])
|
||||||
|
if test -z "$have_ld_version_script"; then
|
||||||
|
AC_MSG_CHECKING([if LD -Wl,--version-script works])
|
||||||
|
save_LDFLAGS="$LDFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
|
||||||
|
cat > conftest.map <<EOF
|
||||||
|
foo
|
||||||
|
EOF
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||||
|
[accepts_syntax_errors=yes], [accepts_syntax_errors=no])
|
||||||
|
if test "$accepts_syntax_errors" = no; then
|
||||||
|
cat > conftest.map <<EOF
|
||||||
|
VERS_1 {
|
||||||
|
global: sym;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERS_2 {
|
||||||
|
global: sym;
|
||||||
|
} VERS_1;
|
||||||
|
EOF
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||||
|
[have_ld_version_script=yes], [have_ld_version_script=no])
|
||||||
|
else
|
||||||
|
have_ld_version_script=no
|
||||||
|
fi
|
||||||
|
rm -f conftest.map
|
||||||
|
LDFLAGS="$save_LDFLAGS"
|
||||||
|
AC_MSG_RESULT($have_ld_version_script)
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
|
||||||
|
])
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
|
# serial 1 (pkg-config-0.24)
|
||||||
|
#
|
||||||
|
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||||
|
# ----------------------------------
|
||||||
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
|
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||||
|
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
|
||||||
|
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
||||||
|
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
||||||
|
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||||
|
|
||||||
|
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||||
|
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||||
|
fi
|
||||||
|
if test -n "$PKG_CONFIG"; then
|
||||||
|
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||||
|
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
PKG_CONFIG=""
|
||||||
|
fi
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
|
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
# Check to see whether a particular set of modules exists. Similar
|
||||||
|
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||||
|
#
|
||||||
|
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
|
# only at the first occurence in configure.ac, so if the first place
|
||||||
|
# it's called might be skipped (such as if it is within an "if", you
|
||||||
|
# have to call PKG_CHECK_EXISTS manually
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||||
|
m4_default([$2], [:])
|
||||||
|
m4_ifvaln([$3], [else
|
||||||
|
$3])dnl
|
||||||
|
fi])
|
||||||
|
|
||||||
|
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||||
|
# ---------------------------------------------
|
||||||
|
m4_define([_PKG_CONFIG],
|
||||||
|
[if test -n "$$1"; then
|
||||||
|
pkg_cv_[]$1="$$1"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
PKG_CHECK_EXISTS([$3],
|
||||||
|
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes ],
|
||||||
|
[pkg_failed=yes])
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_CONFIG
|
||||||
|
|
||||||
|
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
# -----------------------------
|
||||||
|
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
|
# [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Note that if there is a possibility the first call to
|
||||||
|
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||||
|
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||||
|
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
AC_MSG_CHECKING([for $1])
|
||||||
|
|
||||||
|
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||||
|
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||||
|
|
||||||
|
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||||
|
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||||
|
See the pkg-config man page for more details.])
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
_PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
||||||
|
else
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||||
|
|
||||||
|
m4_default([$4], [AC_MSG_ERROR(
|
||||||
|
[Package requirements ($2) were not met:
|
||||||
|
|
||||||
|
$$1_PKG_ERRORS
|
||||||
|
|
||||||
|
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||||
|
installed software in a non-standard prefix.
|
||||||
|
|
||||||
|
_PKG_TEXT])[]dnl
|
||||||
|
])
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
m4_default([$4], [AC_MSG_FAILURE(
|
||||||
|
[The pkg-config script could not be found or is too old. Make sure it
|
||||||
|
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||||
|
path to pkg-config.
|
||||||
|
|
||||||
|
_PKG_TEXT
|
||||||
|
|
||||||
|
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||||
|
])
|
||||||
|
else
|
||||||
|
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||||
|
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
$3
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_CHECK_MODULES
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_INSTALLDIR(DIRECTORY)
|
||||||
|
# -------------------------
|
||||||
|
# Substitutes the variable pkgconfigdir as the location where a module
|
||||||
|
# should install pkg-config .pc files. By default the directory is
|
||||||
|
# $libdir/pkgconfig, but the default can be changed by passing
|
||||||
|
# DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||||
|
# parameter.
|
||||||
|
AC_DEFUN([PKG_INSTALLDIR],
|
||||||
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||||
|
m4_pushdef([pkg_description],
|
||||||
|
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
||||||
|
AC_ARG_WITH([pkgconfigdir],
|
||||||
|
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
||||||
|
[with_pkgconfigdir=]pkg_default)
|
||||||
|
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||||
|
m4_popdef([pkg_default])
|
||||||
|
m4_popdef([pkg_description])
|
||||||
|
]) dnl PKG_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
|
||||||
|
# -------------------------
|
||||||
|
# Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||||
|
# module should install arch-independent pkg-config .pc files. By
|
||||||
|
# default the directory is $datadir/pkgconfig, but the default can be
|
||||||
|
# changed by passing DIRECTORY. The user can override through the
|
||||||
|
# --with-noarch-pkgconfigdir parameter.
|
||||||
|
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||||
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||||
|
m4_pushdef([pkg_description],
|
||||||
|
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
||||||
|
AC_ARG_WITH([noarch-pkgconfigdir],
|
||||||
|
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
||||||
|
[with_noarch_pkgconfigdir=]pkg_default)
|
||||||
|
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||||
|
m4_popdef([pkg_default])
|
||||||
|
m4_popdef([pkg_description])
|
||||||
|
]) dnl PKG_NOARCH_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||||
|
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
|
# -------------------------------------------
|
||||||
|
# Retrieves the value of the pkg-config variable for the given module.
|
||||||
|
AC_DEFUN([PKG_CHECK_VAR],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||||
|
|
||||||
|
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
||||||
|
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||||
|
|
||||||
|
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||||
|
])# PKG_CHECK_VAR
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# valgrind-tests.m4 serial 2
|
||||||
|
dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Simon Josefsson
|
||||||
|
|
||||||
|
# gl_VALGRIND_TESTS()
|
||||||
|
# -------------------
|
||||||
|
# Check if valgrind is available, and set VALGRIND to it if available.
|
||||||
|
AC_DEFUN([gl_VALGRIND_TESTS],
|
||||||
|
[
|
||||||
|
AC_ARG_ENABLE(valgrind-tests,
|
||||||
|
AS_HELP_STRING([--enable-valgrind-tests],
|
||||||
|
[run self tests under valgrind]),
|
||||||
|
[opt_valgrind_tests=$enableval], [opt_valgrind_tests=no])
|
||||||
|
|
||||||
|
# Run self-tests under valgrind?
|
||||||
|
if test "$opt_valgrind_tests" = "yes" && test "$cross_compiling" = no; then
|
||||||
|
AC_CHECK_PROGS(VALGRIND, valgrind)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$VALGRIND" && $VALGRIND -q true > /dev/null 2>&1; then
|
||||||
|
opt_valgrind_tests=yes
|
||||||
|
VALGRIND="$VALGRIND -q --error-exitcode=1 --leak-check=full \
|
||||||
|
--trace-children=yes --trace-children-skip=/usr/*,/bin/*"
|
||||||
|
else
|
||||||
|
opt_valgrind_tests=no
|
||||||
|
VALGRIND=
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether self tests are run under valgrind])
|
||||||
|
AC_MSG_RESULT($opt_valgrind_tests)
|
||||||
|
])
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
bindir=@bindir@
|
||||||
|
|
||||||
|
Name: @PACKAGE_NAME@
|
||||||
|
Description: @PACKAGE_DESCRIPTION@
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
URL: @PACKAGE_URL@
|
||||||
|
Libs: -L${libdir} -lprotobuf-c
|
||||||
|
Libs.private:
|
||||||
|
Cflags: -I${includedir}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
LIBPROTOBUF_C_1.0.0 {
|
||||||
|
global:
|
||||||
|
protobuf_c_buffer_simple_append;
|
||||||
|
protobuf_c_enum_descriptor_get_value;
|
||||||
|
protobuf_c_enum_descriptor_get_value_by_name;
|
||||||
|
protobuf_c_message_check;
|
||||||
|
protobuf_c_message_descriptor_get_field;
|
||||||
|
protobuf_c_message_descriptor_get_field_by_name;
|
||||||
|
protobuf_c_message_free_unpacked;
|
||||||
|
protobuf_c_message_get_packed_size;
|
||||||
|
protobuf_c_message_init;
|
||||||
|
protobuf_c_message_pack;
|
||||||
|
protobuf_c_message_pack_to_buffer;
|
||||||
|
protobuf_c_message_unpack;
|
||||||
|
protobuf_c_service_descriptor_get_method_by_name;
|
||||||
|
protobuf_c_service_destroy;
|
||||||
|
protobuf_c_service_generated_init;
|
||||||
|
protobuf_c_service_invoke_internal;
|
||||||
|
protobuf_c_version;
|
||||||
|
protobuf_c_version_number;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBPROTOBUF_C_1.3.0 {
|
||||||
|
global:
|
||||||
|
protobuf_c_empty_string;
|
||||||
|
} LIBPROTOBUF_C_1.0.0;
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021, the protobuf-c authors.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
|
// We never need to generate protobuf-c.pb-c.{c,h}, the options are used
|
||||||
|
// only by protoc-gen-c, never by the protobuf-c runtime itself
|
||||||
|
option (pb_c_file).no_generate = true;
|
||||||
|
|
||||||
|
message ProtobufCFileOptions {
|
||||||
|
// Suppresses pb-c.{c,h} file output completely.
|
||||||
|
optional bool no_generate = 1 [default = false];
|
||||||
|
|
||||||
|
// Generate helper pack/unpack functions?
|
||||||
|
// For backwards compatibility, if this field is not explicitly set,
|
||||||
|
// only top-level message pack/unpack functions will be generated
|
||||||
|
optional bool gen_pack_helpers = 2 [default = true];
|
||||||
|
|
||||||
|
// Generate helper init message functions?
|
||||||
|
optional bool gen_init_helpers = 3 [default = true];
|
||||||
|
|
||||||
|
// Use const char * instead of char * for string fields
|
||||||
|
optional bool const_strings = 4 [default = false];
|
||||||
|
|
||||||
|
// For oneof fields, set ProtobufCFieldDescriptor name field to the
|
||||||
|
// name of the containing oneof, instead of the field name
|
||||||
|
optional bool use_oneof_field_name = 5 [default = false];
|
||||||
|
|
||||||
|
// Overrides the package name, if present
|
||||||
|
optional string c_package = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.FileOptions {
|
||||||
|
optional ProtobufCFileOptions pb_c_file = 1019;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProtobufCMessageOptions {
|
||||||
|
// Overrides the parent setting only if present
|
||||||
|
optional bool gen_pack_helpers = 1 [default = false];
|
||||||
|
|
||||||
|
// Overrides the parent setting only if present
|
||||||
|
optional bool gen_init_helpers = 2 [default = true];
|
||||||
|
|
||||||
|
// Reserved base message field name
|
||||||
|
optional string base_field_name = 3 [default = "base"];
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.MessageOptions {
|
||||||
|
optional ProtobufCMessageOptions pb_c_msg = 1019;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProtobufCFieldOptions {
|
||||||
|
// Treat string as bytes in generated code
|
||||||
|
optional bool string_as_bytes = 1 [default = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.FieldOptions {
|
||||||
|
optional ProtobufCFieldOptions pb_c_field = 1019;
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#include <protoc-c/c_bytes_field.h>
|
||||||
|
#include <protoc-c/c_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <protobuf-c/protobuf-c.pb.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
|
||||||
|
void SetBytesVariables(const FieldDescriptor* descriptor,
|
||||||
|
std::map<std::string, std::string>* variables) {
|
||||||
|
(*variables)["name"] = FieldName(descriptor);
|
||||||
|
(*variables)["default"] =
|
||||||
|
"\"" + CEscape(descriptor->default_value_string()) + "\"";
|
||||||
|
(*variables)["deprecated"] = FieldDeprecated(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
BytesFieldGenerator::
|
||||||
|
BytesFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: FieldGenerator(descriptor) {
|
||||||
|
SetBytesVariables(descriptor, &variables_);
|
||||||
|
variables_["default_value"] = descriptor->has_default_value()
|
||||||
|
? GetDefaultValue()
|
||||||
|
: std::string("{0,NULL}");
|
||||||
|
}
|
||||||
|
|
||||||
|
BytesFieldGenerator::~BytesFieldGenerator() {}
|
||||||
|
|
||||||
|
void BytesFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
switch (descriptor_->label()) {
|
||||||
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
printer->Print(variables_, "ProtobufCBinaryData $name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_OPTIONAL:
|
||||||
|
if (descriptor_->containing_oneof() == NULL && FieldSyntax(descriptor_) == 2)
|
||||||
|
printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n");
|
||||||
|
printer->Print(variables_, "ProtobufCBinaryData $name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_REPEATED:
|
||||||
|
printer->Print(variables_, "size_t n_$name$$deprecated$;\n");
|
||||||
|
printer->Print(variables_, "ProtobufCBinaryData *$name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BytesFieldGenerator::GenerateDefaultValueDeclarations(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
vars["default_value_data"] = FullNameToLower(descriptor_->full_name(), descriptor_->file())
|
||||||
|
+ "__default_value_data";
|
||||||
|
printer->Print(vars, "extern uint8_t $default_value_data$[];\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void BytesFieldGenerator::GenerateDefaultValueImplementations(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
vars["default_value_data"] = FullNameToLower(descriptor_->full_name(), descriptor_->file())
|
||||||
|
+ "__default_value_data";
|
||||||
|
vars["escaped"] = CEscape(descriptor_->default_value_string());
|
||||||
|
printer->Print(vars, "uint8_t $default_value_data$[] = \"$escaped$\";\n");
|
||||||
|
}
|
||||||
|
std::string BytesFieldGenerator::GetDefaultValue(void) const
|
||||||
|
{
|
||||||
|
return "{ "
|
||||||
|
+ SimpleItoa(descriptor_->default_value_string().size())
|
||||||
|
+ ", "
|
||||||
|
+ FullNameToLower(descriptor_->full_name(), descriptor_->file())
|
||||||
|
+ "__default_value_data }";
|
||||||
|
}
|
||||||
|
void BytesFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
switch (descriptor_->label()) {
|
||||||
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
printer->Print(variables_, "$default_value$");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_OPTIONAL:
|
||||||
|
if (FieldSyntax(descriptor_) == 2)
|
||||||
|
printer->Print(variables_, "0, ");
|
||||||
|
printer->Print(variables_, "$default_value$");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_REPEATED:
|
||||||
|
// no support for default?
|
||||||
|
printer->Print("0,NULL");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BytesFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
GenerateDescriptorInitializerGeneric(printer, true, "BYTES", "NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_C_BYTES_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_C_BYTES_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <protoc-c/c_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
class BytesFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit BytesFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~BytesFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateStructMembers(io::Printer* printer) const;
|
||||||
|
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||||
|
void GenerateDefaultValueDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateDefaultValueImplementations(io::Printer* printer) const;
|
||||||
|
std::string GetDefaultValue(void) const;
|
||||||
|
void GenerateStaticInit(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(BytesFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_C_STRING_FIELD_H__
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <protoc-c/c_enum.h>
|
||||||
|
#include <protoc-c/c_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
|
const std::string& dllexport_decl)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
dllexport_decl_(dllexport_decl) {
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumGenerator::~EnumGenerator() {}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
||||||
|
vars["shortname"] = descriptor_->name();
|
||||||
|
vars["uc_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file());
|
||||||
|
|
||||||
|
SourceLocation sourceLoc;
|
||||||
|
descriptor_->GetSourceLocation(&sourceLoc);
|
||||||
|
PrintComment (printer, sourceLoc.leading_comments);
|
||||||
|
|
||||||
|
printer->Print(vars, "typedef enum _$classname$ {\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
const EnumValueDescriptor* min_value = descriptor_->value(0);
|
||||||
|
const EnumValueDescriptor* max_value = descriptor_->value(0);
|
||||||
|
|
||||||
|
|
||||||
|
vars["opt_comma"] = ",";
|
||||||
|
vars["prefix"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__";
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
vars["name"] = descriptor_->value(i)->name();
|
||||||
|
vars["number"] = SimpleItoa(descriptor_->value(i)->number());
|
||||||
|
if (i + 1 == descriptor_->value_count())
|
||||||
|
vars["opt_comma"] = "";
|
||||||
|
|
||||||
|
SourceLocation valSourceLoc;
|
||||||
|
descriptor_->value(i)->GetSourceLocation(&valSourceLoc);
|
||||||
|
|
||||||
|
PrintComment (printer, valSourceLoc.leading_comments);
|
||||||
|
PrintComment (printer, valSourceLoc.trailing_comments);
|
||||||
|
printer->Print(vars, "$prefix$$name$ = $number$$opt_comma$\n");
|
||||||
|
|
||||||
|
if (descriptor_->value(i)->number() < min_value->number()) {
|
||||||
|
min_value = descriptor_->value(i);
|
||||||
|
}
|
||||||
|
if (descriptor_->value(i)->number() > max_value->number()) {
|
||||||
|
max_value = descriptor_->value(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars, " PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE($uc_name$)\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(vars, "} $classname$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateDescriptorDeclarations(io::Printer* printer) {
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
if (dllexport_decl_.empty()) {
|
||||||
|
vars["dllexport"] = "";
|
||||||
|
} else {
|
||||||
|
vars["dllexport"] = dllexport_decl_ + " ";
|
||||||
|
}
|
||||||
|
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
||||||
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"extern $dllexport$const ProtobufCEnumDescriptor $lcclassname$__descriptor;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ValueIndex
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
unsigned index;
|
||||||
|
unsigned final_index; /* index in uniqified array of values */
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
void EnumGenerator::GenerateValueInitializer(io::Printer *printer, int index)
|
||||||
|
{
|
||||||
|
const EnumValueDescriptor *vd = descriptor_->value(index);
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
|
||||||
|
descriptor_->file()->options().optimize_for() ==
|
||||||
|
FileOptions_OptimizeMode_CODE_SIZE;
|
||||||
|
vars["enum_value_name"] = vd->name();
|
||||||
|
vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__" + vd->name();
|
||||||
|
vars["value"] = SimpleItoa(vd->number());
|
||||||
|
if (optimize_code_size)
|
||||||
|
printer->Print(vars, " { NULL, NULL, $value$ }, /* CODE_SIZE */\n");
|
||||||
|
else
|
||||||
|
printer->Print(vars,
|
||||||
|
" { \"$enum_value_name$\", \"$c_enum_value_name$\", $value$ },\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_value_indices_by_value_then_index(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const ValueIndex *vi_a = (const ValueIndex *) a;
|
||||||
|
const ValueIndex *vi_b = (const ValueIndex *) b;
|
||||||
|
if (vi_a->value < vi_b->value) return -1;
|
||||||
|
if (vi_a->value > vi_b->value) return +1;
|
||||||
|
if (vi_a->index < vi_b->index) return -1;
|
||||||
|
if (vi_a->index > vi_b->index) return +1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_value_indices_by_name(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const ValueIndex *vi_a = (const ValueIndex *) a;
|
||||||
|
const ValueIndex *vi_b = (const ValueIndex *) b;
|
||||||
|
return strcmp (vi_a->name, vi_b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) {
|
||||||
|
std::map<std::string, std::string> vars;
|
||||||
|
vars["fullname"] = descriptor_->full_name();
|
||||||
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
|
||||||
|
vars["cname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
|
||||||
|
vars["shortname"] = descriptor_->name();
|
||||||
|
vars["packagename"] = descriptor_->file()->package();
|
||||||
|
vars["value_count"] = SimpleItoa(descriptor_->value_count());
|
||||||
|
|
||||||
|
bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
|
||||||
|
descriptor_->file()->options().optimize_for() ==
|
||||||
|
FileOptions_OptimizeMode_CODE_SIZE;
|
||||||
|
|
||||||
|
// Sort by name and value, dropping duplicate values if they appear later.
|
||||||
|
// TODO: use a c++ paradigm for this!
|
||||||
|
NameIndex *name_index = new NameIndex[descriptor_->value_count()];
|
||||||
|
ValueIndex *value_index = new ValueIndex[descriptor_->value_count()];
|
||||||
|
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||||
|
const EnumValueDescriptor *vd = descriptor_->value(j);
|
||||||
|
name_index[j].index = j;
|
||||||
|
name_index[j].name = vd->name().c_str();
|
||||||
|
value_index[j].index = j;
|
||||||
|
value_index[j].value = vd->number();
|
||||||
|
value_index[j].name = vd->name().c_str();
|
||||||
|
}
|
||||||
|
qsort(value_index, descriptor_->value_count(),
|
||||||
|
sizeof(ValueIndex), compare_value_indices_by_value_then_index);
|
||||||
|
|
||||||
|
// only record unique values
|
||||||
|
int n_unique_values;
|
||||||
|
if (descriptor_->value_count() == 0) {
|
||||||
|
n_unique_values = 0; // should never happen
|
||||||
|
} else {
|
||||||
|
n_unique_values = 1;
|
||||||
|
value_index[0].final_index = 0;
|
||||||
|
for (int j = 1; j < descriptor_->value_count(); j++) {
|
||||||
|
if (value_index[j-1].value != value_index[j].value)
|
||||||
|
value_index[j].final_index = n_unique_values++;
|
||||||
|
else
|
||||||
|
value_index[j].final_index = n_unique_values - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vars["unique_value_count"] = SimpleItoa(n_unique_values);
|
||||||
|
printer->Print(vars,
|
||||||
|
"static const ProtobufCEnumValue $lcclassname$__enum_values_by_number[$unique_value_count$] =\n"
|
||||||
|
"{\n");
|
||||||
|
if (descriptor_->value_count() > 0) {
|
||||||
|
GenerateValueInitializer(printer, value_index[0].index);
|
||||||
|
for (int j = 1; j < descriptor_->value_count(); j++) {
|
||||||
|
if (value_index[j-1].value != value_index[j].value) {
|
||||||
|
GenerateValueInitializer(printer, value_index[j].index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printer->Print(vars, "};\n");
|
||||||
|
printer->Print(vars, "static const ProtobufCIntRange $lcclassname$__value_ranges[] = {\n");
|
||||||
|
unsigned n_ranges = 0;
|
||||||
|
if (descriptor_->value_count() > 0) {
|
||||||
|
unsigned range_start = 0;
|
||||||
|
unsigned range_len = 1;
|
||||||
|
int range_start_value = value_index[0].value;
|
||||||
|
int last_value = range_start_value;
|
||||||
|
for (int j = 1; j < descriptor_->value_count(); j++) {
|
||||||
|
if (value_index[j-1].value != value_index[j].value) {
|
||||||
|
if (last_value + 1 == value_index[j].value) {
|
||||||
|
range_len++;
|
||||||
|
} else {
|
||||||
|
// output range
|
||||||
|
vars["range_start_value"] = SimpleItoa(range_start_value);
|
||||||
|
vars["orig_index"] = SimpleItoa(range_start);
|
||||||
|
printer->Print (vars, "{$range_start_value$, $orig_index$},");
|
||||||
|
range_start_value = value_index[j].value;
|
||||||
|
range_start += range_len;
|
||||||
|
range_len = 1;
|
||||||
|
n_ranges++;
|
||||||
|
}
|
||||||
|
last_value = value_index[j].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vars["range_start_value"] = SimpleItoa(range_start_value);
|
||||||
|
vars["orig_index"] = SimpleItoa(range_start);
|
||||||
|
printer->Print (vars, "{$range_start_value$, $orig_index$},");
|
||||||
|
range_start += range_len;
|
||||||
|
n_ranges++;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vars["range_start_value"] = SimpleItoa(0);
|
||||||
|
vars["orig_index"] = SimpleItoa(range_start);
|
||||||
|
printer->Print (vars, "{$range_start_value$, $orig_index$}\n};\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vars["n_ranges"] = SimpleItoa(n_ranges);
|
||||||
|
|
||||||
|
if (!optimize_code_size) {
|
||||||
|
qsort(value_index, descriptor_->value_count(),
|
||||||
|
sizeof(ValueIndex), compare_value_indices_by_name);
|
||||||
|
printer->Print(vars,
|
||||||
|
"static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n"
|
||||||
|
"{\n");
|
||||||
|
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||||
|
vars["index"] = SimpleItoa(value_index[j].final_index);
|
||||||
|
vars["name"] = value_index[j].name;
|
||||||
|
printer->Print (vars, " { \"$name$\", $index$ },\n");
|
||||||
|
}
|
||||||
|
printer->Print(vars, "};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optimize_code_size) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"const ProtobufCEnumDescriptor $lcclassname$__descriptor =\n"
|
||||||
|
"{\n"
|
||||||
|
" PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,\n"
|
||||||
|
" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n"
|
||||||
|
" $unique_value_count$,\n"
|
||||||
|
" $lcclassname$__enum_values_by_number,\n"
|
||||||
|
" 0, NULL, /* CODE_SIZE */\n"
|
||||||
|
" $n_ranges$,\n"
|
||||||
|
" $lcclassname$__value_ranges,\n"
|
||||||
|
" NULL,NULL,NULL,NULL /* reserved[1234] */\n"
|
||||||
|
"};\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(vars,
|
||||||
|
"const ProtobufCEnumDescriptor $lcclassname$__descriptor =\n"
|
||||||
|
"{\n"
|
||||||
|
" PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,\n"
|
||||||
|
" \"$fullname$\",\n"
|
||||||
|
" \"$shortname$\",\n"
|
||||||
|
" \"$cname$\",\n"
|
||||||
|
" \"$packagename$\",\n"
|
||||||
|
" $unique_value_count$,\n"
|
||||||
|
" $lcclassname$__enum_values_by_number,\n"
|
||||||
|
" $value_count$,\n"
|
||||||
|
" $lcclassname$__enum_values_by_name,\n"
|
||||||
|
" $n_ranges$,\n"
|
||||||
|
" $lcclassname$__value_ranges,\n"
|
||||||
|
" NULL,NULL,NULL,NULL /* reserved[1234] */\n"
|
||||||
|
"};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] value_index;
|
||||||
|
delete[] name_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_C_ENUM_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_C_ENUM_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
class Printer; // printer.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
class EnumGenerator {
|
||||||
|
public:
|
||||||
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
|
explicit EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
|
const std::string& dllexport_decl);
|
||||||
|
~EnumGenerator();
|
||||||
|
|
||||||
|
// Header stuff.
|
||||||
|
|
||||||
|
// Generate header code defining the enum. This code should be placed
|
||||||
|
// within the enum's package namespace, but NOT within any class, even for
|
||||||
|
// nested enums.
|
||||||
|
void GenerateDefinition(io::Printer* printer);
|
||||||
|
|
||||||
|
void GenerateDescriptorDeclarations(io::Printer* printer);
|
||||||
|
|
||||||
|
|
||||||
|
// Source file stuff.
|
||||||
|
|
||||||
|
// Generate the ProtobufCEnumDescriptor for this enum
|
||||||
|
void GenerateEnumDescriptor(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate static initializer for a ProtobufCEnumValue
|
||||||
|
// given the index of the value in the enum.
|
||||||
|
void GenerateValueInitializer(io::Printer *printer, int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const EnumDescriptor* descriptor_;
|
||||||
|
std::string dllexport_decl_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_C_ENUM_H__
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#include <protoc-c/c_enum_field.h>
|
||||||
|
#include <protoc-c/c_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
|
||||||
|
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||||
|
// repeat code between this and the other field types.
|
||||||
|
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||||
|
std::map<std::string, std::string>* variables) {
|
||||||
|
|
||||||
|
(*variables)["name"] = FieldName(descriptor);
|
||||||
|
(*variables)["type"] = FullNameToC(descriptor->enum_type()->full_name(), descriptor->enum_type()->file());
|
||||||
|
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||||
|
(*variables)["default"] = FullNameToUpper(default_value->type()->full_name(), default_value->type()->file())
|
||||||
|
+ "__" + default_value->name();
|
||||||
|
(*variables)["deprecated"] = FieldDeprecated(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
EnumFieldGenerator::
|
||||||
|
EnumFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: FieldGenerator(descriptor)
|
||||||
|
{
|
||||||
|
SetEnumVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
switch (descriptor_->label()) {
|
||||||
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
printer->Print(variables_, "$type$ $name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_OPTIONAL:
|
||||||
|
if (descriptor_->containing_oneof() == NULL && FieldSyntax(descriptor_) == 2)
|
||||||
|
printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n");
|
||||||
|
printer->Print(variables_, "$type$ $name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_REPEATED:
|
||||||
|
printer->Print(variables_, "size_t n_$name$$deprecated$;\n");
|
||||||
|
printer->Print(variables_, "$type$ *$name$$deprecated$;\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EnumFieldGenerator::GetDefaultValue(void) const
|
||||||
|
{
|
||||||
|
return variables_.find("default")->second;
|
||||||
|
}
|
||||||
|
void EnumFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
switch (descriptor_->label()) {
|
||||||
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
printer->Print(variables_, "$default$");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_OPTIONAL:
|
||||||
|
if (FieldSyntax(descriptor_) == 2)
|
||||||
|
printer->Print(variables_, "0, ");
|
||||||
|
printer->Print(variables_, "$default$");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_REPEATED:
|
||||||
|
// no support for default?
|
||||||
|
printer->Print("0,NULL");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||||
|
{
|
||||||
|
std::string addr = "&" + FullNameToLower(descriptor_->enum_type()->full_name(), descriptor_->enum_type()->file()) + "__descriptor";
|
||||||
|
GenerateDescriptorInitializerGeneric(printer, true, "ENUM", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_C_ENUM_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_C_ENUM_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <protoc-c/c_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
class EnumFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~EnumFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateStructMembers(io::Printer* printer) const;
|
||||||
|
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||||
|
std::string GetDefaultValue(void) const;
|
||||||
|
void GenerateStaticInit(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_C_ENUM_FIELD_H__
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#include <protoc-c/c_extension.h>
|
||||||
|
#include <protoc-c/c_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const std::string& dllexport_decl)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
dllexport_decl_(dllexport_decl) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtensionGenerator::~ExtensionGenerator() {}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_C_EXTENSION_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_C_EXTENSION_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
class FieldDescriptor; // descriptor.h
|
||||||
|
namespace io {
|
||||||
|
class Printer; // printer.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
// Generates code for an extension, which may be within the scope of some
|
||||||
|
// message or may be at file scope. This is much simpler than FieldGenerator
|
||||||
|
// since extensions are just simple identifiers with interesting types.
|
||||||
|
class ExtensionGenerator {
|
||||||
|
public:
|
||||||
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
|
explicit ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const std::string& dllexport_decl);
|
||||||
|
~ExtensionGenerator();
|
||||||
|
|
||||||
|
// Header stuff.
|
||||||
|
void GenerateDeclaration(io::Printer* printer);
|
||||||
|
|
||||||
|
// Source file stuff.
|
||||||
|
void GenerateDefinition(io::Printer* printer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
std::string type_traits_;
|
||||||
|
std::string dllexport_decl_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_C_MESSAGE_H__
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
// Copyright (c) 2008-2013, Dave Benson. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Modified to implement C code by Dave Benson.
|
||||||
|
|
||||||
|
#include <protoc-c/c_field.h>
|
||||||
|
#include <protoc-c/c_primitive_field.h>
|
||||||
|
#include <protoc-c/c_string_field.h>
|
||||||
|
#include <protoc-c/c_bytes_field.h>
|
||||||
|
#include <protoc-c/c_enum_field.h>
|
||||||
|
#include <protoc-c/c_message_field.h>
|
||||||
|
#include <protoc-c/c_helpers.h>
|
||||||
|
#include <protobuf-c/protobuf-c.pb.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace c {
|
||||||
|
|
||||||
|
FieldGenerator::~FieldGenerator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static bool is_packable_type(FieldDescriptor::Type type)
|
||||||
|
{
|
||||||
|
return type == FieldDescriptor::TYPE_DOUBLE
|
||||||
|
|| type == FieldDescriptor::TYPE_FLOAT
|
||||||
|
|| type == FieldDescriptor::TYPE_INT64
|
||||||
|
|| type == FieldDescriptor::TYPE_UINT64
|
||||||
|
|| type == FieldDescriptor::TYPE_INT32
|
||||||
|
|| type == FieldDescriptor::TYPE_FIXED64
|
||||||
|
|| type == FieldDescriptor::TYPE_FIXED32
|
||||||
|
|| type == FieldDescriptor::TYPE_BOOL
|
||||||
|
|| type == FieldDescriptor::TYPE_UINT32
|
||||||
|
|| type == FieldDescriptor::TYPE_ENUM
|
||||||
|
|| type == FieldDescriptor::TYPE_SFIXED32
|
||||||
|
|| type == FieldDescriptor::TYPE_SFIXED64
|
||||||
|
|| type == FieldDescriptor::TYPE_SINT32
|
||||||
|
|| type == FieldDescriptor::TYPE_SINT64;
|
||||||
|
//TYPE_BYTES
|
||||||
|
//TYPE_STRING
|
||||||
|
//TYPE_GROUP
|
||||||
|
//TYPE_MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer,
|
||||||
|
bool optional_uses_has,
|
||||||
|
const std::string &type_macro,
|
||||||
|
const std::string &descriptor_addr) const
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> variables;
|
||||||
|
const OneofDescriptor *oneof = descriptor_->containing_oneof();
|
||||||
|
const ProtobufCFileOptions opt = descriptor_->file()->options().GetExtension(pb_c_file);
|
||||||
|
variables["TYPE"] = type_macro;
|
||||||
|
variables["classname"] = FullNameToC(FieldScope(descriptor_)->full_name(), FieldScope(descriptor_)->file());
|
||||||
|
variables["name"] = FieldName(descriptor_);
|
||||||
|
if (opt.use_oneof_field_name())
|
||||||
|
variables["proto_name"] = oneof->name();
|
||||||
|
else
|
||||||
|
variables["proto_name"] = descriptor_->name();
|
||||||
|
variables["descriptor_addr"] = descriptor_addr;
|
||||||
|
variables["value"] = SimpleItoa(descriptor_->number());
|
||||||
|
if (oneof != NULL)
|
||||||
|
variables["oneofname"] = CamelToLower(oneof->name());
|
||||||
|
|
||||||
|
if (FieldSyntax(descriptor_) == 3 &&
|
||||||
|
descriptor_->label() == FieldDescriptor::LABEL_OPTIONAL) {
|
||||||
|
variables["LABEL"] = "NONE";
|
||||||
|
optional_uses_has = false;
|
||||||
|
} else {
|
||||||
|
variables["LABEL"] = CamelToUpper(GetLabelName(descriptor_->label()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor_->has_default_value()) {
|
||||||
|
variables["default_value"] = std::string("&")
|
||||||
|
+ FullNameToLower(descriptor_->full_name(), descriptor_->file())
|
||||||
|
+ "__default_value";
|
||||||
|
} else if (FieldSyntax(descriptor_) == 3 &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
variables["default_value"] = "&protobuf_c_empty_string";
|
||||||
|
} else {
|
||||||
|
variables["default_value"] = "NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
variables["flags"] = "0";
|
||||||
|
|
||||||
|
if (descriptor_->label() == FieldDescriptor::LABEL_REPEATED
|
||||||
|
&& is_packable_type (descriptor_->type())
|
||||||
|
&& descriptor_->options().packed()) {
|
||||||
|
variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_PACKED";
|
||||||
|
} else if (descriptor_->label() == FieldDescriptor::LABEL_REPEATED
|
||||||
|
&& is_packable_type (descriptor_->type())
|
||||||
|
&& FieldSyntax(descriptor_) == 3
|
||||||
|
&& !descriptor_->options().has_packed()) {
|
||||||
|
variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_PACKED";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor_->options().deprecated())
|
||||||
|
variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_DEPRECATED";
|
||||||
|
|
||||||
|
if (oneof != NULL)
|
||||||
|
variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_ONEOF";
|
||||||
|
|
||||||
|
printer->Print("{\n");
|
||||||
|
if (descriptor_->file()->options().has_optimize_for() &&
|
||||||
|
descriptor_->file()->options().optimize_for() ==
|
||||||
|
FileOptions_OptimizeMode_CODE_SIZE) {
|
||||||
|
printer->Print(" NULL, /* CODE_SIZE */\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables, " \"$proto_name$\",\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables,
|
||||||
|
" $value$,\n"
|
||||||
|
" PROTOBUF_C_LABEL_$LABEL$,\n"
|
||||||
|
" PROTOBUF_C_TYPE_$TYPE$,\n");
|
||||||
|
switch (descriptor_->label()) {
|
||||||
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
printer->Print(variables, " 0, /* quantifier_offset */\n");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_OPTIONAL:
|
||||||
|
if (oneof != NULL) {
|
||||||
|
printer->Print(variables, " offsetof($classname$, $oneofname$_case),\n");
|
||||||
|
} else if (optional_uses_has) {
|
||||||
|
printer->Print(variables, " offsetof($classname$, has_$name$),\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables, " 0, /* quantifier_offset */\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::LABEL_REPEATED:
|
||||||
|
printer->Print(variables, " offsetof($classname$, n_$name$),\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printer->Print(variables, " offsetof($classname$, $name$),\n");
|
||||||
|
printer->Print(variables, " $descriptor_addr$,\n");
|
||||||
|
printer->Print(variables, " $default_value$,\n");
|
||||||
|
printer->Print(variables, " $flags$, /* flags */\n");
|
||||||
|
printer->Print(variables, " 0,NULL,NULL /* reserved1,reserved2, etc */\n");
|
||||||
|
printer->Print("},\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
field_generators_(
|
||||||
|
new std::unique_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||||
|
// Construct all the FieldGenerators.
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
|
field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
|
||||||
|
const ProtobufCFieldOptions opt = field->options().GetExtension(pb_c_field);
|
||||||
|
switch (field->type()) {
|
||||||
|
case FieldDescriptor::TYPE_MESSAGE:
|
||||||
|
return new MessageFieldGenerator(field);
|
||||||
|
case FieldDescriptor::TYPE_STRING:
|
||||||
|
if (opt.string_as_bytes())
|
||||||
|
return new BytesFieldGenerator(field);
|
||||||
|
else
|
||||||
|
return new StringFieldGenerator(field);
|
||||||
|
case FieldDescriptor::TYPE_BYTES:
|
||||||
|
return new BytesFieldGenerator(field);
|
||||||
|
case FieldDescriptor::TYPE_ENUM:
|
||||||
|
return new EnumFieldGenerator(field);
|
||||||
|
case FieldDescriptor::TYPE_GROUP:
|
||||||
|
return 0; // XXX
|
||||||
|
default:
|
||||||
|
return new PrimitiveFieldGenerator(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGeneratorMap::~FieldGeneratorMap() {}
|
||||||
|
|
||||||
|
const FieldGenerator& FieldGeneratorMap::get(
|
||||||
|
const FieldDescriptor* field) const {
|
||||||
|
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
|
||||||
|
return *field_generators_[field->index()];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace c
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user