mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-15 12:38:46 +02:00
Added source files for UVCCameraControl.
This commit is contained in:
parent
cc9f8bc717
commit
1757f32fd0
2 changed files with 466 additions and 0 deletions
83
interface/external/UVCCameraControl/src/UVCCameraControl.h
vendored
Normal file
83
interface/external/UVCCameraControl/src/UVCCameraControl.h
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
|
||||
#define UVC_INPUT_TERMINAL_ID 0x01
|
||||
#define UVC_PROCESSING_UNIT_ID 0x03
|
||||
|
||||
#define UVC_CONTROL_INTERFACE_CLASS 14
|
||||
#define UVC_CONTROL_INTERFACE_SUBCLASS 1
|
||||
|
||||
#define UVC_SET_CUR 0x01
|
||||
#define UVC_GET_CUR 0x81
|
||||
#define UVC_GET_MIN 0x82
|
||||
#define UVC_GET_MAX 0x83
|
||||
|
||||
typedef struct {
|
||||
int min, max;
|
||||
} uvc_range_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
int selector;
|
||||
int size;
|
||||
} uvc_control_info_t;
|
||||
|
||||
typedef struct {
|
||||
uvc_control_info_t autoExposure;
|
||||
uvc_control_info_t exposure;
|
||||
uvc_control_info_t brightness;
|
||||
uvc_control_info_t contrast;
|
||||
uvc_control_info_t gain;
|
||||
uvc_control_info_t saturation;
|
||||
uvc_control_info_t sharpness;
|
||||
uvc_control_info_t whiteBalance;
|
||||
uvc_control_info_t autoWhiteBalance;
|
||||
} uvc_controls_t ;
|
||||
|
||||
|
||||
@interface UVCCameraControl : NSObject {
|
||||
long dataBuffer;
|
||||
IOUSBInterfaceInterface190 **interface;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithLocationID:(UInt32)locationID;
|
||||
- (id)initWithVendorID:(long)vendorID productID:(long)productID;
|
||||
- (IOUSBInterfaceInterface190 **)getControlInferaceWithDeviceInterface:(IOUSBDeviceInterface **)deviceInterface;
|
||||
|
||||
- (BOOL)sendControlRequest:(IOUSBDevRequest)controlRequest;
|
||||
- (BOOL)setData:(long)value withLength:(int)length forSelector:(int)selector at:(int)unitID;
|
||||
- (long)getDataFor:(int)type withLength:(int)length fromSelector:(int)selector at:(int)unitID;
|
||||
|
||||
- (uvc_range_t)getRangeForControl:(const uvc_control_info_t *)control;
|
||||
- (float)mapValue:(float)value fromMin:(float)fromMin max:(float)fromMax toMin:(float)toMin max:(float)toMax;
|
||||
- (float)getValueForControl:(const uvc_control_info_t *)control;
|
||||
- (BOOL)setValue:(float)value forControl:(const uvc_control_info_t *)control;
|
||||
|
||||
|
||||
- (BOOL)setAutoExposure:(BOOL)enabled;
|
||||
- (BOOL)getAutoExposure;
|
||||
- (BOOL)setExposure:(float)value;
|
||||
- (float)getExposure;
|
||||
- (BOOL)setGain:(float)value;
|
||||
- (float)getGain;
|
||||
- (BOOL)setBrightness:(float)value;
|
||||
- (float)getBrightness;
|
||||
- (BOOL)setContrast:(float)value;
|
||||
- (float)getContrast;
|
||||
- (BOOL)setSaturation:(float)value;
|
||||
- (float)getSaturation;
|
||||
- (BOOL)setSharpness:(float)value;
|
||||
- (float)getSharpness;
|
||||
- (BOOL)setAutoWhiteBalance:(BOOL)enabled;
|
||||
- (BOOL)getAutoWhiteBalance;
|
||||
- (BOOL)setWhiteBalance:(float)value;
|
||||
- (float)getWhiteBalance;
|
||||
|
||||
@end
|
383
interface/external/UVCCameraControl/src/UVCCameraControl.m
vendored
Normal file
383
interface/external/UVCCameraControl/src/UVCCameraControl.m
vendored
Normal file
|
@ -0,0 +1,383 @@
|
|||
#import "UVCCameraControl.h"
|
||||
#import "UVCCameraControl.hpp"
|
||||
|
||||
void configureCamera(int vendorID, int productID, int autoExposure, float exposure, float contrast, float saturation, float sharpness, int autoWhiteBalance, float whiteBalance) {
|
||||
UVCCameraControl* cameraControl = [[UVCCameraControl alloc] initWithVendorID:0x05ac productID:0x8510];
|
||||
[cameraControl setAutoExposure:autoExposure];
|
||||
[cameraControl setExposure:exposure];
|
||||
[cameraControl setContrast:contrast];
|
||||
[cameraControl setSaturation:saturation];
|
||||
[cameraControl setSharpness:sharpness];
|
||||
[cameraControl setAutoWhiteBalance:autoWhiteBalance];
|
||||
[cameraControl setWhiteBalance:whiteBalance];
|
||||
}
|
||||
|
||||
const uvc_controls_t uvc_controls = {
|
||||
.autoExposure = {
|
||||
.unit = UVC_INPUT_TERMINAL_ID,
|
||||
.selector = 0x02,
|
||||
.size = 1,
|
||||
},
|
||||
.exposure = {
|
||||
.unit = UVC_INPUT_TERMINAL_ID,
|
||||
.selector = 0x04,
|
||||
.size = 4,
|
||||
},
|
||||
.brightness = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x02,
|
||||
.size = 2,
|
||||
},
|
||||
.contrast = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x03,
|
||||
.size = 2,
|
||||
},
|
||||
.gain = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x04,
|
||||
.size = 2,
|
||||
},
|
||||
.saturation = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x07,
|
||||
.size = 2,
|
||||
},
|
||||
.sharpness = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x08,
|
||||
.size = 2,
|
||||
},
|
||||
.whiteBalance = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x0A,
|
||||
.size = 2,
|
||||
},
|
||||
.autoWhiteBalance = {
|
||||
.unit = UVC_PROCESSING_UNIT_ID,
|
||||
.selector = 0x0B,
|
||||
.size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@implementation UVCCameraControl
|
||||
|
||||
|
||||
- (id)initWithLocationID:(UInt32)locationID {
|
||||
if( self = [super init] ) {
|
||||
interface = NULL;
|
||||
|
||||
// Find All USB Devices, get their locationId and check if it matches the requested one
|
||||
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
||||
io_iterator_t serviceIterator;
|
||||
IOServiceGetMatchingServices( kIOMasterPortDefault, matchingDict, &serviceIterator );
|
||||
|
||||
io_service_t camera;
|
||||
while( camera = IOIteratorNext(serviceIterator) ) {
|
||||
// Get DeviceInterface
|
||||
IOUSBDeviceInterface **deviceInterface = NULL;
|
||||
IOCFPlugInInterface **plugInInterface = NULL;
|
||||
SInt32 score;
|
||||
kern_return_t kr = IOCreatePlugInInterfaceForService( camera, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score );
|
||||
if( (kIOReturnSuccess != kr) || !plugInInterface ) {
|
||||
NSLog( @"CameraControl Error: IOCreatePlugInInterfaceForService returned 0x%08x.", kr );
|
||||
continue;
|
||||
}
|
||||
|
||||
HRESULT res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceInterface );
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
if( res || deviceInterface == NULL ) {
|
||||
NSLog( @"CameraControl Error: QueryInterface returned %d.\n", (int)res );
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt32 currentLocationID = 0;
|
||||
(*deviceInterface)->GetLocationID(deviceInterface, ¤tLocationID);
|
||||
|
||||
if( currentLocationID == locationID ) {
|
||||
// Yep, this is the USB Device that was requested!
|
||||
interface = [self getControlInferaceWithDeviceInterface:deviceInterface];
|
||||
return self;
|
||||
}
|
||||
} // end while
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithVendorID:(long)vendorID productID:(long)productID {
|
||||
if( self = [super init] ) {
|
||||
interface = NULL;
|
||||
|
||||
// Find USB Device
|
||||
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
||||
CFNumberRef numberRef;
|
||||
|
||||
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorID);
|
||||
CFDictionarySetValue( matchingDict, CFSTR(kUSBVendorID), numberRef );
|
||||
CFRelease(numberRef);
|
||||
|
||||
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &productID);
|
||||
CFDictionarySetValue( matchingDict, CFSTR(kUSBProductID), numberRef );
|
||||
CFRelease(numberRef);
|
||||
io_service_t camera = IOServiceGetMatchingService( kIOMasterPortDefault, matchingDict );
|
||||
|
||||
|
||||
// Get DeviceInterface
|
||||
IOUSBDeviceInterface **deviceInterface = NULL;
|
||||
IOCFPlugInInterface **plugInInterface = NULL;
|
||||
SInt32 score;
|
||||
kern_return_t kr = IOCreatePlugInInterfaceForService( camera, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score );
|
||||
if( (kIOReturnSuccess != kr) || !plugInInterface ) {
|
||||
NSLog( @"CameraControl Error: IOCreatePlugInInterfaceForService returned 0x%08x.", kr );
|
||||
return self;
|
||||
}
|
||||
|
||||
HRESULT res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceInterface );
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
if( res || deviceInterface == NULL ) {
|
||||
NSLog( @"CameraControl Error: QueryInterface returned %d.\n", (int)res );
|
||||
return self;
|
||||
}
|
||||
|
||||
interface = [self getControlInferaceWithDeviceInterface:deviceInterface];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (IOUSBInterfaceInterface190 **)getControlInferaceWithDeviceInterface:(IOUSBDeviceInterface **)deviceInterface {
|
||||
IOUSBInterfaceInterface190 **controlInterface;
|
||||
|
||||
io_iterator_t interfaceIterator;
|
||||
IOUSBFindInterfaceRequest interfaceRequest;
|
||||
interfaceRequest.bInterfaceClass = UVC_CONTROL_INTERFACE_CLASS;
|
||||
interfaceRequest.bInterfaceSubClass = UVC_CONTROL_INTERFACE_SUBCLASS;
|
||||
interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
|
||||
interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
||||
|
||||
IOReturn success = (*deviceInterface)->CreateInterfaceIterator( deviceInterface, &interfaceRequest, &interfaceIterator );
|
||||
if( success != kIOReturnSuccess ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
io_service_t usbInterface;
|
||||
HRESULT result;
|
||||
|
||||
|
||||
if( usbInterface = IOIteratorNext(interfaceIterator) ) {
|
||||
IOCFPlugInInterface **plugInInterface = NULL;
|
||||
|
||||
//Create an intermediate plug-in
|
||||
SInt32 score;
|
||||
kern_return_t kr = IOCreatePlugInInterfaceForService( usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score );
|
||||
|
||||
//Release the usbInterface object after getting the plug-in
|
||||
kr = IOObjectRelease(usbInterface);
|
||||
if( (kr != kIOReturnSuccess) || !plugInInterface ) {
|
||||
NSLog( @"CameraControl Error: Unable to create a plug-in (%08x)\n", kr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Now create the device interface for the interface
|
||||
result = (*plugInInterface)->QueryInterface( plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID *) &controlInterface );
|
||||
|
||||
//No longer need the intermediate plug-in
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
|
||||
if( result || !controlInterface ) {
|
||||
NSLog( @"CameraControl Error: Couldn’t create a device interface for the interface (%08x)", (int) result );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return controlInterface;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (BOOL)sendControlRequest:(IOUSBDevRequest)controlRequest {
|
||||
if( !interface ){
|
||||
NSLog( @"CameraControl Error: No interface to send request" );
|
||||
return NO;
|
||||
}
|
||||
|
||||
//Now open the interface. This will cause the pipes associated with
|
||||
//the endpoints in the interface descriptor to be instantiated
|
||||
kern_return_t kr = (*interface)->ControlRequest( interface, 0, &controlRequest );
|
||||
if( kr != kIOReturnSuccess ) {
|
||||
NSLog( @"CameraControl Error: Control request failed: %08x", kr );
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)setData:(long)value withLength:(int)length forSelector:(int)selector at:(int)unitId {
|
||||
IOUSBDevRequest controlRequest;
|
||||
controlRequest.bmRequestType = USBmakebmRequestType( kUSBOut, kUSBClass, kUSBInterface );
|
||||
controlRequest.bRequest = UVC_SET_CUR;
|
||||
controlRequest.wValue = (selector << 8) | 0x00;
|
||||
controlRequest.wIndex = (unitId << 8) | 0x00;
|
||||
controlRequest.wLength = length;
|
||||
controlRequest.wLenDone = 0;
|
||||
controlRequest.pData = &value;
|
||||
return [self sendControlRequest:controlRequest];
|
||||
}
|
||||
|
||||
|
||||
- (long)getDataFor:(int)type withLength:(int)length fromSelector:(int)selector at:(int)unitId {
|
||||
long value = 0;
|
||||
IOUSBDevRequest controlRequest;
|
||||
controlRequest.bmRequestType = USBmakebmRequestType( kUSBIn, kUSBClass, kUSBInterface );
|
||||
controlRequest.bRequest = type;
|
||||
controlRequest.wValue = (selector << 8) | 0x00;
|
||||
controlRequest.wIndex = (unitId << 8) | 0x00;
|
||||
controlRequest.wLength = length;
|
||||
controlRequest.wLenDone = 0;
|
||||
controlRequest.pData = &value;
|
||||
BOOL success = [self sendControlRequest:controlRequest];
|
||||
return ( success ? value : 0 );
|
||||
}
|
||||
|
||||
|
||||
// Get Range (min, max)
|
||||
- (uvc_range_t)getRangeForControl:(uvc_control_info_t *)control {
|
||||
uvc_range_t range = { 0, 0 };
|
||||
range.min = [self getDataFor:UVC_GET_MIN withLength:control->size fromSelector:control->selector at:control->unit];
|
||||
range.max = [self getDataFor:UVC_GET_MAX withLength:control->size fromSelector:control->selector at:control->unit];
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
// Used to de-/normalize values
|
||||
- (float)mapValue:(float)value fromMin:(float)fromMin max:(float)fromMax toMin:(float)toMin max:(float)toMax {
|
||||
return toMin + (toMax - toMin) * ((value - fromMin) / (fromMax - fromMin));
|
||||
}
|
||||
|
||||
|
||||
// Get a normalized value
|
||||
- (float)getValueForControl:(uvc_control_info_t *)control {
|
||||
// TODO: Cache the range somewhere?
|
||||
uvc_range_t range = [self getRangeForControl:control];
|
||||
|
||||
int intval = [self getDataFor:UVC_GET_CUR withLength:control->size fromSelector:control->selector at:control->unit];
|
||||
return [self mapValue:intval fromMin:range.min max:range.max toMin:0 max:1];
|
||||
}
|
||||
|
||||
|
||||
// Set a normalized value
|
||||
- (BOOL)setValue:(float)value forControl:(uvc_control_info_t *)control {
|
||||
// TODO: Cache the range somewhere?
|
||||
uvc_range_t range = [self getRangeForControl:control];
|
||||
|
||||
int intval = [self mapValue:value fromMin:0 max:1 toMin:range.min max:range.max];
|
||||
return [self setData:intval withLength:control->size forSelector:control->selector at:control->unit];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================================================================
|
||||
|
||||
// Set/Get the actual values for the camera
|
||||
//
|
||||
|
||||
- (BOOL)setAutoExposure:(BOOL)enabled {
|
||||
int intval = (enabled ? 0x08 : 0x01); // "auto exposure modes" ar NOT boolean (on|off) as it seems
|
||||
return [self setData:intval
|
||||
withLength:uvc_controls.autoExposure.size
|
||||
forSelector:uvc_controls.autoExposure.selector
|
||||
at:uvc_controls.autoExposure.unit];
|
||||
}
|
||||
|
||||
- (BOOL)getAutoExposure {
|
||||
int intval = [self getDataFor:UVC_GET_CUR
|
||||
withLength:uvc_controls.autoExposure.size
|
||||
fromSelector:uvc_controls.autoExposure.selector
|
||||
at:uvc_controls.autoExposure.unit];
|
||||
|
||||
return ( intval == 0x08 ? YES : NO );
|
||||
}
|
||||
|
||||
- (BOOL)setExposure:(float)value {
|
||||
value = 1 - value;
|
||||
return [self setValue:value forControl:&uvc_controls.exposure];
|
||||
}
|
||||
|
||||
- (float)getExposure {
|
||||
float value = [self getValueForControl:&uvc_controls.exposure];
|
||||
return 1 - value;
|
||||
}
|
||||
|
||||
- (BOOL)setGain:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.gain];
|
||||
}
|
||||
|
||||
- (float)getGain {
|
||||
return [self getValueForControl:&uvc_controls.gain];
|
||||
}
|
||||
|
||||
- (BOOL)setBrightness:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.brightness];
|
||||
}
|
||||
|
||||
- (float)getBrightness {
|
||||
return [self getValueForControl:&uvc_controls.brightness];
|
||||
}
|
||||
|
||||
- (BOOL)setContrast:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.contrast];
|
||||
}
|
||||
|
||||
- (float)getContrast {
|
||||
return [self getValueForControl:&uvc_controls.contrast];
|
||||
}
|
||||
|
||||
- (BOOL)setSaturation:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.saturation];
|
||||
}
|
||||
|
||||
- (float)getSaturation {
|
||||
return [self getValueForControl:&uvc_controls.saturation];
|
||||
}
|
||||
|
||||
- (BOOL)setSharpness:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.sharpness];
|
||||
}
|
||||
|
||||
- (float)getSharpness {
|
||||
return [self getValueForControl:&uvc_controls.sharpness];
|
||||
}
|
||||
|
||||
- (BOOL)setAutoWhiteBalance:(BOOL)enabled {
|
||||
int intval = (enabled ? 0x01 : 0x00);
|
||||
return [self setData:intval
|
||||
withLength:uvc_controls.autoWhiteBalance.size
|
||||
forSelector:uvc_controls.autoWhiteBalance.selector
|
||||
at:uvc_controls.autoWhiteBalance.unit];
|
||||
}
|
||||
|
||||
- (BOOL)getAutoWhiteBalance {
|
||||
int intval = [self getDataFor:UVC_GET_CUR
|
||||
withLength:uvc_controls.autoWhiteBalance.size
|
||||
fromSelector:uvc_controls.autoWhiteBalance.selector
|
||||
at:uvc_controls.autoWhiteBalance.unit];
|
||||
|
||||
return ( intval ? YES : NO );
|
||||
}
|
||||
|
||||
- (BOOL)setWhiteBalance:(float)value {
|
||||
return [self setValue:value forControl:&uvc_controls.whiteBalance];
|
||||
}
|
||||
|
||||
- (float)getWhiteBalance {
|
||||
return [self getValueForControl:&uvc_controls.whiteBalance];
|
||||
}
|
||||
|
||||
|
||||
@end
|
Loading…
Reference in a new issue