Skip to content

Commit

Permalink
fix: lightguide sent to interface 0x4 endpoint 4 via bulk
Browse files Browse the repository at this point in the history
  • Loading branch information
tillt committed Jan 11, 2024
1 parent 0c417f6 commit 72b4ace
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 63 deletions.
51 changes: 26 additions & 25 deletions KompleteSynthesia/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ @interface AppDelegate ()
@property (nonatomic, strong) MIDI2HIDController* midi2hidController;
@property (nonatomic, strong) VideoController* videoController;
@property (nonatomic, strong) HIDController* hidController;
@property (nonatomic, strong) USBController* usbController;
@property (nonatomic, strong) MIDIController* midiController;
@property (nonatomic, strong) LogViewController* log;
@property (nonatomic, strong) SynthesiaController* synthesia;
Expand Down Expand Up @@ -163,7 +164,13 @@ - (void)applicationDidFinishInitializingWithSynthesiaRunning
{
NSError* error = nil;

_hidController = [[HIDController alloc] initWithLogViewController:_log];
_usbController = [[USBController alloc] initWithLogViewController:_log];
// Try to open a USB device interface for bulk transfer.
if ([_usbController setupWithError:&error] == NO) {
usbAvailable = NO;
}

_hidController = [[HIDController alloc] initWithUSBController:_usbController logViewController:_log];

_midiController = [[MIDIController alloc] initWithLogViewController:_log];

Expand All @@ -177,36 +184,30 @@ - (void)applicationDidFinishInitializingWithSynthesiaRunning
return;
}

// We won't need any bulk USB access for MK1 controllers - they have no screens.
if (_hidController.mk == 1) {
usbAvailable = NO;
}

// FIXME: Actively disable USB bulk transfer on MK3 until further notice...
if (_hidController.mk == 3) {
usbAvailable = NO;
}

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults registerDefaults:@{kAppDefaultActivateSynthesia : @(YES)}];
_midi2hidController.forwardButtonsToSynthesiaOnly = [userDefaults boolForKey:kAppDefaultActivateSynthesia];

if (usbAvailable == YES) {
_videoController = [[VideoController alloc] initWithLogViewController:_log error:&error];
if (_videoController == nil) {
[[NSAlert alertWithError:error] runModal];
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
return;
}

[userDefaults registerDefaults:@{kAppDefaultMirrorSynthesia : @(YES)}];
_videoController.mirrorSynthesiaApplicationWindow = [userDefaults boolForKey:kAppDefaultMirrorSynthesia];

if (![_videoController reset:&error]) {
[[NSAlert alertWithError:error] runModal];
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
return;
if (_hidController.mk == 2) {
_videoController = [[VideoController alloc] initWithUSBController:_usbController
logViewController:_log
error:&error];
if (_videoController == nil) {
[[NSAlert alertWithError:error] runModal];
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
return;
}

[userDefaults registerDefaults:@{kAppDefaultMirrorSynthesia : @(YES)}];
_videoController.mirrorSynthesiaApplicationWindow = [userDefaults boolForKey:kAppDefaultMirrorSynthesia];

if (![_videoController reset:&error]) {
[[NSAlert alertWithError:error] runModal];
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
return;
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion KompleteSynthesia/HIDController.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ enum {
};

@class LogViewController;
@class USBController;

@protocol HIDControllerDelegate <NSObject>
- (void)receivedEvent:(const int)event value:(int)value;
Expand All @@ -123,7 +124,7 @@ enum {

+ (NSColor*)colorWithKeyState:(const unsigned char)keyState;

- (id)initWithLogViewController:(LogViewController*)lc;
- (id)initWithUSBController:(USBController*)uc logViewController:(LogViewController*)lc;

- (BOOL)setupWithError:(NSError**)error;

Expand Down
47 changes: 32 additions & 15 deletions KompleteSynthesia/HIDController.m
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,12 @@ @interface HIDController ()

@implementation HIDController {
LogViewController* log;
USBController* usb;

size_t lightGuideUpdateMessageSize;
unsigned char* lightGuideUpdateMessage;
NSMutableData* lightGuideStreamMK3;

unsigned char buttonLightingFeedback[kKompleteKontrolButtonsMessageSize];
unsigned char buttonLightingUpdateMessage[kKompleteKontrolButtonsMessageSize];

Expand Down Expand Up @@ -178,11 +181,13 @@ + (NSColor*)colorWithKeyState:(const unsigned char)keyState
alpha:1.0f];
}

- (id)initWithLogViewController:(LogViewController*)lc
- (id)initWithUSBController:(USBController*)uc logViewController:(LogViewController*)lc;
{
self = [super init];
if (self) {
log = lc;
usb = uc;

lastVolumeKnobValue = INTMAX_C(16);
atomic_fetch_and(&swooshActive, 0);
swooshQueue = dispatch_queue_create("KompleteSynthesia.SwooshQueue", NULL);
Expand Down Expand Up @@ -468,21 +473,25 @@ - (IOHIDDeviceRef)detectKeyboardController:(NSError**)error

lightGuideUpdateMessageSize =
_mk == 3 ? kKompleteKontrolLightGuideMessageSizeMK3 : kKompleteKontrolLightGuideMessageSize;
lightGuideUpdateMessage = calloc(lightGuideUpdateMessageSize, 1);

switch (_mk) {
case 1:
lightGuideUpdateMessage[0] = kCommandLightGuideUpdateMK1;
break;
case 2:
lightGuideUpdateMessage[0] = kCommandLightGuideUpdateMK2;
break;
case 3:
*(unsigned long*)lightGuideUpdateMessage = lightGuideUpdateMessageSize - 4;
memcpy(lightGuideUpdateMessage + 4, kKompleteKontrolLightGuidePrefixMK3,
sizeof(kKompleteKontrolLightGuidePrefixMK3));
break;

lightGuideStreamMK3 = nil;

if (_mk == 3) {
lightGuideStreamMK3 = [[NSMutableData alloc] initWithCapacity:lightGuideUpdateMessageSize];
unsigned int length = (unsigned int)lightGuideUpdateMessageSize - 4;
[lightGuideStreamMK3 appendBytes:&length length:sizeof(length)];
[lightGuideStreamMK3 appendBytes:&kKompleteKontrolLightGuidePrefixMK3
length:sizeof(kKompleteKontrolLightGuidePrefixMK3)];
for (int i = 0; i < 128; i++) {
unsigned char entry[] = {0x92, 0x00, 0x00};
[lightGuideStreamMK3 appendBytes:entry length:sizeof(entry)];
}
lightGuideUpdateMessage = (unsigned char*)lightGuideStreamMK3.bytes;
} else {
lightGuideUpdateMessage = calloc(lightGuideUpdateMessageSize, 1);
lightGuideUpdateMessage[0] = _mk == 1 ? kCommandLightGuideUpdateMK1 : kCommandLightGuideUpdateMK2;
}

// FIXME: This is likely wrong for MK1 devices!
buttonLightingUpdateMessage[0] = kCommandButtonLightsUpdate;
_deviceName =
Expand Down Expand Up @@ -588,6 +597,13 @@ - (BOOL)setReport:(const unsigned char*)report length:(size_t)length error:(NSEr

- (BOOL)updateLightGuideMap:(NSError**)error
{
extern const double kTimeoutDelay;

if (_mk == 3) {
BOOL ret = [usb bulkWriteData:lightGuideStreamMK3 error:error];
[usb waitForBulkTransfer:kTimeoutDelay];
return ret;
}
return [self setReport:lightGuideUpdateMessage length:lightGuideUpdateMessageSize error:error];
}

Expand Down Expand Up @@ -625,6 +641,7 @@ - (void)lightKeysWithColor:(unsigned char)color
memset(_keys, color, kKompleteKontrolLightGuideKeyMapSize);
break;
case 3:

for (unsigned int i = 0; i < 128; i++) {
_keys[i * 3 + 0] = kCommandLightGuideKeyCommandMK3;
_keys[i * 3 + 1] = i;
Expand Down
5 changes: 4 additions & 1 deletion KompleteSynthesia/USBController.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ extern const uint32_t kPID_S49MK3;
extern const uint32_t kPID_S61MK3;
extern const uint32_t kPID_S88MK3;

@class LogViewController;

@interface USBController : NSObject

@property (nonatomic, copy) NSString* deviceName;
Expand All @@ -41,7 +43,8 @@ extern const uint32_t kPID_S88MK3;

+ (NSString*)descriptionWithIOReturn:(IOReturn)code;

- (id)initWithError:(NSError**)error;
- (id)initWithLogViewController:(LogViewController*)lc;
- (BOOL)setupWithError:(NSError**)error;
- (BOOL)bulkWriteData:(NSData*)data error:(NSError**)error;
- (BOOL)waitForBulkTransfer:(NSTimeInterval)timeout;
- (void)teardown;
Expand Down
42 changes: 29 additions & 13 deletions KompleteSynthesia/USBController.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#import <IOKit/IOKitLib.h>
#import <IOKit/usb/IOUSBLib.h>

#import "LogViewController.h"

/// Detects a Komplete Kontrol S-series USB controller. Supports USB bulk write for transmitting large amounts of data
/// as needed for graphics data transfer to the LCD screens.

Expand All @@ -34,41 +36,53 @@
const uint32_t kPID_S61MK3 = 0x2110; // Confirmed, thanks to @Bounga.
const uint32_t kPID_S88MK3 = 0x2120; // FIXME: NO IDEA - THESE ARE PLACEHOLDERS SO FAR

const uint32_t kUSBDeviceInterface = 0x03; // FIXME: Possibly MK2 specific.
const uint32_t kUSBDeviceInterfaceEndpoint = 0x03; // FIXME: Possibly MK2 specific.
// Bulk transfer interface specifications.
const uint32_t kUSBDeviceInterfaceMK2 = 0x03;
const uint32_t kUSBDeviceInterfaceEndpointMK2 = 0x03;

const uint32_t kUSBDeviceInterfaceMK3 = 0x04;
const uint32_t kUSBDeviceInterfaceEndpointMK3 = 0x04;

@implementation USBController {
IOUSBDeviceInterface942** device;
IOUSBInterfaceInterface942** interface;
uint8_t endpointCount;
uint8_t endpointAddresses[32];
dispatch_semaphore_t transfers;
LogViewController* log;
}

+ (NSString*)descriptionWithIOReturn:(IOReturn)err
{
return [NSString stringWithCString:mach_error_string(err) encoding:NSStringEncodingConversionAllowLossy];
}

- (id)initWithError:(NSError**)error
- (id)initWithLogViewController:(LogViewController*)lc
{
self = [super init];
if (self) {
_connected = NO;
_deviceInterfaceEndpoint = kUSBDeviceInterfaceEndpoint;
log = lc;
transfers = dispatch_semaphore_create(0);
if ([self detectDevice:error] == NULL) {
return nil;
}
NSLog(@"detected %@ USB device", _deviceName);
if ([self openDevice:error] == NO) {
return nil;
}
NSLog(@"USB controller fully connected - up and running");
}
return self;
}

- (BOOL)setupWithError:(NSError**)error
{
_connected = NO;
if ([self detectDevice:error] == NULL) {
return NO;
}
[log logLine:[NSString stringWithFormat:@"detected %@ USB device", _deviceName]];

if ([self openDevice:error] == NO) {
return NO;
}
NSLog(@"USB controller fully connected - up and running");
return YES;
}

- (void)dealloc
{
if (interface != NULL) {
Expand Down Expand Up @@ -430,7 +444,9 @@ - (BOOL)openDevice:(NSError**)error
return NO;
}

ret = [self openDeviceInterface:kUSBDeviceInterface];
_deviceInterfaceEndpoint = _mk == 2 ? kUSBDeviceInterfaceEndpointMK2 : kUSBDeviceInterfaceEndpointMK3;

ret = [self openDeviceInterface:_mk == 2 ? kUSBDeviceInterfaceMK2 : kUSBDeviceInterfaceMK3];
if (ret != kIOReturnSuccess) {
if (error) {
NSDictionary* userInfo = @{
Expand Down
2 changes: 1 addition & 1 deletion KompleteSynthesia/VideoController.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef struct {

@property (nonatomic, strong) NSTextField* volumeValue;

- (id)initWithLogViewController:(LogViewController*)lc error:(NSError**)error;
- (id)initWithUSBController:(USBController*)uc logViewController:(LogViewController*)lc error:(NSError**)error;
- (BOOL)reset:(NSError**)error;
- (void)teardown;
- (void)showOSD;
Expand Down
9 changes: 2 additions & 7 deletions KompleteSynthesia/VideoController.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ @implementation VideoController {
BOOL showValue;
}

- (id)initWithLogViewController:(LogViewController*)lc error:(NSError**)error
- (id)initWithUSBController:(USBController*)uc logViewController:(LogViewController*)lc error:(NSError**)error
{
self = [super init];
if (self) {
Expand All @@ -69,12 +69,7 @@ - (id)initWithLogViewController:(LogViewController*)lc error:(NSError**)error
imageConversionScaleBuffer = NULL;

log = lc;

usb = [[USBController alloc] initWithError:error];
if (usb == nil) {
return nil;
}
[log logLine:[NSString stringWithFormat:@"detected %@ USB device", usb.deviceName]];
usb = uc;

if (usb.mk > 1) {
_screenCount = usb.mk == 2 ? 2 : 1;
Expand Down

0 comments on commit 72b4ace

Please sign in to comment.