Skip to content

hal: add Fullhan FH8852/FH8856 (V100) support - #43

Open
kasperiio wants to merge 2 commits into
OpenIPC:masterfrom
kasperiio:divinus-fh-hal
Open

hal: add Fullhan FH8852/FH8856 (V100) support#43
kasperiio wants to merge 2 commits into
OpenIPC:masterfrom
kasperiio:divinus-fh-hal

Conversation

@kasperiio

Copy link
Copy Markdown
Contributor

A HAL for the Fullhan V100 generation (FH8852/FH8856, ARM1176, ARMv6), driving the vendor SDK's libdsp / libisp / libvmm through dlopen, with a GalaxyCore GC4653 sensor driver. There is no public SDK header set for these parts; the interfaces here were derived from the vendor application's behaviour and verified on hardware.

Identification is by chip_name in /proc/driver/chip, where the vendor kernel reports FH8852/FH8856. The whole platform is gated on __ARM_ARCH == 6, so no other ARM build changes.

Note on the SoC generation. FH8856 on plat_id 0x17092901 is the V100 part (pkg_id & 0xF == 0xD); FH8856V200 is a different platform id entirely. Building this board as V200 hangs the SoC in fh_pinctrl_init_devices(), misreads PLL2 and corrupts the console baud — worth stating because the naming invites the mistake.

Points worth a reviewer's attention, each commented at the point of use:

  • Frames are copied once out of the SDK's DMA buffer, which is mapped uncached. Every pass over it (start-code scans, RTP payload copies) reads at bus speed; a 300 KB keyframe cost about 400 ms of CPU before this.
  • HEVC parameter sets: the encoder bundles VPS, SPS and PPS into the IDR entry with 3-byte start codes inside it, so entries are split on start codes for the consumers that trust per-NALU boundaries.
  • H.264 profile: High (100) is rejected by FH_VENC_SetChnAttr with 0x19d and leaves the channel closed, so every profile maps to Main (77), as the vendor application does.
  • Channel lifetime: there is no FH_VENC_DestroyChn; a channel's memory pool lives until FH_SYS_Exit and a second CreateChn fails with -0x3f3. Channels are therefore created once with both codecs reserved and reconfigured afterwards.
  • gpio: the exported line's sysfs directory is GPIO<n> on these kernels rather than gpio<n>; probed once and cached. The same change corrects three open() error checks that tested !fd instead of fd < 0.
  • quirks: the Fullhan ISP library exports its own isp_malloc(), which the HiSilicon trampoline would shadow under -rdynamic, so it is left out of ARMv6 builds.
  • Audio init failure is a warning, not fatal, on this platform only: the SoC is watchdog-guarded, so aborting the SDK start turns a bad microphone configuration into a reboot loop.
  • Day/night can use the SDK's SmartIR (image gain) rather than an ADC, and a white lamp mode that keeps the IR-cut filter in for colour night vision.

Testing

Built for fh8856v100_lite and running from flash on three Fullhan FH8856 cameras (Vatilon PB1 / Asecam, GC4653): RTSP, ONVIF, the web UI, full-resolution snapshots, IR-cut switching and day/night. This branch is build-tested on its own; the hardware runs the combined branch it was split from, which is these three PRs together.

Depends on the two companion PRs only for merge order, not for compilation.

A HAL for the Fullhan V100 generation (ARM1176, ARMv6), driving the vendor
SDK's libdsp/libisp/libvmm through dlopen, with a GC4653 sensor driver.

Identification is by chip_name in /proc/driver/chip, which is where the vendor
kernel reports FH8852/FH8856; the platform is gated on __ARM_ARCH == 6 so no
other ARM build changes.

Notable points, all found on hardware and commented at the point of use:

- Video frames are copied once out of the SDK's uncached DMA buffer. Every pass
  over it reads at bus speed, and a 300 KB keyframe cost about 400 ms of CPU.
- The HEVC encoder bundles VPS, SPS and PPS into the IDR entry, so entries are
  split on start codes for the consumers that trust per-NALU boundaries.
- H.264 High profile is rejected by the encoder (0x19d) and would leave the
  channel closed, so every profile maps to Main.
- There is no FH_VENC_DestroyChn; a channel's pool lives until FH_SYS_Exit, so
  channels are created once with both codecs reserved and switched afterwards.
- gpio: the exported line's sysfs directory is GPIO<n> on these kernels rather
  than gpio<n>; probed and cached. The same commit corrects three open() error
  checks that tested !fd rather than fd < 0.
- quirks: the Fullhan ISP library exports its own isp_malloc(), which the
  trampoline would shadow under -rdynamic, so it is left out of ARMv6 builds.
- An audio init failure is a warning rather than fatal on this platform: the
  SoC is watchdog-guarded and aborting the SDK start means a reboot loop.
@kasperiio
kasperiio marked this pull request as ready for review September 5, 2026 16:59
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add Fullhan FH8852/FH8856 V100 HAL support

✨ Enhancement 🐞 Bug fix ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Adds an ARMv6 Fullhan V100 HAL for audio, imaging, encoding, overlays, and snapshots.
• Introduces GC4653 sensor control and hardware-verified vendor SDK compatibility shims.
• Extends day/night configuration with SmartIR, white-light mode, and Fullhan GPIO handling.
Diagram

graph TD
  A["Application Media"] --> B["HAL Dispatch"] --> C["Fullhan HAL"] --> D["Vendor SDK"]
  D --> E["ISP Pipeline"] --> F["GC4653 Sensor"]
  D --> G["VPSS Encoder"] --> H["Stream Consumers"]
Loading
High-Level Assessment

The dynamic wrapper approach is appropriate because the target SDK is binary-only and lacks public headers. It also matches the repository’s HAL boundaries while isolating ARMv6-specific ABI, symbol-collision, and hardware-lifecycle behavior; static linking or adapting another vendor HAL would increase coupling without removing the reverse-engineering requirement.

Files changed (23) +2581 / -12

Enhancement (18) +2448 / -1
fh_aud.hDefine the Fullhan audio SDK adapter +77/-0

Define the Fullhan audio SDK adapter

• Declares recovered audio configuration and frame ABIs. Dynamically loads capture, volume, initialization, and frame-retrieval symbols from 'libacw_mpi.so'.

src/hal/fh/fh_aud.h

fh_common.hDefine shared Fullhan HAL types +47/-0

Define shared Fullhan HAL types

• Introduces common channel limits, encoder and rate-control enums, dimensions, and documented SDK error values.

src/hal/fh/fh_common.h

fh_hal.cImplement the Fullhan V100 multimedia HAL +1154/-0

Implement the Fullhan V100 multimedia HAL

• Implements Fullhan system, audio, ISP, VPSS, encoder, overlay, snapshot, and day/night lifecycles. It handles persistent SDK channel pools, cached DMA frame copies, HEVC NALU splitting, SmartIR, lamp PWM, MJPEG fallback snapshots, and hardware-specific encoder constraints.

src/hal/fh/fh_hal.c

fh_hal.hExpose the Fullhan HAL interface +57/-0

Expose the Fullhan HAL interface

• Declares the Fullhan lifecycle, media channel, audio, image, overlay, snapshot, and day/night entry points used by application dispatch.

src/hal/fh/fh_hal.h

fh_isp.hDefine and load Fullhan ISP interfaces +226/-0

Define and load Fullhan ISP interfaces

• Models the recovered ISP, MIPI, sensor callback, SmartIR, and saturation ABIs. Loads required symbols from the vendor ISP libraries while treating optional SmartIR capabilities dynamically.

src/hal/fh/fh_isp.h

fh_snr.hIntroduce Fullhan sensor driver abstraction +25/-0

Introduce Fullhan sensor driver abstraction

• Defines the user-space sensor driver contract for probing, format selection, dimensions, and ISP callback creation. Registers the GC4653 implementation.

src/hal/fh/fh_snr.h

fh_snr_gc4653.cImplement the GC4653 Fullhan sensor driver +299/-0

Implement the GC4653 Fullhan sensor driver

• Adds I2C probing and register access for GC4653 sensors at two possible addresses. Implements gain, exposure, frame timing, orientation, MIPI setup, and 15–30 FPS format callbacks.

src/hal/fh/fh_snr_gc4653.c

fh_snr_gc4653_regs.hAdd GC4653 initialization and gain tables +132/-0

Add GC4653 initialization and gain tables

• Provides reference RAW10 two-lane MIPI register sequences for 15, 20, 25, and 30 FPS operation, plus analog and digital gain mappings.

src/hal/fh/fh_snr_gc4653_regs.h

fh_sys.hDefine the Fullhan system SDK adapter +61/-0

Define the Fullhan system SDK adapter

• Loads 'libvmm' and 'libdsp' in dependency order and exposes initialization, shutdown, version, and VPSS-to-encoder binding operations.

src/hal/fh/fh_sys.h

fh_venc.hDefine the Fullhan encoder SDK adapter +125/-0

Define the Fullhan encoder SDK adapter

• Declares recovered channel, rate-control, attribute, NALU, and stream layouts. Dynamically resolves H.264, H.265, MJPEG, and JPEG channel and stream functions.

src/hal/fh/fh_venc.h

fh_vpss.hDefine the Fullhan scaling SDK adapter +86/-0

Define the Fullhan scaling SDK adapter

• Declares VPSS dimensions, frame control, channel lifecycle, and output-mode interfaces and loads their 'libdsp' symbols.

src/hal/fh/fh_vpss.h

support.cDetect and register Fullhan V100 platforms +20/-0

Detect and register Fullhan V100 platforms

• Reads 'chip_name' from '/proc/driver/chip' on ARMv6 and identifies Fullhan hardware. It installs Fullhan channel state and audio, ISP, and video worker callbacks.

src/hal/support.c

support.hInclude Fullhan HAL for ARMv6 builds +3/-0

Include Fullhan HAL for ARMv6 builds

• Makes the Fullhan HAL declarations available only to matching ARMv6 soft-float builds.

src/hal/support.h

types.hAdd the Fullhan platform identifier +1/-0

Add the Fullhan platform identifier

• Adds 'HAL_PLATFORM_FH' to the shared platform enumeration for runtime dispatch.

src/hal/types.h

jpeg.cRoute snapshots through the Fullhan encoder +11/-0

Route snapshots through the Fullhan encoder

• Adds Fullhan handling for JPEG encoder creation, destruction, and snapshot frame retrieval.

src/jpeg.c

media.cIntegrate Fullhan into media lifecycle dispatch +71/-1

Integrate Fullhan into media lifecycle dispatch

• Routes audio, video, channels, callbacks, pipeline setup, tuning, and shutdown through the Fullhan HAL. Fullhan audio failures now disable audio without aborting startup and triggering watchdog reboot loops.

src/media.c

night.cAdd Fullhan SmartIR and lamp modes +38/-0

Add Fullhan SmartIR and lamp modes

• Uses ISP gain-based SmartIR when available and applies configurable thresholds at the vendor-required polling rate. Adds infrared, white-light color, and unilluminated night behaviors with Fullhan PWM control.

src/night.c

region.cRoute overlays through the Fullhan OSD plane +15/-0

Route overlays through the Fullhan OSD plane

• Adds Fullhan region creation, bitmap updates, and destruction to both overlay rendering paths.

src/region.c

Bug fix (3) +115 / -10
gpio.cSupport Fullhan GPIO sysfs naming +25/-10

Support Fullhan GPIO sysfs naming

• Probes and caches whether exported GPIO directories use 'GPIO<n>' or 'gpio<n>'. It also corrects three file-descriptor checks to recognize negative 'open()' failures.

src/gpio.c

fh_compat.cAvoid unsafe Fullhan kernel netlink queries +86/-0

Avoid unsafe Fullhan kernel netlink queries

• Overrides ARMv6 'getifaddrs()' with an ioctl-based IPv4 implementation because the vendor kernel crashes during netlink interface dumps. Provides matching allocation cleanup.

src/hal/fh/fh_compat.c

quirks.cPrevent ISP allocator collision on ARMv6 +4/-0

Prevent ISP allocator collision on ARMv6

• Excludes the HiSilicon 'isp_malloc' trampoline from ARMv6 builds so it cannot shadow the Fullhan ISP library’s allocator.

src/hal/hisi/quirks.c

Other (2) +18 / -1
app_config.cPersist and parse Fullhan night-mode options +15/-1

Persist and parse Fullhan night-mode options

• Adds SmartIR gain thresholds and lamp selection to night-mode configuration. It defaults the lamp to infrared and permits the sentinel sensor pin used when no external light sensor exists.

src/app_config.c

app_config.hDefine SmartIR and lamp configuration fields +3/-0

Define SmartIR and lamp configuration fields

• Extends AppConfig with the night illuminator mode and Fullhan SmartIR day/night gain thresholds.

src/app_config.h

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 5, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Lamp config buffer overflow ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new lamp value is parsed without a destination size into an 8-byte buffer, so any configured
value longer than seven characters overwrites adjacent AppConfig fields during startup. This can
corrupt configuration state or crash the process before the value is validated or used.
Code

src/app_config.c[R378-379]

+        parse_param_value(
+            &ini, "night_mode", "lamp", app_config.night_lamp);
Evidence
night_lamp is only eight bytes, while the newly added parser call passes it to
parse_param_value(), whose implementation writes the entire matched configuration value using
unbounded sprintf().

src/app_config.h[35-41]
src/app_config.c[375-382]
src/hal/config.c[58-98]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `night_mode.lamp` configuration is copied by the unbounded `parse_param_value()` function into the newly added 8-byte `night_lamp` field. Parse into a sufficiently sized temporary buffer, validate against `ir`, `white`, and `none`, then copy safely into the destination.
## Issue Context
`parse_param_value()` uses `sprintf()` and has no destination-size argument, so callers with small buffers cannot prevent overflow.
## Fix Focus Areas
- src/app_config.c[375-380]
- src/app_config.h[35-41]
- src/hal/config.c[58-98]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. OSD clearing underflows bounds ✓ Resolved 🐞 Bug ≡ Correctness
Description
fh_osd_clear() subtracts rect.x from the sensor width without first ensuring rect.x is inside
the plane; an OSD position beyond the frame therefore underflows w and performs a huge
out-of-bounds memset. The configuration parser permits positions up to SHRT_MAX, making this
reachable through ordinary OSD configuration.
Code

src/hal/fh/fh_hal.c[R627-629]

+        unsigned int w = rect.width;
+        if (rect.x + w > _fh_snr_dim.width) w = _fh_snr_dim.width - rect.x;
+        memset(_fh_osd_virt + py * _fh_snr_dim.width + rect.x, 0, w * 2);
Evidence
OSD X positions are accepted up to SHRT_MAX; after scaling, fh_osd_clear() calculates
sensor_width - rect.x as unsigned even when X exceeds the width, then uses the result as the
memset size.

src/app_config.c[409-414]
src/hal/fh/fh_hal.c[613-630]
src/hal/fh/fh_hal.c[633-680]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
OSD clearing can underflow its clipped width when a region begins beyond the sensor plane, causing memory corruption. Reject or fully clip rectangles before calculating buffer offsets or widths.
## Issue Context
OSD positions may be much larger than the active frame dimensions, and `fh_region_setbitmap()` invokes the clear operation immediately after region creation.
## Fix Focus Areas
- src/hal/fh/fh_hal.c[622-630]
- src/hal/fh/fh_hal.c[633-680]
- src/app_config.c[409-414]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unchecked snapshot reallocations 🐞 Bug ☼ Reliability
Description
The snapshot paths replace jpeg->data directly with realloc() and update its capacity without
checking for failure. Under memory pressure this loses the existing buffer and passes NULL to
memcpy(), crashing snapshot handling.
Code

src/hal/fh/fh_hal.c[R846-850]

+                if (_fh_mjpeg_len > jpeg->length) {
+                    jpeg->data = realloc(jpeg->data, _fh_mjpeg_len);
+                    jpeg->length = _fh_mjpeg_len;
+                }
+                memcpy(jpeg->data, _fh_mjpeg_cache, _fh_mjpeg_len);
Evidence
hal_jpegdata.data is the destination pointer and length is its capacity. Each new Fullhan
snapshot branch overwrites that pointer and then copies unconditionally, without testing the
allocation result.

src/hal/types.h[83-87]
src/hal/fh/fh_hal.c[842-853]
src/hal/fh/fh_hal.c[884-900]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
All snapshot buffer expansions must preserve the old pointer until `realloc()` succeeds and return a failure without copying when allocation fails. Update capacity only after successful allocation.
## Issue Context
The MJPEG fallback, JPEG output, and NALU aggregation branches all directly assign `realloc()` results to `jpeg->data`.
## Fix Focus Areas
- src/hal/fh/fh_hal.c[842-853]
- src/hal/fh/fh_hal.c[884-900]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. OSD bitmap scaling omitted ✓ Resolved 🐞 Bug ≡ Correctness
Description
The OSD plane is allocated at sensor resolution, but fh_osd_scale() scales only a region's
position while copying its bitmap at the original main-stream dimensions. When the main stream is
smaller than the sensor, overlays are displaced according to one scale but rendered and cleared at
another, producing incorrectly sized OSD output.
Code

src/hal/fh/fh_hal.c[R618-619]

+    rect->x = (unsigned int)rect->x * _fh_snr_dim.width / sw;
+    rect->y = (unsigned int)rect->y * _fh_snr_dim.height / sh;
Evidence
The implementation states that incoming coordinates use main-stream pixels and the plane uses sensor
dimensions, but only X and Y are transformed. fh_region_setbitmap() subsequently restores the
unscaled bitmap width and height and copies pixels one-for-one into the sensor-sized plane.

src/hal/fh/fh_hal.c[590-620]
src/hal/fh/fh_hal.c[661-680]
src/region.c[385-433]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Apply the same main-stream-to-sensor scaling to the bitmap dimensions and pixel content as to its position, or create the overlay plane in the coordinate space used by incoming bitmaps. Ensure stored clear bounds match the actual rendered dimensions.
## Issue Context
Generic OSD bitmaps are rendered in main-stream pixels, while the Fullhan graphics plane covers the native sensor frame.
## Fix Focus Areas
- src/hal/fh/fh_hal.c[590-620]
- src/hal/fh/fh_hal.c[633-680]
- src/region.c[385-433]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. OSD opacity is ignored ✓ Resolved 🐞 Bug ≡ Correctness
Description
fh_region_create() accepts the configured opacity but never applies it, while the graphics plane
alpha is always hardcoded to 255. Consequently every Fullhan OSD is fully opaque regardless of
regN_opal or runtime opacity settings.
Code

src/hal/fh/fh_hal.c[R601-604]

+    graph.enable = 1;
+    graph.physAddr = _fh_osd_phys;
+    graph.alpha = 255;
+    graph.width = _fh_snr_dim.width;
Evidence
The generic region code passes the configured opacity to the Fullhan HAL, and configuration permits
values from 0 through 255. The Fullhan setup hardcodes alpha to 255 and never references the
opacity argument.

src/app_config.c[406-408]
src/region.c[426-433]
src/hal/fh/fh_hal.c[576-610]
src/hal/fh/fh_hal.c[633-649]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Propagate the region opacity into the Fullhan overlay configuration instead of always using alpha 255. If the hardware supports only plane-wide alpha, document and consistently manage that limitation across active regions.
## Issue Context
The generic OSD path passes `osds[id].opal` to `fh_region_create()`, but the parameter is unused and graph alpha is fixed.
## Fix Focus Areas
- src/hal/fh/fh_hal.c[576-610]
- src/hal/fh/fh_hal.c[633-649]
- src/region.c[426-433]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/app_config.c Outdated
Comment thread src/hal/fh/fh_hal.c Outdated
Comment thread src/hal/fh/fh_hal.c
Comment on lines +846 to +850
if (_fh_mjpeg_len > jpeg->length) {
jpeg->data = realloc(jpeg->data, _fh_mjpeg_len);
jpeg->length = _fh_mjpeg_len;
}
memcpy(jpeg->data, _fh_mjpeg_cache, _fh_mjpeg_len);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Unchecked snapshot reallocations 🐞 Bug ☼ Reliability

The snapshot paths replace jpeg->data directly with realloc() and update its capacity without
checking for failure. Under memory pressure this loses the existing buffer and passes NULL to
memcpy(), crashing snapshot handling.
Agent Prompt
## Issue description
All snapshot buffer expansions must preserve the old pointer until `realloc()` succeeds and return a failure without copying when allocation fails. Update capacity only after successful allocation.

## Issue Context
The MJPEG fallback, JPEG output, and NALU aggregation branches all directly assign `realloc()` results to `jpeg->data`.

## Fix Focus Areas
- src/hal/fh/fh_hal.c[842-853]
- src/hal/fh/fh_hal.c[884-900]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/hal/fh/fh_hal.c
Comment thread src/hal/fh/fh_hal.c
fh_osd_clear() derived its clipped width from rect.x before checking rect.x was
inside the plane. hal_rect.x is an unsigned short and OSD positions are only
range-checked against SHRT_MAX, so a region placed past the frame wrapped
_fh_snr_dim.width - rect.x and memset most of memory. The rectangle is now
rejected up front and the width computed once.

fh_region_setbitmap() scaled a region's position from main-stream to sensor
coordinates but copied its bitmap at the original size, so whenever the main
stream was smaller than the sensor the overlay was placed for one resolution
and drawn at another. The bitmap is now sampled nearest neighbour through the
same ratio, and the stored clear bounds match what was drawn.

fh_region_create() took an opacity and ignored it while the plane alpha stayed
at 255. The hardware has one alpha for the whole graphics plane and ARGB1555
carries only an opaque/transparent bit per pixel, so a per-region value cannot
be honoured individually; the highest opacity among active regions is applied
to the plane, which is exact for the usual single region and never leaves one
more transparent than configured.

The three snapshot buffer growths assigned realloc() straight to jpeg->data,
losing the old buffer and memcpy()ing to NULL under memory pressure. They now
keep the old pointer until the allocation succeeds and fail the snapshot
otherwise.

night_mode.lamp was read by the unbounded parse_param_value() into an
eight-byte field, so a longer configured value overwrote neighbouring
AppConfig members at startup. It is parsed into a temporary and accepted only
as ir, white or none.
kasperiio added a commit to kasperiio/divinus that referenced this pull request Sep 5, 2026
Adds src/hal/fh: a HAL for the Fullhan FH8852/FH8856 V100 generation
(ARM1176 softfloat, kernel 3.0.8, SDK V1.2.0 "OSDRV" libraries libdsp/
libisp/libispcore/libvmm/libmipi/libadvapi/libacw_mpi). The SDK ships as
binary-only shared objects without headers; the interface was recovered
from the libraries and a vendor application that statically links the same
SDK, and verified on an Asecam/Vatilon PB1 (FH8856 + GC4653).

- fh_sys/fh_vpss/fh_venc/fh_isp/fh_aud: dlopen wrappers for the MPI subset
- fh_snr_gc4653: userspace GC4653 driver (the ISP calls back into a sensor
  op table; registers go over /dev/i2c-0)
- H.264 and H.265 over RTSP, MJPEG, JPEG snapshots, audio capture, OSD via
  the VPU graphic plane (ARGB1555 at sensor resolution)
- anti-flicker via the AE flicker command; SmartIR image-gain day/night
  detection wired into night mode (no external light sensor needed)
- the VPU exposes two scaler channels (main + one sub); the JPEG snapshot is
  taken from the MJPEG sub-stream when MJPEG is enabled, mirroring the vendor
- fh_compat: getifaddrs() over SIOCGIFCONF; gpio.c resolves GPIO<n> vs
  gpio<n> sysfs node naming (fh kernels use uppercase)
- server: do not crash on an OSD POST without a Content-Type header
- platform detection via /proc/driver/chip; built only for ARMv6 targets

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Epx86cKNLr14TY4B41nq89

Includes the fixes from the upstream review of the three PRs this branch is
split into (OpenIPC/divinus OpenIPC#41, OpenIPC#42, OpenIPC#43): stage-aware rollback on media
init failure, the RTCP bounds check before indexing, validated audio API
ranges, interleaved flush for audio-only sessions, a latched RTSP audio codec,
exact 8 kHz G.711 resampling, bounded config parsing for rtsp.audio_codec and
night_mode.lamp, JSON escaping in the new endpoints, OSD clipping and bitmap
scaling, per-region OSD opacity, and checked snapshot reallocations.
kasperiio added a commit to kasperiio/divinus that referenced this pull request Sep 5, 2026
Adds src/hal/fh: a HAL for the Fullhan FH8852/FH8856 V100 generation
(ARM1176 softfloat, kernel 3.0.8, SDK V1.2.0 "OSDRV" libraries libdsp/
libisp/libispcore/libvmm/libmipi/libadvapi/libacw_mpi). The SDK ships as
binary-only shared objects without headers; the interface was recovered
from the libraries and a vendor application that statically links the same
SDK, and verified on an Asecam/Vatilon PB1 (FH8856 + GC4653).

- fh_sys/fh_vpss/fh_venc/fh_isp/fh_aud: dlopen wrappers for the MPI subset
- fh_snr_gc4653: userspace GC4653 driver (the ISP calls back into a sensor
  op table; registers go over /dev/i2c-0)
- H.264 and H.265 over RTSP, MJPEG, JPEG snapshots, audio capture, OSD via
  the VPU graphic plane (ARGB1555 at sensor resolution)
- anti-flicker via the AE flicker command; SmartIR image-gain day/night
  detection wired into night mode (no external light sensor needed)
- the VPU exposes two scaler channels (main + one sub); the JPEG snapshot is
  taken from the MJPEG sub-stream when MJPEG is enabled, mirroring the vendor
- fh_compat: getifaddrs() over SIOCGIFCONF; gpio.c resolves GPIO<n> vs
  gpio<n> sysfs node naming (fh kernels use uppercase)
- server: do not crash on an OSD POST without a Content-Type header
- platform detection via /proc/driver/chip; built only for ARMv6 targets

Claude-Session: https://claude.ai/code/session_01Epx86cKNLr14TY4B41nq89

Includes the fixes from the upstream review of the three PRs this branch is
split into (OpenIPC/divinus OpenIPC#41, OpenIPC#42, OpenIPC#43): stage-aware rollback on media
init failure, the RTCP bounds check before indexing, validated audio API
ranges, interleaved flush for audio-only sessions, a latched RTSP audio codec,
exact 8 kHz G.711 resampling, bounded config parsing for rtsp.audio_codec and
night_mode.lamp, JSON escaping in the new endpoints, OSD clipping and bitmap
scaling, per-region OSD opacity, and checked snapshot reallocations.
@wberube
wberube force-pushed the master branch 2 times, most recently from a77c369 to 1e92d52 Compare September 10, 2026 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant