Skip to content

Commit

Permalink
make reply-timeouts tuneable at runtime with -W flag
Browse files Browse the repository at this point in the history
maintains values from fe2ef4a8c6, but allows them to be changed
by the command invocation.

relates to #57
  • Loading branch information
kfix committed Jan 10, 2021
1 parent 167540a commit d3ab6ec
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
26 changes: 14 additions & 12 deletions src/DDC.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#define kIOFBDependentIndexKey "IOFBDependentIndex"
#endif

long DDCDelayBase = 1; // nanoseconds

/*
Iterate IOreg's device tree to find the IOFramebuffer mach service port that corresponds to a given CGDisplayID && IOReg path
Expand Down Expand Up @@ -193,11 +195,16 @@ bool FramebufferI2CRequest(io_service_t framebuffer, IOI2CRequest *request) {
}

long DDCDelay(io_service_t framebuffer) {
// Certain displays / graphics cards require a long-enough delay to yield a response to DDC commands
// Relying on retry will not help if the delay is too short.
// kernel panics are possible if value is wrong
// https://developer.apple.com/documentation/iokit/ioi2crequest/1410394-minreplydelay?language=objc

CFStringRef ioRegPath = IORegistryEntryCopyPath(framebuffer, kIOServicePlane);
if (CFStringFind(ioRegPath, CFSTR("/AMD"), kCFCompareCaseInsensitive).location != kCFNotFound) {
return 30000000; // Team Red needs more time, as usual!
return DDCDelayBase + 30000000; // Team Red needs more time, as usual!
}
return 1;
return DDCDelayBase;
}

bool DDCWrite(io_service_t framebuffer, struct DDCWriteCommand *write) {
Expand Down Expand Up @@ -234,6 +241,8 @@ bool DDCRead(io_service_t framebuffer, struct DDCReadCommand *read) {
bool result = false;
UInt8 data[128];

long reply_timeout = DDCDelay(framebuffer) * kNanosecondScale;

for (int i=1; i<=kMaxRequests; i++) {
bzero(&request, sizeof(request));

Expand All @@ -242,14 +251,7 @@ bool DDCRead(io_service_t framebuffer, struct DDCReadCommand *read) {
request.sendTransactionType = kIOI2CSimpleTransactionType;
request.sendBuffer = (vm_address_t) &data[0];
request.sendBytes = 5;
// Certain displays / graphics cards require a long-enough delay to give a response.
// Relying on retry will not help if the delay is too short.
request.minReplyDelay = DDCDelay(framebuffer) * kNanosecondScale;
// FIXME: this should be tuneable at runtime
// https://github.com/kfix/ddcctl/issues/57
// incorrect values for GPU-vendor can cause kernel panic
// https://developer.apple.com/documentation/iokit/ioi2crequest/1410394-minreplydelay?language=objc

request.minReplyDelay = reply_timeout;
data[0] = 0x51;
data[1] = 0x82;
data[2] = 0x01;
Expand All @@ -273,7 +275,7 @@ bool DDCRead(io_service_t framebuffer, struct DDCReadCommand *read) {

if (result) { // checksum is ok
if (i > 1) {
printf("D: Tries required to get data: %d \n", i);
printf("D: Tries required to get data: %d (%ldns reply-timeout)\n", i, reply_timeout);
}
break;
}
Expand All @@ -286,7 +288,7 @@ bool DDCRead(io_service_t framebuffer, struct DDCReadCommand *read) {
read->success = false;
read->max_value = 0;
read->current_value = 0;
printf("E: No data after %d tries! \n", i);
printf("E: No data after %d tries! (%ldns reply-timeout)\n", i, reply_timeout);
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/DDC.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ struct EDID {
UInt8 checksum : 8;
};

long DDCDelayBase;
long DDCDelay(io_service_t framebuffer);
bool DDCWrite(io_service_t framebuffer, struct DDCWriteCommand *write);
bool DDCRead(io_service_t framebuffer, struct DDCReadCommand *read);
Expand Down
12 changes: 11 additions & 1 deletion src/ddcctl.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

extern io_service_t CGDisplayIOServicePort(CGDirectDisplayID display) __attribute__((weak_import));

extern long DDCDelayBase;

NSString *EDIDString(char *string)
{
NSString *temp = [[NSString alloc] initWithBytes:string length:13 encoding:NSASCIIStringEncoding];
Expand Down Expand Up @@ -217,7 +219,8 @@ int main(int argc, const char * argv[])

NSString *HelpString = @"Usage:\n"
@"ddcctl \t-d <1-..> [display#]\n"
@"\t-w 100000 [delay usecs between settings]\n"
@"\t-w <0-..> [delay in usecs between settings]\n"
@"\t-W <0-..> [timeout in nanosecs for replies]\n"
@"\n"
@"----- Basic settings -----\n"
@"\t-b <1-..> [brightness]\n"
Expand Down Expand Up @@ -363,6 +366,13 @@ int main(int argc, const char * argv[])
if (i >= argc) break;
command_interval = atoi(argv[i]);
}

else if (!strcmp(argv[i], "-W")) {
i++;
if (i >= argc) break;
DDCDelayBase = atoi(argv[i]);
}

#ifdef OSD
else if (!strcmp(argv[i], "-O")) {
useOsd = YES;
Expand Down

0 comments on commit d3ab6ec

Please sign in to comment.