Skip to content

Commit d2f09d1

Browse files
authored
Fix Intel DDC Swift optimization issue (MonitorControl#562)
1 parent c8a15c5 commit d2f09d1

File tree

1 file changed

+68
-61
lines changed

1 file changed

+68
-61
lines changed

MonitorControl/Support/IntelDDC.swift

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Original code: https://github.com/reitermarkus/DDC.swift
66
// Adapted for MonitorControl
7-
// Credits to @reitermarkus
7+
// Credits to @reitermarkus, @waydabber
88
//
99

1010
import Foundation
@@ -38,84 +38,91 @@ public class IntelDDC {
3838
}
3939

4040
public func write(command: UInt8, value: UInt16, errorRecoveryWaitTime: UInt32? = nil, writeSleepTime: UInt32 = 10000, numofWriteCycles: UInt8 = 2) -> Bool {
41-
let message: [UInt8] = [0x03, command, UInt8(value >> 8), UInt8(value & 0xFF)]
42-
var replyData: [UInt8] = []
4341
var success: Bool = false
42+
var data: [UInt8] = Array(repeating: 0, count: 7)
43+
44+
data[0] = 0x51
45+
data[1] = 0x84
46+
data[2] = 0x03
47+
data[3] = command
48+
data[4] = UInt8(value >> 8)
49+
data[5] = UInt8(value & 255)
50+
data[6] = 0x6E ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5]
51+
4452
for _ in 1 ... numofWriteCycles {
4553
usleep(writeSleepTime)
46-
if self.sendMessage(message, replyData: &replyData, errorRecoveryWaitTime: errorRecoveryWaitTime ?? 20000) != nil {
54+
var request = IOI2CRequest()
55+
request.commFlags = 0
56+
request.sendAddress = 0x6E
57+
request.sendTransactionType = IOOptionBits(kIOI2CSimpleTransactionType)
58+
request.sendBuffer = withUnsafePointer(to: &data[0]) { vm_address_t(bitPattern: $0) }
59+
request.sendBytes = UInt32(data.count)
60+
request.replyTransactionType = IOOptionBits(kIOI2CNoTransactionType)
61+
request.replyBytes = 0
62+
if IntelDDC.send(request: &request, to: self.framebuffer, errorRecoveryWaitTime: errorRecoveryWaitTime) {
4763
success = true
4864
}
4965
}
5066
return success
5167
}
5268

53-
public func sendMessage(_ message: [UInt8], replyData: inout [UInt8], minReplyDelay: UInt64? = nil, errorRecoveryWaitTime: UInt32? = nil) -> IOI2CRequest? {
54-
var data: [UInt8] = [UInt8(0x51), UInt8(0x80 + message.count)] + message + [UInt8(0x6E)]
55-
for i in 0 ..< (data.count - 1) {
56-
data[data.count - 1] ^= data[i]
57-
}
58-
var request = IOI2CRequest()
59-
request.commFlags = 0
60-
request.sendAddress = 0x6E
61-
request.sendTransactionType = IOOptionBits(kIOI2CSimpleTransactionType)
62-
request.sendBytes = UInt32(data.count)
63-
request.sendBuffer = withUnsafePointer(to: &data[0]) { vm_address_t(bitPattern: $0) }
64-
if replyData.count == 0 {
65-
request.replyTransactionType = IOOptionBits(kIOI2CNoTransactionType)
66-
request.replyBytes = 0
67-
} else {
69+
public func read(command: UInt8, tries: UInt = 1, replyTransactionType _: IOOptionBits? = nil, minReplyDelay: UInt64? = nil, errorRecoveryWaitTime: UInt32? = nil, writeSleepTime: UInt32 = 10000) -> (UInt16, UInt16)? {
70+
var data: [UInt8] = Array(repeating: 0, count: 5)
71+
var replyData: [UInt8] = Array(repeating: 0, count: 11)
72+
73+
data[0] = 0x51
74+
data[1] = 0x82
75+
data[2] = 0x01
76+
data[3] = command
77+
data[4] = 0x6E ^ data[0] ^ data[1] ^ data[2] ^ data[3]
78+
79+
for i in 1 ... tries {
80+
usleep(writeSleepTime)
81+
usleep(errorRecoveryWaitTime ?? 0)
82+
var request = IOI2CRequest()
83+
request.commFlags = 0
84+
request.sendAddress = 0x6E
85+
request.sendTransactionType = IOOptionBits(kIOI2CSimpleTransactionType)
86+
request.sendBuffer = withUnsafePointer(to: &data[0]) { vm_address_t(bitPattern: $0) }
87+
request.sendBytes = UInt32(data.count)
6888
request.minReplyDelay = minReplyDelay ?? 10
6989
request.replyAddress = 0x6F
7090
request.replySubAddress = 0x51
7191
request.replyTransactionType = self.replyTransactionType
7292
request.replyBytes = UInt32(replyData.count)
7393
request.replyBuffer = withUnsafePointer(to: &replyData[0]) { vm_address_t(bitPattern: $0) }
74-
}
75-
guard IntelDDC.send(request: &request, to: self.framebuffer, errorRecoveryWaitTime: errorRecoveryWaitTime) else {
76-
return nil
77-
}
78-
if replyData.count > 0 {
79-
let checksum = replyData.last!
80-
var calculated = UInt8(0x50)
81-
for i in 0 ..< (replyData.count - 1) {
82-
calculated ^= replyData[i]
83-
}
84-
guard checksum == calculated else {
85-
os_log("Checksum of reply does not match. Expected %u, got %u.", type: .error, checksum, calculated)
86-
os_log("Response was: %{public}@", type: .debug, replyData.map { String(format: "%02X", $0) }.joined(separator: " "))
87-
return nil
88-
}
89-
}
90-
return request
91-
}
9294

93-
public func read(command: UInt8, tries: UInt = 1, replyTransactionType _: IOOptionBits? = nil, minReplyDelay: UInt64? = nil, errorRecoveryWaitTime: UInt32? = nil) -> (UInt16, UInt16)? {
94-
assert(tries > 0)
95-
let message: [UInt8] = [0x01, command]
96-
var replyData: [UInt8] = Array(repeating: 0, count: 11)
97-
for i in 1 ... tries {
98-
guard self.sendMessage(message, replyData: &replyData, minReplyDelay: minReplyDelay, errorRecoveryWaitTime: errorRecoveryWaitTime ?? 40000) != nil else {
99-
continue
100-
}
101-
guard replyData[2] == 0x02 else {
102-
os_log("Got wrong response type for %{public}@. Expected %u, got %u.", type: .debug, String(reflecting: command), 0x02, replyData[2])
103-
os_log("Response was: %{public}@", type: .debug, replyData.map { String(format: "%02X", $0) }.joined(separator: " "))
104-
continue
105-
}
106-
guard replyData[3] == 0x00 else {
107-
os_log("Reading %{public}@ is not supported.", type: .debug, String(reflecting: command))
108-
return nil
109-
}
110-
if i > 1 {
111-
os_log("Reading %{public}@ took %u tries.", type: .debug, String(reflecting: command), i)
95+
if IntelDDC.send(request: &request, to: self.framebuffer, errorRecoveryWaitTime: errorRecoveryWaitTime) {
96+
if replyData.count > 0 {
97+
let checksum = replyData.last!
98+
var calculated = UInt8(0x50)
99+
for i in 0 ..< (replyData.count - 1) {
100+
calculated ^= replyData[i]
101+
}
102+
guard checksum == calculated else {
103+
os_log("Checksum of reply does not match. Expected %u, got %u.", type: .debug, checksum, calculated)
104+
os_log("Response was: %{public}@", type: .debug, replyData.map { String(format: "%02X", $0) }.joined(separator: " "))
105+
continue
106+
}
107+
}
108+
guard replyData[2] == 0x02 else {
109+
os_log("Got wrong response type for %{public}@. Expected %u, got %u.", type: .debug, String(reflecting: command), 0x02, replyData[2])
110+
os_log("Response was: %{public}@", type: .debug, replyData.map { String(format: "%02X", $0) }.joined(separator: " "))
111+
continue
112+
}
113+
guard replyData[3] == 0x00 else {
114+
os_log("Reading %{public}@ is not supported.", type: .debug, String(reflecting: command))
115+
return nil
116+
}
117+
if i > 1 {
118+
os_log("Reading %{public}@ took %u tries.", type: .debug, String(reflecting: command), i)
119+
}
120+
let (mh, ml, sh, sl) = (replyData[6], replyData[7], replyData[8], replyData[9])
121+
let maxValue = UInt16(mh << 8) + UInt16(ml)
122+
let currentValue = UInt16(sh << 8) + UInt16(sl)
123+
return (currentValue, maxValue)
112124
}
113-
let (mh, ml, sh, sl) = (replyData[6], replyData[7], replyData[8], replyData[9])
114-
let maxValue = UInt16(mh << 8) + UInt16(ml)
115-
let currentValue = UInt16(sh << 8) + UInt16(sl)
116-
return (currentValue, maxValue)
117125
}
118-
os_log("Reading %{public}@ failed.", type: .error, String(reflecting: command))
119126
return nil
120127
}
121128

0 commit comments

Comments
 (0)