From 0c11bff25e1f12e060e3acb0f87445d2c0a3b5f6 Mon Sep 17 00:00:00 2001 From: AI Dev Date: Sat, 19 Sep 2026 07:09:02 +0000 Subject: [PATCH 1/2] Per-device settings: the three files that teach an image its board A mainline image is built for an SoC family, so it knows nothing about where a particular camera's IR-cut filter is wired or which pad powers its SD card. Three files supply that, and none of them were documented anywhere: a reader could find en/gpio-settings.md listing a board's pin numbers and had no page telling them where those numbers are supposed to go. The consequence shows up in review. Somebody with a new camera writes a fresh init script with the pin numbers typed into it, or drops a customizer.sh into the shared firmware overlay where it reaches every camera of every vendor, because nothing pointed at the seam that already exists. That is not a mistake a contributor can be expected to avoid unaided. The page covers what runs when -- customizer.sh once behind /etc/custom.ok, muxes.sh on every boot because pad multiplexing does not survive a power cycle, gpio.conf sourced rather than executed -- what belongs in each, and why they live in OpenIPC/builder under the device's own directory rather than in the firmware tree. It ends with a worked example and the four things that actually go wrong, including the one that catches everyone: a factory reset clears the overlay and with it /etc/custom.ok, so the device re-applies its defaults from scratch on the next boot. Figures in the page were counted from builder as it stands: 96 devices ship a customizer.sh, 18 a gpio.conf, 15 a muxes.sh, and seven pin names appear in every one of those gpio.conf files. Cross-linked both ways with gpio-settings.md and finding-a-gpio.md, which are where a reader arrives with a pin number and no idea what to do with it. --- README.md | 1 + en/finding-a-gpio.md | 6 + en/gpio-settings.md | 6 + en/per-device-settings.md | 289 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 en/per-device-settings.md diff --git a/README.md b/README.md index c9e777ca..b5cd9eda 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ OpenIPC Wiki - [Using ipctool](en/example-ipctool.md) - [Board specific GPIO settings list](en/gpio-settings.md) - [Finding out what a pin is wired to](en/finding-a-gpio.md) +- [Per-device settings: customizer.sh, muxes.sh and gpio.conf](en/per-device-settings.md) - [ACMEv2](en/acme-v2.md) - [WiFi XM530](en/wifi-xm530.md) - [How an IR-cut filter is driven](en/ircut-filter.md) diff --git a/en/finding-a-gpio.md b/en/finding-a-gpio.md index 92becb07..236bb654 100644 --- a/en/finding-a-gpio.md +++ b/en/finding-a-gpio.md @@ -274,3 +274,9 @@ a job: For the day/night filter, the two coil pins belong on **Settings → Day / Night** instead, where **Test the filter** can adjudicate them — the hunt proposes, the test decides. If the test says *wired backwards*, swap the two coils there. + +--- + +What to do with the answer: a pin you have identified belongs in the device's own +`gpio.conf`, so every script on that camera refers to it by name. See +[Per-device settings: customizer.sh, muxes.sh and gpio.conf](per-device-settings.md). diff --git a/en/gpio-settings.md b/en/gpio-settings.md index 27697b52..48eb626a 100644 --- a/en/gpio-settings.md +++ b/en/gpio-settings.md @@ -334,3 +334,9 @@ PTZ via OpenIPC `gpio-motors`: `fw_setenv gpio_motors '3 4 72 73 69 59 58 57'` | Processor | IRCUT1 | IRCUT2 | IRSTATUS | DEVICE ID | |-------------|--------|--------|--------------|---------------| | Hi3518Ev200 | 61 | 60 | 1 (inverted) | ZG2622MW | + +--- + +Once you know a board's numbers, record them on the device rather than typing them +into each script that needs them: see +[Per-device settings: customizer.sh, muxes.sh and gpio.conf](per-device-settings.md). diff --git a/en/per-device-settings.md b/en/per-device-settings.md new file mode 100644 index 00000000..de2f232b --- /dev/null +++ b/en/per-device-settings.md @@ -0,0 +1,289 @@ +# OpenIPC Wiki +[Table of Content](../README.md) + +Per-device settings: `customizer.sh`, `muxes.sh` and `gpio.conf` +================================================================ + +A mainline OpenIPC image is built for an SoC family, not for a camera. It has to boot on +any board with that chip, so it ships no knowledge of where *your* camera's IR-cut filter +is wired, which pad powers its SD card, or where it should fetch its next firmware from. + +Three files supply exactly that, and they are the reason a supported retail camera comes +up already knowing its own hardware: + +| File | Runs | Use it for | +| --- | --- | --- | +| `/usr/share/openipc/customizer.sh` | once, on first boot | settings that should persist: bootloader environment, streamer configuration, extra accounts | +| `/usr/share/openipc/muxes.sh` | every boot | pad multiplexing and GPIO states that do not survive a power cycle | +| `/usr/share/openipc/gpio.conf` | never — it is sourced | naming the pins, so scripts refer to `$ircut1` rather than `67` | + +All three are optional. An image without them boots perfectly well; it simply knows +nothing about the board it is on. + +> **These files belong in [OpenIPC/builder](https://github.com/OpenIPC/builder), not in +> OpenIPC/firmware.** `general/overlay/` in the firmware tree is copied verbatim into +> *every* image the tree builds, so a `customizer.sh` placed there sets your camera's +> sensor, upgrade URL and pin numbers on every camera of every vendor. In builder each +> file sits under `devices//general/overlay/usr/share/openipc/` and reaches only +> that board. See [Where they live](#where-they-live) below. + +## When each one runs + +`/etc/init.d/S30customizer` is what calls them. `rcS` runs the `S??*` scripts in sorted +order, so S30 lands after logging and the clock are up and before the hostname, kernel +modules, networking and the streamer: + +``` +S01syslogd → S02fakehwclock → S29debugfs → S29pstore → S30customizer → +S31hostname → S35modules → S38mdev → S40network → … → S95majestic → S99rc.local +``` + +That position is deliberate. Settings written by `customizer.sh` are in place before +anything reads them: `S40network` picks up the wireless credentials, and the streamer +starts long afterwards with whatever configuration was written. + +`S30customizer` does four things in order: + +1. If `/etc/custom.ok` does **not** exist and `customizer.sh` does, run it, then create + `/etc/custom.ok`. +2. If `/etc/network.ok` does **not** exist and `wireless.sh` does, run it, then create + `/etc/network.ok`. (This hook is supported but no device currently ships one.) +3. If `muxes.sh` exists, run it — **every boot**, with no marker file. +4. Repair the camera's MAC address if it needs one. + +## `customizer.sh` — the one-time setup + +This is a plain shell script run once, in full, as root. There is no schema and no +special vocabulary: whatever you would type at a shell, you can put here. + +Three kinds of thing are worth putting in it. + +**Bootloader environment**, via `fw_setenv`. These survive reflashing the rootfs, which +is why they are the right home for a board's identity. Across the 96 devices in builder +that ship a `customizer.sh`, the common ones are: + +| Variable | Set by | What it does | +| --- | --- | --- | +| `upgrade` | 95 devices | the URL `sysupgrade` fetches this board's firmware from | +| `wlandev` | 77 | which wireless profile `/etc/wireless/usb` should use | +| `wlanssid`, `wlanpass` | 68 | network credentials, if the device ships with any | +| `osmem`, `rmem`, `totalmem` | 33 / 25 / 3 | the memory split — see [Memory tuning](memory-tuning.md) | +| `sensor` | 10 | the image sensor, when autodetection cannot find it | + +`rcS` reads `sensor` and `upgrade` into the environment at every boot, so a value set +here is visible to everything that starts afterwards. Note that the reset button is +*not* one of these: it is named in `gpio.conf` as `button`, and read from there by the +device's own reset daemon. + +**Streamer configuration**, via `cli -s`. Anything you would otherwise set through the +web interface can be preset: + +```sh +cli -s .image.mirror true +cli -s .image.flip true +cli -s .nightMode.irCutPin1 52 +cli -s .nightMode.irCutPin2 53 +cli -s .nightMode.backlightPin 4 +cli -s .audio.enabled true +``` + +> `cli -s` cannot fail. It stores whatever key path you hand it and exits 0, and a key +> the streamer does not recognise is simply ignored — for the life of the device. A typo +> such as a trailing colon costs you the setting silently, so check the spelling of every +> path you add. [Majestic example config](majestic-config.md) lists the real ones. + +**Anything else a first boot should do** — creating a limited viewer account, for +instance. It is a shell script. + +### Running it again + +`/etc/custom.ok` is the marker that stops it re-running. It lives in the writable overlay +mounted over the root filesystem, so: + +- to re-run the script on the next boot by hand: `rm /etc/custom.ok && reboot` +- a **factory reset** clears the whole overlay, and `/etc/custom.ok` with it, so the + script runs again on the boot after — see + [Factory reset and the unclaimed camera](first-boot.md) + +That second point is the one that surprises people: a factory reset does not just forget +your settings, it re-applies the device's defaults from scratch. + +## `muxes.sh` — the every-boot part + +Pad multiplexing and GPIO output states are hardware registers. They reset when the +camera loses power, so unlike the bootloader environment they cannot be set once — which +is why this script has no marker file and runs on every boot. + +Keep it to what genuinely must be re-applied: putting a pad into the right function, +powering a peripheral on, setting an LED's initial state. + +```sh +#!/bin/sh + +### set leds power off ### +gpio set 10 +gpio set 25 + +### sd card power en ### +devmem 0x100c0058 32 0 +gpio set 38 +``` + +The `gpio` helper takes `set` (drive high), `clear` (drive low), `toggle`, `read` and +`unexport`, and exports the pin and sets its direction for you on first use. See +[Finding out what a pin is wired to](finding-a-gpio.md) if you do not yet know your +board's numbers, and [Board specific GPIO settings list](gpio-settings.md) for boards +somebody has already mapped. + +## `gpio.conf` — naming the pins + +A bare `gpio set 38` in three different scripts is three chances to get it wrong, and +nothing to grep for when the board revision moves a pad. `gpio.conf` gives the pins +names. It is not executed — it is *sourced*, so it is a list of shell variables: + +```sh +alarm_in=-1 +alarm_out=-1 +button=64 +ircut1=63 +ircut2=67 +led1=10 +led2=25 +light_ir=72 +light_wl=-1 +light_sensor=-1 +mmc_pwr=38 +speaker=28 +usb=7 +``` + +Seven names appear on every one of the 18 devices that ship a `gpio.conf` — `button`, +`ircut1`, `ircut2`, `led1`, `led2`, `light_ir` and `mmc_pwr`. Six more are almost as +common: `alarm_in`, `alarm_out`, `light_wl`, `speaker` and `usb` on 17, and +`light_sensor` on 16. Individual boards add their own (`led3`, `relay`, `motors`, +`pir_sensor`) — nothing validates the list, so a name only matters to the scripts that +read it. + +**`-1` means the board does not have that pin.** Keep the line rather than deleting it: +it records that somebody looked and the answer was "absent", which is information the +next person needs. + +To use it, source it and then refer to the names: + +```sh +#!/bin/sh +. /usr/share/openipc/gpio.conf + +# sd card power enable +gpio clear $mmc_pwr +``` + +Consumers guard the include, because the file is optional: + +```sh +if [ -e /usr/share/openipc/gpio.conf ]; then + . /usr/share/openipc/gpio.conf +fi +``` + +Both `muxes.sh` and per-device helper scripts such as a reset-button daemon use it, and +so does the QR-code Wi-Fi provisioning script in the firmware tree, which blinks `$led1` +while it scans. + +## Where they live + +In [OpenIPC/builder](https://github.com/OpenIPC/builder), under the device's own +directory, at the same paths they will occupy on the camera: + +``` +devices/__-/ +└── general/ + ├── overlay/ + │ └── usr/share/openipc/ + │ ├── customizer.sh + │ ├── muxes.sh + │ └── gpio.conf + └── scripts/ + └── excludes/_.list +``` + +When builder builds that device it copies the contents of `devices//` over a fresh +checkout of the firmware tree, so `devices//general/overlay/...` becomes +`general/overlay/...` and is picked up as part of the rootfs overlay like anything else. +That is why the paths match: the device directory is a patch over the firmware tree, +applied for one board only. + +The same directory is where a per-device *exclusion list* goes — the list of files to +strip from that board's rootfs to fit its flash. Note that the list is keyed by +`_` and not by device, so it must live in the device directory to be +per-board; the same file placed in the firmware tree would prune the generic image for +that SoC too. + +## A minimal worked example + +For a camera whose IR-cut filter is on pins 63 and 67, whose status LED is pin 10, and +whose SD-card power needs enabling at every boot: + +`gpio.conf` + +```sh +button=64 +ircut1=63 +ircut2=67 +led1=10 +led2=-1 +light_ir=72 +light_wl=-1 +light_sensor=-1 +mmc_pwr=38 +speaker=-1 +usb=-1 +alarm_in=-1 +alarm_out=-1 +``` + +`muxes.sh` + +```sh +#!/bin/sh +. /usr/share/openipc/gpio.conf + +# SD card power rail — resets on every power cycle +gpio set $mmc_pwr +``` + +`customizer.sh` + +```sh +#!/bin/sh +# +# Perform basic settings on a known IP camera +# +fw_setenv sensor sc2335 +fw_setenv upgrade 'https://github.com/OpenIPC/builder/releases/download/latest/-nor.tgz' +# +# Tell the streamer where the IR-cut actuator is +# +cli -s .nightMode.irCutPin1 63 +cli -s .nightMode.irCutPin2 67 +cli -s .nightMode.backlightPin 72 + +exit 0 +``` + +## Troubleshooting + +**Nothing happened on first boot.** The scripts are only run if they exist at those exact +paths. Check them on the camera with `ls -l /usr/share/openipc/`, and look for the +`Run customizer script...` and `Run custom muxes & gpios preset script...` lines in the +boot log. + +**It ran once and now it will not.** That is `/etc/custom.ok` doing its job. Remove it and +reboot. + +**A `cli -s` setting did not take.** Re-read the key path character by character. The +write succeeds whatever you type, so a wrong path is silent. + +**A GPIO does not do what you expect.** Confirm the number first with +[Finding out what a pin is wired to](finding-a-gpio.md) — a pad that is multiplexed to +something other than GPIO will accept `gpio set` and change nothing visible. From 8c84dcbe3a0212556e9138b2a09bd0057419af62 Mon Sep 17 00:00:00 2001 From: AI Dev Date: Sat, 19 Sep 2026 07:18:39 +0000 Subject: [PATCH 2/2] Cover both routes equally, and stop contradicting myself on rail polarity The page presented device profiles as the way to tell a camera about its hardware, with the web interface mentioned only in passing. That is backwards for most readers: somebody with one camera in front of them sets the IR-cut pins on Settings -> Day / Night and declares a pad on Settings -> Pins, and never writes a file at all. The three profile files are for the person who wants the hundredth unit of a model to come up right with nobody there. Both now get a section of their own, with a table up front so a reader can tell in one glance which one they want. The honest framing is that they are not alternatives: a profile mostly consists of the very writes the interface would have made. The one real difference is worth its own row and its own troubleshooting entry, because it catches people -- a factory reset clears the overlay, so settings made on the camera do not come back and settings carried by a profile do. Retitled accordingly, since "customizer.sh, muxes.sh and gpio.conf" no longer describes half of what the page covers, and relinked from the table of contents and the two GPIO pages. The bot review caught a real contradiction: the gpio.conf snippet drove mmc_pwr low as "power enable" while the worked example drove the same named rail high. Both were copied from real devices, so the fix is not to pick one -- polarity is board-specific and gpio.conf records which pad, never which level. Said so, with both examples now labelled which way their board goes. Also removed a duplicated warning about cli -s silently accepting a mistyped path; it belongs with the settings route, and the profile section now points back at it with the reason it is worse there -- nobody is at the interface to notice the switch did nothing. --- README.md | 2 +- en/finding-a-gpio.md | 7 ++- en/gpio-settings.md | 7 ++- en/per-device-settings.md | 126 ++++++++++++++++++++++++++++++++------ 4 files changed, 117 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index b5cd9eda..fadb53e1 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ OpenIPC Wiki - [Using ipctool](en/example-ipctool.md) - [Board specific GPIO settings list](en/gpio-settings.md) - [Finding out what a pin is wired to](en/finding-a-gpio.md) -- [Per-device settings: customizer.sh, muxes.sh and gpio.conf](en/per-device-settings.md) +- [Telling a camera about its own hardware](en/per-device-settings.md) - [ACMEv2](en/acme-v2.md) - [WiFi XM530](en/wifi-xm530.md) - [How an IR-cut filter is driven](en/ircut-filter.md) diff --git a/en/finding-a-gpio.md b/en/finding-a-gpio.md index 236bb654..186fdbaf 100644 --- a/en/finding-a-gpio.md +++ b/en/finding-a-gpio.md @@ -277,6 +277,7 @@ test decides. If the test says *wired backwards*, swap the two coils there. --- -What to do with the answer: a pin you have identified belongs in the device's own -`gpio.conf`, so every script on that camera refers to it by name. See -[Per-device settings: customizer.sh, muxes.sh and gpio.conf](per-device-settings.md). +What to do with the answer, beyond the settings pages above: a pin that should be +known to *every* unit of a model belongs in that device's profile rather than being +re-entered on each camera. See +[Telling a camera about its own hardware](per-device-settings.md). diff --git a/en/gpio-settings.md b/en/gpio-settings.md index 48eb626a..471aa1c0 100644 --- a/en/gpio-settings.md +++ b/en/gpio-settings.md @@ -337,6 +337,7 @@ PTZ via OpenIPC `gpio-motors`: `fw_setenv gpio_motors '3 4 72 73 69 59 58 57'` --- -Once you know a board's numbers, record them on the device rather than typing them -into each script that needs them: see -[Per-device settings: customizer.sh, muxes.sh and gpio.conf](per-device-settings.md). +Once you know a board's numbers, put them where the camera will read them — on +**Settings → Pins** and **Settings → Day / Night** for one camera, or in a device +profile so every unit of the model comes up knowing them. Both routes: +[Telling a camera about its own hardware](per-device-settings.md). diff --git a/en/per-device-settings.md b/en/per-device-settings.md index de2f232b..52c07852 100644 --- a/en/per-device-settings.md +++ b/en/per-device-settings.md @@ -1,15 +1,84 @@ # OpenIPC Wiki [Table of Content](../README.md) -Per-device settings: `customizer.sh`, `muxes.sh` and `gpio.conf` -================================================================ +Telling a camera about its own hardware +======================================= A mainline OpenIPC image is built for an SoC family, not for a camera. It has to boot on any board with that chip, so it ships no knowledge of where *your* camera's IR-cut filter is wired, which pad powers its SD card, or where it should fetch its next firmware from. -Three files supply exactly that, and they are the reason a supported retail camera comes -up already knowing its own hardware: +There are **two ways** to tell it, and which one you want depends on whether you are +setting up a camera or supporting a model. + +| | [Through the camera's own settings](#through-the-cameras-own-settings) | [Through a device profile](#through-a-device-profile) | +| --- | --- | --- | +| **Who does it** | whoever has the camera | whoever maintains support for that model | +| **How** | the web interface, or `cli` over SSH | three files in [OpenIPC/builder](https://github.com/OpenIPC/builder) | +| **Applies to** | that one camera | every unit of that model, on first boot | +| **Takes effect** | immediately | before the streamer ever starts | +| **Survives a reboot** | yes | yes | +| **Survives a factory reset** | **no** — settings go with the overlay | **yes** — the profile re-applies them | +| **Needs a rebuild** | no | yes, the image is rebuilt for that device | + +They are not alternatives so much as the same settings arriving by different routes: a +device profile mostly consists of the very writes the web interface would have made, made +for you before you ever open it. Read the first section if you have a camera in front of +you; read the second if you want the next hundred units of that model to come up right +with nobody touching them. + +--- + +Through the camera's own settings +--------------------------------- + +Most of what a camera needs to know about its own hardware is an ordinary setting, and +the web interface is where you set it. Nothing here involves files, a rebuild, or a +shell. + +**Settings → Pins** draws the chip and lets you say what is soldered to each pad — a +lamp, a button, a sensor bus. You can **Try it** first, and **Keep** it once you are +happy; a kept choice is saved on the camera rather than needing a boot script to +re-apply it, which is the part a hand-written `devmem` line never managed. + +**Settings → Day / Night** is where the IR-cut filter's two coil pins, the infrared +lamp and a light sensor go, and it can test the filter and tell you if the coils are +wired backwards. + +If you do not yet know which pad is which, the camera will find out for you — see +[Finding out what a pin is wired to](finding-a-gpio.md), which covers both hunts, what +the camera refuses to drive and why, and what to do when it comes up empty. + +The same settings are reachable over SSH with `cli`, which is useful for scripting and +is exactly what a device profile uses: + +```sh +cli -s .nightMode.irCutPin1 63 +cli -s .nightMode.irCutPin2 67 +cli -s .nightMode.backlightPin 72 +cli -g .nightMode.irCutPin1 # read one back +``` + +> `cli -s` cannot fail. It stores whatever key path you hand it and exits 0, and a key +> the streamer does not recognise is simply ignored — for the life of the device. A typo +> such as a trailing colon costs you the setting silently, so check the spelling of every +> path you add. [Majestic example config](majestic-config.md) lists the real ones. The +> web interface does not have this problem: it only offers paths that exist. + +**Where these settings live, and what erases them.** They are written into the streamer's +configuration file, which sits in the writable overlay on top of the read-only root +filesystem. A reboot keeps them. A **factory reset** clears that overlay, and your +settings go with it — the camera comes back with whatever its image shipped. That is the +single biggest practical difference between the two routes, and the reason a model with +real support behind it uses the second one. + +--- + +Through a device profile +------------------------ + +A device profile is how a camera model comes up already knowing its own hardware, with +nobody opening the web interface at all. It is three files: | File | Runs | Use it for | | --- | --- | --- | @@ -18,7 +87,7 @@ up already knowing its own hardware: | `/usr/share/openipc/gpio.conf` | never — it is sourced | naming the pins, so scripts refer to `$ircut1` rather than `67` | All three are optional. An image without them boots perfectly well; it simply knows -nothing about the board it is on. +nothing about the board it is on, and everything above has to be done by hand. > **These files belong in [OpenIPC/builder](https://github.com/OpenIPC/builder), not in > OpenIPC/firmware.** `general/overlay/` in the firmware tree is copied verbatim into @@ -27,7 +96,7 @@ nothing about the board it is on. > file sits under `devices//general/overlay/usr/share/openipc/` and reaches only > that board. See [Where they live](#where-they-live) below. -## When each one runs +### When each one runs `/etc/init.d/S30customizer` is what calls them. `rcS` runs the `S??*` scripts in sorted order, so S30 lands after logging and the clock are up and before the hostname, kernel @@ -51,7 +120,7 @@ starts long afterwards with whatever configuration was written. 3. If `muxes.sh` exists, run it — **every boot**, with no marker file. 4. Repair the camera's MAC address if it needs one. -## `customizer.sh` — the one-time setup +### `customizer.sh` — the one-time setup This is a plain shell script run once, in full, as root. There is no schema and no special vocabulary: whatever you would type at a shell, you can put here. @@ -87,15 +156,16 @@ cli -s .nightMode.backlightPin 4 cli -s .audio.enabled true ``` -> `cli -s` cannot fail. It stores whatever key path you hand it and exits 0, and a key -> the streamer does not recognise is simply ignored — for the life of the device. A typo -> such as a trailing colon costs you the setting silently, so check the spelling of every -> path you add. [Majestic example config](majestic-config.md) lists the real ones. +These are the same writes described under +[Through the camera's own settings](#through-the-cameras-own-settings), and they carry +the same caution: a mistyped path is stored and ignored rather than rejected, so it costs +you the setting silently. Presetting from a profile makes that worse, not better — there +is no one at the web interface to notice the switch did nothing. **Anything else a first boot should do** — creating a limited viewer account, for instance. It is a shell script. -### Running it again +#### Running it again `/etc/custom.ok` is the marker that stops it re-running. It lives in the writable overlay mounted over the root filesystem, so: @@ -108,7 +178,7 @@ mounted over the root filesystem, so: That second point is the one that surprises people: a factory reset does not just forget your settings, it re-applies the device's defaults from scratch. -## `muxes.sh` — the every-boot part +### `muxes.sh` — the every-boot part Pad multiplexing and GPIO output states are hardware registers. They reset when the camera loses power, so unlike the bootloader environment they cannot be set once — which @@ -135,7 +205,7 @@ The `gpio` helper takes `set` (drive high), `clear` (drive low), `toggle`, `read board's numbers, and [Board specific GPIO settings list](gpio-settings.md) for boards somebody has already mapped. -## `gpio.conf` — naming the pins +### `gpio.conf` — naming the pins A bare `gpio set 38` in three different scripts is three chances to get it wrong, and nothing to grep for when the board revision moves a pad. `gpio.conf` gives the pins @@ -174,10 +244,16 @@ To use it, source it and then refer to the names: #!/bin/sh . /usr/share/openipc/gpio.conf -# sd card power enable +# SD card power rail — this board enables it by driving the pad low gpio clear $mmc_pwr ``` +> **Polarity is board-specific, and the name does not tell you which way round it is.** +> `mmc_pwr` is enabled by `gpio clear` on the board above and by `gpio set` on the one in +> [the worked example](#a-minimal-worked-example) below; both are real devices. `gpio.conf` +> records *which pad*, never *which level* — so check your board rather than copying a +> line, and say in a comment which way yours goes. + Consumers guard the include, because the file is optional: ```sh @@ -190,7 +266,7 @@ Both `muxes.sh` and per-device helper scripts such as a reset-button daemon use so does the QR-code Wi-Fi provisioning script in the firmware tree, which blinks `$led1` while it scans. -## Where they live +### Where they live In [OpenIPC/builder](https://github.com/OpenIPC/builder), under the device's own directory, at the same paths they will occupy on the camera: @@ -248,7 +324,8 @@ alarm_out=-1 #!/bin/sh . /usr/share/openipc/gpio.conf -# SD card power rail — resets on every power cycle +# SD card power rail — this board enables it high, and it resets on every +# power cycle, so it has to be re-applied rather than set once gpio set $mmc_pwr ``` @@ -271,8 +348,20 @@ cli -s .nightMode.backlightPin 72 exit 0 ``` +For a single camera you would reach the same end state without any of these files: set +the three pins on **Settings → Day / Night**, the sensor and upgrade URL are already +right for the image you flashed, and the SD-card rail is one line in a startup script or +a pad you declare on **Settings → Pins**. The profile's value is not that it can do +something the interface cannot — it is that the hundredth unit of this model does it +without anyone being there, and does it again after a factory reset. + ## Troubleshooting +**A setting I made in the web interface is gone.** A factory reset clears the overlay, +and the streamer's configuration lives there. Settings made on the camera do not come +back; settings carried by a device profile do, because `customizer.sh` runs again on the +next boot. If you want a setting to survive resets, it has to be in the profile. + **Nothing happened on first boot.** The scripts are only run if they exist at those exact paths. Check them on the camera with `ls -l /usr/share/openipc/`, and look for the `Run customizer script...` and `Run custom muxes & gpios preset script...` lines in the @@ -282,7 +371,8 @@ boot log. reboot. **A `cli -s` setting did not take.** Re-read the key path character by character. The -write succeeds whatever you type, so a wrong path is silent. +write succeeds whatever you type, so a wrong path is silent. Setting the same thing once +through the web interface is the quickest way to find out what the path should be. **A GPIO does not do what you expect.** Confirm the number first with [Finding out what a pin is wired to](finding-a-gpio.md) — a pad that is multiplexed to