mirror of
https://github.com/samhenrigold/LidAngleSensor.git
synced 2026-01-12 09:17:43 +03:00
init
This commit is contained in:
@@ -246,13 +246,19 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
AUTOMATION_APPLE_EVENTS = NO;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = CG56CG5WCQ;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_USER_SELECTED_FILES = readonly;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
@@ -265,6 +271,12 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gold.samhenri.LidAngleSensor;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_JIT = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO;
|
||||
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
};
|
||||
@@ -275,13 +287,19 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
AUTOMATION_APPLE_EVENTS = NO;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = CG56CG5WCQ;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_USER_SELECTED_FILES = readonly;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
@@ -294,6 +312,12 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gold.samhenri.LidAngleSensor;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_JIT = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO;
|
||||
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) NSWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -6,27 +6,154 @@
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "LidAngleSensor.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (strong) IBOutlet NSWindow *window;
|
||||
@property (strong, nonatomic) LidAngleSensor *lidSensor;
|
||||
@property (strong, nonatomic) NSTextField *angleLabel;
|
||||
@property (strong, nonatomic) NSTextField *statusLabel;
|
||||
@property (strong, nonatomic) NSTimer *updateTimer;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
// Insert code here to initialize your application
|
||||
[self createWindow];
|
||||
[self initializeLidSensor];
|
||||
[self startUpdatingDisplay];
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
// Insert code here to tear down your application
|
||||
[self.updateTimer invalidate];
|
||||
[self.lidSensor stopLidAngleUpdates];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)createWindow {
|
||||
// Create the main window
|
||||
NSRect windowFrame = NSMakeRect(100, 100, 400, 300);
|
||||
self.window = [[NSWindow alloc] initWithContentRect:windowFrame
|
||||
styleMask:NSWindowStyleMaskTitled |
|
||||
NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
[self.window setTitle:@"MacBook Lid Angle Sensor"];
|
||||
[self.window makeKeyAndOrderFront:nil];
|
||||
[self.window center];
|
||||
|
||||
// Create the content view
|
||||
NSView *contentView = [[NSView alloc] initWithFrame:windowFrame];
|
||||
[self.window setContentView:contentView];
|
||||
|
||||
// Create title label
|
||||
NSTextField *titleLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 220, 300, 40)];
|
||||
[titleLabel setStringValue:@"MacBook Lid Angle Sensor"];
|
||||
[titleLabel setFont:[NSFont boldSystemFontOfSize:18]];
|
||||
[titleLabel setBezeled:NO];
|
||||
[titleLabel setDrawsBackground:NO];
|
||||
[titleLabel setEditable:NO];
|
||||
[titleLabel setSelectable:NO];
|
||||
[titleLabel setAlignment:NSTextAlignmentCenter];
|
||||
[contentView addSubview:titleLabel];
|
||||
|
||||
// Create angle display label
|
||||
self.angleLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 150, 300, 50)];
|
||||
[self.angleLabel setStringValue:@"Initializing..."];
|
||||
[self.angleLabel setFont:[NSFont monospacedSystemFontOfSize:24 weight:NSFontWeightMedium]];
|
||||
[self.angleLabel setBezeled:NO];
|
||||
[self.angleLabel setDrawsBackground:NO];
|
||||
[self.angleLabel setEditable:NO];
|
||||
[self.angleLabel setSelectable:NO];
|
||||
[self.angleLabel setAlignment:NSTextAlignmentCenter];
|
||||
[self.angleLabel setTextColor:[NSColor systemBlueColor]];
|
||||
[contentView addSubview:self.angleLabel];
|
||||
|
||||
// Create status label
|
||||
self.statusLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 100, 300, 30)];
|
||||
[self.statusLabel setStringValue:@"Detecting sensor..."];
|
||||
[self.statusLabel setFont:[NSFont systemFontOfSize:14]];
|
||||
[self.statusLabel setBezeled:NO];
|
||||
[self.statusLabel setDrawsBackground:NO];
|
||||
[self.statusLabel setEditable:NO];
|
||||
[self.statusLabel setSelectable:NO];
|
||||
[self.statusLabel setAlignment:NSTextAlignmentCenter];
|
||||
[self.statusLabel setTextColor:[NSColor secondaryLabelColor]];
|
||||
[contentView addSubview:self.statusLabel];
|
||||
|
||||
// Create info label
|
||||
NSTextField *infoLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 30, 300, 60)];
|
||||
[infoLabel setStringValue:@"This app reads the MacBook's internal lid angle sensor.\n0° = Closed, ~180° = Fully Open"];
|
||||
[infoLabel setFont:[NSFont systemFontOfSize:12]];
|
||||
[infoLabel setBezeled:NO];
|
||||
[infoLabel setDrawsBackground:NO];
|
||||
[infoLabel setEditable:NO];
|
||||
[infoLabel setSelectable:NO];
|
||||
[infoLabel setAlignment:NSTextAlignmentCenter];
|
||||
[infoLabel setTextColor:[NSColor tertiaryLabelColor]];
|
||||
[contentView addSubview:infoLabel];
|
||||
}
|
||||
|
||||
- (void)initializeLidSensor {
|
||||
self.lidSensor = [[LidAngleSensor alloc] init];
|
||||
|
||||
if (self.lidSensor.isAvailable) {
|
||||
[self.statusLabel setStringValue:@"Sensor detected - Reading angle..."];
|
||||
[self.statusLabel setTextColor:[NSColor systemGreenColor]];
|
||||
} else {
|
||||
[self.statusLabel setStringValue:@"Lid angle sensor not available on this device"];
|
||||
[self.statusLabel setTextColor:[NSColor systemRedColor]];
|
||||
[self.angleLabel setStringValue:@"Not Available"];
|
||||
[self.angleLabel setTextColor:[NSColor systemRedColor]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startUpdatingDisplay {
|
||||
// Update the display every 100ms for smooth real-time updates
|
||||
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
|
||||
target:self
|
||||
selector:@selector(updateAngleDisplay)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
}
|
||||
|
||||
- (void)updateAngleDisplay {
|
||||
if (!self.lidSensor.isAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
double angle = [self.lidSensor lidAngle];
|
||||
|
||||
if (angle == -2.0) {
|
||||
[self.angleLabel setStringValue:@"Read Error"];
|
||||
[self.angleLabel setTextColor:[NSColor systemOrangeColor]];
|
||||
[self.statusLabel setStringValue:@"Failed to read sensor data"];
|
||||
[self.statusLabel setTextColor:[NSColor systemOrangeColor]];
|
||||
} else {
|
||||
[self.angleLabel setStringValue:[NSString stringWithFormat:@"%.1f°", angle]];
|
||||
[self.angleLabel setTextColor:[NSColor systemBlueColor]];
|
||||
|
||||
// Provide contextual status based on angle
|
||||
NSString *status;
|
||||
if (angle < 5.0) {
|
||||
status = @"Lid is closed";
|
||||
} else if (angle < 45.0) {
|
||||
status = @"Lid slightly open";
|
||||
} else if (angle < 90.0) {
|
||||
status = @"Lid partially open";
|
||||
} else if (angle < 135.0) {
|
||||
status = @"Lid mostly open";
|
||||
} else {
|
||||
status = @"Lid fully open";
|
||||
}
|
||||
|
||||
[self.statusLabel setStringValue:status];
|
||||
[self.statusLabel setTextColor:[NSColor secondaryLabelColor]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17150" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24123.1" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17150"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24123.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -11,12 +10,8 @@
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="">
|
||||
<connections>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
@@ -680,19 +675,5 @@
|
||||
</items>
|
||||
<point key="canvasLocation" x="200" y="121"/>
|
||||
</menu>
|
||||
<window title="LidAngleSensor" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="top-28-M4D"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="200" y="400"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
51
LidAngleSensor/LidAngleSensor.h
Normal file
51
LidAngleSensor/LidAngleSensor.h
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// LidAngleSensor.h
|
||||
// LidAngleSensor
|
||||
//
|
||||
// Created by Sam on 2025-09-06.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <IOKit/hid/IOHIDManager.h>
|
||||
#import <IOKit/hid/IOHIDDevice.h>
|
||||
|
||||
/**
|
||||
* LidAngleSensor provides access to the MacBook's internal lid angle sensor.
|
||||
*
|
||||
* This class interfaces with the HID device that reports the angle between
|
||||
* the laptop lid and base, providing real-time angle measurements in degrees.
|
||||
*
|
||||
* Device Specifications (discovered through reverse engineering):
|
||||
* - Apple device: VID=0x05AC, PID=0x8104
|
||||
* - HID Usage: Sensor page (0x0020), Orientation usage (0x008A)
|
||||
* - Data format: 16-bit angle value in centidegrees (0.01° resolution)
|
||||
* - Range: 0-360 degrees
|
||||
*/
|
||||
@interface LidAngleSensor : NSObject
|
||||
|
||||
@property (nonatomic, assign, readonly) IOHIDDeviceRef hidDevice;
|
||||
@property (nonatomic, assign, readonly) BOOL isAvailable;
|
||||
|
||||
/**
|
||||
* Initialize and connect to the lid angle sensor.
|
||||
* @return Initialized sensor instance, or nil if sensor not available
|
||||
*/
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Read the current lid angle.
|
||||
* @return Angle in degrees (0-360), or -2.0 if read failed
|
||||
*/
|
||||
- (double)lidAngle;
|
||||
|
||||
/**
|
||||
* Start lid angle monitoring (called automatically in init).
|
||||
*/
|
||||
- (void)startLidAngleUpdates;
|
||||
|
||||
/**
|
||||
* Stop lid angle monitoring and release resources.
|
||||
*/
|
||||
- (void)stopLidAngleUpdates;
|
||||
|
||||
@end
|
||||
153
LidAngleSensor/LidAngleSensor.m
Normal file
153
LidAngleSensor/LidAngleSensor.m
Normal file
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// LidAngleSensor.m
|
||||
// LidAngleSensor
|
||||
//
|
||||
// Created by Sam on 2025-09-06.
|
||||
//
|
||||
|
||||
#import "LidAngleSensor.h"
|
||||
|
||||
@interface LidAngleSensor ()
|
||||
@property (nonatomic, assign) IOHIDDeviceRef hidDevice;
|
||||
@end
|
||||
|
||||
@implementation LidAngleSensor
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_hidDevice = [self findLidAngleSensor];
|
||||
if (_hidDevice) {
|
||||
IOHIDDeviceOpen(_hidDevice, kIOHIDOptionsTypeNone);
|
||||
NSLog(@"[LidAngleSensor] Successfully initialized lid angle sensor");
|
||||
} else {
|
||||
NSLog(@"[LidAngleSensor] Failed to find lid angle sensor");
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self stopLidAngleUpdates];
|
||||
}
|
||||
|
||||
- (BOOL)isAvailable {
|
||||
return _hidDevice != NULL;
|
||||
}
|
||||
|
||||
- (IOHIDDeviceRef)findLidAngleSensor {
|
||||
IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
if (!manager) {
|
||||
NSLog(@"[LidAngleSensor] Failed to create IOHIDManager");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
|
||||
NSLog(@"[LidAngleSensor] Failed to open IOHIDManager");
|
||||
CFRelease(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Use Generic Desktop + Mouse criteria to find candidate devices
|
||||
// This broader search allows us to find the lid sensor among other HID devices
|
||||
NSDictionary *matchingDict = @{
|
||||
@"UsagePage": @(0x0001), // Generic Desktop
|
||||
@"Usage": @(0x0003), // Mouse
|
||||
};
|
||||
|
||||
IOHIDManagerSetDeviceMatching(manager, (__bridge CFDictionaryRef)matchingDict);
|
||||
CFSetRef devices = IOHIDManagerCopyDevices(manager);
|
||||
IOHIDDeviceRef device = NULL;
|
||||
|
||||
if (devices && CFSetGetCount(devices) > 0) {
|
||||
NSLog(@"[LidAngleSensor] Found %ld devices, looking for sensor...", CFSetGetCount(devices));
|
||||
|
||||
const void **deviceArray = malloc(sizeof(void*) * CFSetGetCount(devices));
|
||||
CFSetGetValues(devices, deviceArray);
|
||||
|
||||
// Search for the specific lid angle sensor device
|
||||
// Discovered through reverse engineering: Apple device with Sensor page
|
||||
for (CFIndex i = 0; i < CFSetGetCount(devices); i++) {
|
||||
IOHIDDeviceRef currentDevice = (IOHIDDeviceRef)deviceArray[i];
|
||||
|
||||
CFNumberRef vendorID = IOHIDDeviceGetProperty(currentDevice, CFSTR("VendorID"));
|
||||
CFNumberRef productID = IOHIDDeviceGetProperty(currentDevice, CFSTR("ProductID"));
|
||||
CFNumberRef usagePage = IOHIDDeviceGetProperty(currentDevice, CFSTR("PrimaryUsagePage"));
|
||||
CFNumberRef usage = IOHIDDeviceGetProperty(currentDevice, CFSTR("PrimaryUsage"));
|
||||
|
||||
int vid = 0, pid = 0, up = 0, u = 0;
|
||||
if (vendorID) CFNumberGetValue(vendorID, kCFNumberIntType, &vid);
|
||||
if (productID) CFNumberGetValue(productID, kCFNumberIntType, &pid);
|
||||
if (usagePage) CFNumberGetValue(usagePage, kCFNumberIntType, &up);
|
||||
if (usage) CFNumberGetValue(usage, kCFNumberIntType, &u);
|
||||
|
||||
// Target the specific lid angle sensor device
|
||||
// VID=0x05AC (Apple), PID=0x8104, UsagePage=0x0020 (Sensor), Usage=0x008A (Orientation)
|
||||
if (vid == 0x05AC && pid == 0x8104 && up == 0x0020 && u == 0x008A) {
|
||||
device = (IOHIDDeviceRef)CFRetain(currentDevice);
|
||||
NSLog(@"[LidAngleSensor] Found lid angle sensor device: VID=0x%04X, PID=0x%04X", vid, pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(deviceArray);
|
||||
}
|
||||
|
||||
if (devices) CFRelease(devices);
|
||||
|
||||
IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
|
||||
CFRelease(manager);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
- (double)lidAngle {
|
||||
if (!_hidDevice) {
|
||||
return -2.0; // Device not available
|
||||
}
|
||||
|
||||
// Read lid angle using discovered parameters:
|
||||
// Feature Report Type 2, Report ID 1, returns 3 bytes with 16-bit angle in centidegrees
|
||||
uint8_t report[8] = {0};
|
||||
CFIndex reportLength = sizeof(report);
|
||||
|
||||
IOReturn result = IOHIDDeviceGetReport(_hidDevice,
|
||||
kIOHIDReportTypeFeature, // Type 2
|
||||
1, // Report ID 1
|
||||
report,
|
||||
&reportLength);
|
||||
|
||||
if (result == kIOReturnSuccess && reportLength >= 3) {
|
||||
// Data format: [report_id, angle_low, angle_high]
|
||||
// Example: [01 72 00] = 0x7201 centidegrees = 291.85 degrees
|
||||
uint16_t rawValue = *(uint16_t*)(report);
|
||||
double angle = rawValue * 0.01; // Convert centidegrees to degrees
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
return -2.0;
|
||||
}
|
||||
|
||||
- (void)startLidAngleUpdates {
|
||||
if (!_hidDevice) {
|
||||
_hidDevice = [self findLidAngleSensor];
|
||||
if (_hidDevice) {
|
||||
NSLog(@"[LidAngleSensor] Starting lid angle updates");
|
||||
IOHIDDeviceOpen(_hidDevice, kIOHIDOptionsTypeNone);
|
||||
} else {
|
||||
NSLog(@"[LidAngleSensor] Lid angle sensor is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopLidAngleUpdates {
|
||||
if (_hidDevice) {
|
||||
NSLog(@"[LidAngleSensor] Stopping lid angle updates");
|
||||
IOHIDDeviceClose(_hidDevice, kIOHIDOptionsTypeNone);
|
||||
CFRelease(_hidDevice);
|
||||
_hidDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
BIN
LidAngleSensor/sfx/CREAK_LOOP.wav
Normal file
BIN
LidAngleSensor/sfx/CREAK_LOOP.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_MED1.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_MED1.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_MED2.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_MED2.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SHARP1.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SHARP1.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SHARP2.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SHARP2.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SHARP3.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SHARP3.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SHARP4.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SHARP4.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SML1.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SML1.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SML2.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SML2.wav
Normal file
Binary file not shown.
BIN
LidAngleSensor/sfx/GRAIN_SML3.wav
Normal file
BIN
LidAngleSensor/sfx/GRAIN_SML3.wav
Normal file
Binary file not shown.
Reference in New Issue
Block a user