fix(smc): correct IOKit service name + SMCKeyData_t layout (Issue #32) #36

Merged
gronod merged 1 commits from fix/32-smc-service-name into milestone/m6-bugfix-stability 2026-09-08 15:15:10 +01:00
Owner

Summary

Two latent bugs kept all SMC telemetry dead — service never opened, and every struct call would have been rejected even if it had.

Fixes

  1. Service name: IOServiceMatching("AppleSMCClient")IOServiceMatching("AppleSMC") (MMAppleSMCClient.m:60) — AppleSMCClient is the user-client class, not the kernel service (ARCHITECTURE.md §3.1).
  2. Struct layout: removed #pragma pack(1) from MMSMCDefines.h. Packed SMCKeyData_t is 74 bytes; the SMC user client requires the canonical 80-byte layout and rejected every IOConnectCallStructMethod with kIOReturnBadArgument. Verified live on Intel hardware — unpacked calls return #KEY info (ui32).
  3. Alert input: context.batteryLevel now prefers the SMC-independent batteryHealth path (currentCapacity/maxCapacity), falling back to the power provider — low-battery alerts can fire even if SMC is unavailable.

Verified

  • xcodebuild build test -destination 'platform=macOS,arch=x86_64' — 93/93 pass; testSMCClientSingletonAndKeyCount now exercises a real open connection (totalKeyCount > 0).
  • swiftlint — 0 violations.
  • Live probe on this machine: IOServiceMatching("AppleSMC") → open OK, GetKeyInfo returns valid data.

Fixes #32.

## Summary Two latent bugs kept all SMC telemetry dead — service never opened, and every struct call would have been rejected even if it had. ### Fixes 1. **Service name**: `IOServiceMatching("AppleSMCClient")` → `IOServiceMatching("AppleSMC")` (`MMAppleSMCClient.m:60`) — `AppleSMCClient` is the user-client class, not the kernel service (ARCHITECTURE.md §3.1). 2. **Struct layout**: removed `#pragma pack(1)` from `MMSMCDefines.h`. Packed `SMCKeyData_t` is 74 bytes; the SMC user client requires the canonical 80-byte layout and rejected every `IOConnectCallStructMethod` with `kIOReturnBadArgument`. Verified live on Intel hardware — unpacked calls return `#KEY` info (`ui32`). 3. **Alert input**: `context.batteryLevel` now prefers the SMC-independent `batteryHealth` path (`currentCapacity/maxCapacity`), falling back to the power provider — low-battery alerts can fire even if SMC is unavailable. ### Verified - `xcodebuild build test -destination 'platform=macOS,arch=x86_64'` — 93/93 pass; `testSMCClientSingletonAndKeyCount` now exercises a real open connection (`totalKeyCount > 0`). - `swiftlint` — 0 violations. - Live probe on this machine: `IOServiceMatching("AppleSMC")` → open OK, GetKeyInfo returns valid data. Fixes #32.
gronod added 1 commit 2026-09-08 15:15:00 +01:00
Two latent bugs kept all SMC telemetry dead:
- IOServiceMatching("AppleSMCClient") never matched — the kernel service
  is AppleSMC, so openWithError always failed and every SMC-gated provider
  (thermal, fan, component, power) reported unavailable.
- #pragma pack(1) shrank SMCKeyData_t to 74 bytes; the SMC user client
  requires the canonical 80-byte layout and rejected every
  IOConnectCallStructMethod with kIOReturnBadArgument. Verified live on
  Intel hardware: unpacked calls succeed and return key data.

Also sources the alert engine's batteryLevel from the SMC-independent
batteryHealth path (currentCapacity/maxCapacity), falling back to the
power provider.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gronod added the Bug/BackendKind/Bug
Priority
Critical
1
Project/Antigravity
labels 2026-09-08 15:15:07 +01:00
gronod merged commit 0e5af9d70d into milestone/m6-bugfix-stability 2026-09-08 15:15:10 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/MacMonitor#36