diff --git a/.swiftlint.yml b/.swiftlint.yml index 94df041..bd69489 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,6 +3,7 @@ disabled_rules: - function_body_length - identifier_name - trailing_comma + - large_tuple type_body_length: 500 file_length: 750 cyclomatic_complexity: @@ -10,4 +11,4 @@ cyclomatic_complexity: opening_brace: allow_multiline_func: true excluded: - - .build \ No newline at end of file + - .build diff --git a/MonitorControl/Info.plist b/MonitorControl/Info.plist index b541340..508171f 100644 --- a/MonitorControl/Info.plist +++ b/MonitorControl/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 7036 + 7045 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/MonitorControl/Model/OtherDisplay.swift b/MonitorControl/Model/OtherDisplay.swift index dee05dd..d920990 100644 --- a/MonitorControl/Model/OtherDisplay.swift +++ b/MonitorControl/Model/OtherDisplay.swift @@ -431,9 +431,9 @@ class OtherDisplay: Display { } DisplayManager.shared.globalDDCQueue.sync { if let unwrappedDelay = delay { - values = Arm64DDC.read(service: self.arm64avService, command: controlCode, tries: UInt8(min(tries, 255)), minReplyDelay: UInt32(unwrappedDelay / 1000)) + values = Arm64DDC.read(service: self.arm64avService, command: controlCode, readSleepTime: UInt32(unwrappedDelay / 1000), numOfRetryAttemps: UInt8(min(tries, 255))) } else { - values = Arm64DDC.read(service: self.arm64avService, command: controlCode, tries: UInt8(min(tries, 255))) + values = Arm64DDC.read(service: self.arm64avService, command: controlCode, numOfRetryAttemps: UInt8(min(tries, 255))) } } } else { diff --git a/MonitorControl/Support/Arm64DDC.swift b/MonitorControl/Support/Arm64DDC.swift index d59615c..b6e678a 100644 --- a/MonitorControl/Support/Arm64DDC.swift +++ b/MonitorControl/Support/Arm64DDC.swift @@ -3,32 +3,52 @@ import Foundation import IOKit -class Arm64DDC: NSObject { - public struct DisplayService { - var displayID: CGDirectDisplayID = 0 - var service: IOAVService? - var serviceLocation: Int = 0 - var isDiscouraged: Bool = false - var isDummy: Bool = false - } +let ARM64_DDC_7BIT_ADDRESS: UInt8 = 0x37 // This works with DisplayPort devices +let ARM64_DDC_DATA_ADDRESS: UInt8 = 0x51 +class Arm64DDC: NSObject { #if arch(arm64) public static let isArm64: Bool = true #else public static let isArm64: Bool = false #endif + static let MAX_MATCH_SCORE: Int = 20 - // This matches Displays to the right IOAVService - public static func getServiceMatches(displayIDs: [CGDirectDisplayID]) -> [DisplayService] { + struct IOregService { + var edidUUID: String = "" + var manufacturerID: String = "" + var productName: String = "" + var serialNumber: Int64 = 0 + var alphanumericSerialNumber: String = "" + var location: String = "" + var ioDisplayLocation: String = "" + var transportUpstream: String = "" + var transportDownstream: String = "" + var service: IOAVService? + var serviceLocation: Int = 0 + var displayAttributes: NSDictionary? + } + + struct Arm64Service { + var displayID: CGDirectDisplayID = 0 + var service: IOAVService? + var serviceLocation: Int = 0 + var discouraged: Bool = false + var dummy: Bool = false + var serviceDetails: IOregService + var matchScore: Int = 0 + } + + static func getServiceMatches(displayIDs: [CGDirectDisplayID]) -> [Arm64Service] { let ioregServicesForMatching = self.getIoregServicesForMatching() - var matchedDisplayServices: [DisplayService] = [] - var scoredCandidateDisplayServices: [Int: [DisplayService]] = [:] + var matchedDisplayServices: [Arm64Service] = [] + var scoredCandidateDisplayServices: [Int: [Arm64Service]] = [:] for displayID in displayIDs { for ioregServiceForMatching in ioregServicesForMatching { - let score = self.ioregMatchScore(displayID: displayID, ioregEdidUUID: ioregServiceForMatching.edidUUID, ioregProductName: ioregServiceForMatching.productName, ioregSerialNumber: ioregServiceForMatching.serialNumber, serviceLocation: ioregServiceForMatching.serviceLocation) - let isDiscouraged = self.checkIfDiscouraged(ioregService: ioregServiceForMatching) - let isDummy = self.checkIfDummy(ioregService: ioregServiceForMatching) - let displayService = DisplayService(displayID: displayID, service: ioregServiceForMatching.service, serviceLocation: ioregServiceForMatching.serviceLocation, isDiscouraged: isDiscouraged, isDummy: isDummy) + let score = self.ioregMatchScore(displayID: displayID, ioregEdidUUID: ioregServiceForMatching.edidUUID, ioDisplayLocation: ioregServiceForMatching.ioDisplayLocation, ioregProductName: ioregServiceForMatching.productName, ioregSerialNumber: ioregServiceForMatching.serialNumber, serviceLocation: ioregServiceForMatching.serviceLocation) + let discouraged = self.checkIfDiscouraged(ioregService: ioregServiceForMatching) + let dummy = self.checkIfDummy(ioregService: ioregServiceForMatching) + let displayService = Arm64Service(displayID: displayID, service: ioregServiceForMatching.service, serviceLocation: ioregServiceForMatching.serviceLocation, discouraged: discouraged, dummy: dummy, serviceDetails: ioregServiceForMatching, matchScore: score) if scoredCandidateDisplayServices[score] == nil { scoredCandidateDisplayServices[score] = [] } @@ -39,24 +59,21 @@ class Arm64DDC: NSObject { var takenDisplayIDs: [CGDirectDisplayID] = [] for score in stride(from: self.MAX_MATCH_SCORE, to: 0, by: -1) { if let scoredCandidateDisplayService = scoredCandidateDisplayServices[score] { - for candidateDisplayService in scoredCandidateDisplayService { - if !(takenDisplayIDs.contains(candidateDisplayService.displayID) || takenServiceLocations.contains(candidateDisplayService.serviceLocation)) { - takenDisplayIDs.append(candidateDisplayService.displayID) - takenServiceLocations.append(candidateDisplayService.serviceLocation) - matchedDisplayServices.append(candidateDisplayService) - } + for candidateDisplayService in scoredCandidateDisplayService where !(takenDisplayIDs.contains(candidateDisplayService.displayID) || takenServiceLocations.contains(candidateDisplayService.serviceLocation)) { + takenDisplayIDs.append(candidateDisplayService.displayID) + takenServiceLocations.append(candidateDisplayService.serviceLocation) + matchedDisplayServices.append(candidateDisplayService) } } } return matchedDisplayServices } - // Perform DDC read - public static func read(service: IOAVService?, command: UInt8, tries: UInt8 = 3, minReplyDelay: UInt32 = 10000) -> (current: UInt16, max: UInt16)? { + static func read(service: IOAVService?, command: UInt8, writeSleepTime: UInt32? = nil, numOfWriteCycles: UInt8? = nil, readSleepTime: UInt32? = nil, numOfRetryAttemps: UInt8? = nil, retrySleepTime: UInt32? = nil) -> (current: UInt16, max: UInt16)? { var values: (UInt16, UInt16)? var send: [UInt8] = [command] var reply = [UInt8](repeating: 0, count: 11) - if Arm64DDC.performDDCCommunication(service: service, send: &send, reply: &reply, readSleepTime: minReplyDelay, numOfRetryAttemps: tries) { + if Self.performDDCCommunication(service: service, send: &send, reply: &reply, writeSleepTime: writeSleepTime, numOfWriteCycles: numOfWriteCycles, readSleepTime: readSleepTime, numOfRetryAttemps: numOfRetryAttemps, retrySleepTime: retrySleepTime) { let max = UInt16(reply[6]) * 256 + UInt16(reply[7]) let current = UInt16(reply[8]) * 256 + UInt16(reply[9]) values = (current, max) @@ -66,64 +83,41 @@ class Arm64DDC: NSObject { return values } - // Perform DDC write - public static func write(service: IOAVService?, command: UInt8, value: UInt16) -> Bool { + static func write(service: IOAVService?, command: UInt8, value: UInt16, writeSleepTime: UInt32? = nil, numOfWriteCycles: UInt8? = nil, numOfRetryAttemps: UInt8? = nil, retrySleepTime: UInt32? = nil) -> Bool { var send: [UInt8] = [command, UInt8(value >> 8), UInt8(value & 255)] var reply: [UInt8] = [] - return Arm64DDC.performDDCCommunication(service: service, send: &send, reply: &reply) + return Self.performDDCCommunication(service: service, send: &send, reply: &reply, writeSleepTime: writeSleepTime, numOfWriteCycles: numOfWriteCycles, numOfRetryAttemps: numOfRetryAttemps, retrySleepTime: retrySleepTime) } - // Performs DDC read or write - public static func performDDCCommunication(service: IOAVService?, send: inout [UInt8], reply: inout [UInt8], writeSleepTime: UInt32 = 10000, numofWriteCycles: UInt8 = 2, readSleepTime: UInt32 = 10000, numOfRetryAttemps: UInt8 = 3, retrySleepTime: UInt32 = 20000) -> Bool { + static func performDDCCommunication(service: IOAVService?, send: inout [UInt8], reply: inout [UInt8], writeSleepTime: UInt32? = nil, numOfWriteCycles: UInt8? = nil, readSleepTime: UInt32? = nil, numOfRetryAttemps: UInt8? = nil, retrySleepTime: UInt32? = nil) -> Bool { + let dataAddress = ARM64_DDC_DATA_ADDRESS var success = false guard service != nil else { return success } - var checkedsend: [UInt8] = [UInt8(0x80 | (send.count + 1)), UInt8(send.count)] + send + [0] - checkedsend[checkedsend.count - 1] = self.checksum(chk: send.count == 1 ? 0x6E : 0x6E ^ 0x51, data: &checkedsend, start: 0, end: checkedsend.count - 2) - for _ in 1 ... numOfRetryAttemps { - for _ in 1 ... numofWriteCycles { - usleep(writeSleepTime) - if IOAVServiceWriteI2C(service, 0x37, 0x51, &checkedsend, UInt32(checkedsend.count)) == 0 { - success = true - } + var packet: [UInt8] = [UInt8(0x80 | (send.count + 1)), UInt8(send.count)] + send + [0] // Note: the last byte is the place of the checksum, see next line! + packet[packet.count - 1] = self.checksum(chk: send.count == 1 ? ARM64_DDC_7BIT_ADDRESS << 1 : ARM64_DDC_7BIT_ADDRESS << 1 ^ dataAddress, data: &packet, start: 0, end: packet.count - 2) + for _ in 1 ... (numOfRetryAttemps ?? 4) + 1 { + for _ in 1 ... max((numOfWriteCycles ?? 2) + 0, 1) { + usleep(writeSleepTime ?? 10000) + success = IOAVServiceWriteI2C(service, UInt32(ARM64_DDC_7BIT_ADDRESS), UInt32(dataAddress), &packet, UInt32(packet.count)) == 0 } - if reply.count > 0 { - usleep(readSleepTime) - if IOAVServiceReadI2C(service, 0x37, 0x51, &reply, UInt32(reply.count)) == 0 { - if self.checksum(chk: 0x50, data: &reply, start: 0, end: reply.count - 2) == reply[reply.count - 1] { - success = true - } else { - success = false - } + if !reply.isEmpty { + usleep(readSleepTime ?? 50000) + if IOAVServiceReadI2C(service, UInt32(ARM64_DDC_7BIT_ADDRESS), UInt32(dataAddress), &reply, UInt32(reply.count)) == 0 { + success = self.checksum(chk: 0x50, data: &reply, start: 0, end: reply.count - 2) == reply[reply.count - 1] } } if success { return success } - usleep(retrySleepTime) + usleep(retrySleepTime ?? 20000) } return success } - // ------- - - private struct IOregService { - var edidUUID: String = "" - var manufacturerID: String = "" - var productName: String = "" - var serialNumber: Int64 = 0 - var location: String = "" - var transportUpstream: String = "" - var transportDownstream: String = "" - var service: IOAVService? - var serviceLocation: Int = 0 - } - - private static let MAX_MATCH_SCORE: Int = 13 - // DDC checksum calculator - private static func checksum(chk: UInt8, data: inout [UInt8], start: Int, end: Int) -> UInt8 { + static func checksum(chk: UInt8, data: inout [UInt8], start: Int, end: Int) -> UInt8 { var chkd: UInt8 = chk for i in start ... end { chkd ^= data[i] @@ -131,8 +125,7 @@ class Arm64DDC: NSObject { return chkd } - // Scores the likelihood of a display match based on EDID UUID, ProductName and SerialNumber from in ioreg, compared to DisplayCreateInfoDictionary. - private static func ioregMatchScore(displayID: CGDirectDisplayID, ioregEdidUUID: String, ioregProductName: String = "", ioregSerialNumber: Int64 = 0, serviceLocation: Int = 0) -> Int { + static func ioregMatchScore(displayID: CGDirectDisplayID, ioregEdidUUID: String, ioDisplayLocation: String = "", ioregProductName: String = "", ioregSerialNumber: Int64 = 0, serviceLocation _: Int = 0) -> Int { var matchScore = 0 if let dictionary = CoreDisplay_DisplayCreateInfoDictionary(displayID)?.takeRetainedValue() as NSDictionary? { if let kDisplayYearOfManufacture = dictionary[kDisplayYearOfManufacture] as? Int64, let kDisplayWeekOfManufacture = dictionary[kDisplayWeekOfManufacture] as? Int64, let kDisplayVendorID = dictionary[kDisplayVendorID] as? Int64, let kDisplayProductID = dictionary[kDisplayProductID] as? Int64, let kDisplayVerticalImageSize = dictionary[kDisplayVerticalImageSize] as? Int64, let kDisplayHorizontalImageSize = dictionary[kDisplayHorizontalImageSize] as? Int64 { @@ -154,66 +147,69 @@ class Arm64DDC: NSObject { + String(format: "%02x", UInt8(max(0, min(kDisplayVerticalImageSize / 10, 256 - 1)))).uppercased(), loc: 30), ] for searchKey in edidUUIDSearchKeys where searchKey.key != "0000" && searchKey.key == ioregEdidUUID.prefix(searchKey.loc + 4).suffix(4) { - matchScore += 2 + matchScore += 1 } } + if ioDisplayLocation != "", let kIODisplayLocation = dictionary[kIODisplayLocationKey] as? String, ioDisplayLocation == kIODisplayLocation { + matchScore += 10 + } if ioregProductName != "", let nameList = dictionary["DisplayProductName"] as? [String: String], let name = nameList["en_US"] ?? nameList.first?.value, name.lowercased() == ioregProductName.lowercased() { - matchScore += 2 + matchScore += 1 } if ioregSerialNumber != 0, let serial = dictionary[kDisplaySerialNumber] as? Int64, serial == ioregSerialNumber { - matchScore += 2 - } - if serviceLocation == displayID { matchScore += 1 } } return matchScore } - // Iterate to the next AppleCLCD2 or DCPAVServiceProxy item in the ioreg tree and return the name and corresponding service - private static func ioregIterateToNextObjectOfInterest(interests _: [String], iterator: inout io_iterator_t) -> (name: String, service: io_service_t)? { - var objectName = "" - var service: io_service_t = IO_OBJECT_NULL + static func ioregIterateToNextObjectOfInterest(interests: [String], iterator: inout io_iterator_t) -> (name: String, entry: io_service_t, preceedingEntry: io_service_t)? { + var entry: io_service_t = IO_OBJECT_NULL + var preceedingEntry: io_service_t = IO_OBJECT_NULL let name = UnsafeMutablePointer.allocate(capacity: MemoryLayout.size) defer { name.deallocate() } while true { - service = IOIteratorNext(iterator) - guard service != MACH_PORT_NULL else { - service = IO_OBJECT_NULL + preceedingEntry = entry + entry = IOIteratorNext(iterator) + guard IORegistryEntryGetName(entry, name) == KERN_SUCCESS, entry != MACH_PORT_NULL else { break } - guard IORegistryEntryGetName(service, name) == KERN_SUCCESS else { - service = IO_OBJECT_NULL - break - } - if String(cString: name) == "AppleCLCD2" || String(cString: name) == "DCPAVServiceProxy" { - objectName = String(cString: name) - return (objectName, service) + let nameString = String(cString: name) + for interest in interests where entry != IO_OBJECT_NULL && nameString.contains(interest) { + return (nameString, entry, preceedingEntry) } } return nil } - // Returns EDID UUDI, Product Name and Serial Number in an IOregService if it is found using the provided io_service_t pointing to a AppleCDC2 item in the ioreg tree - private static func getIORegServiceAppleCDC2Properties(service: io_service_t) -> IOregService { + static func getIORegServiceAppleCDC2Properties(entry: io_service_t) -> IOregService { var ioregService = IOregService() - if let unmanagedEdidUUID = IORegistryEntryCreateCFProperty(service, "EDID UUID" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let edidUUID = unmanagedEdidUUID.takeRetainedValue() as? String { + if let unmanagedEdidUUID = IORegistryEntryCreateCFProperty(entry, "EDID UUID" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let edidUUID = unmanagedEdidUUID.takeRetainedValue() as? String { ioregService.edidUUID = edidUUID } - if let unmanagedDisplayAttrs = IORegistryEntryCreateCFProperty(service, "DisplayAttributes" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let displayAttrs = unmanagedDisplayAttrs.takeRetainedValue() as? NSDictionary, let productAttrs = displayAttrs.value(forKey: "ProductAttributes") as? NSDictionary { - if let manufacturerID = productAttrs.value(forKey: "ManufacturerID") as? String { - ioregService.manufacturerID = manufacturerID - } - if let productName = productAttrs.value(forKey: "ProductName") as? String { - ioregService.productName = productName - } - if let serialNumber = productAttrs.value(forKey: "SerialNumber") as? Int64 { - ioregService.serialNumber = serialNumber + let cpath = UnsafeMutablePointer.allocate(capacity: MemoryLayout.size) + IORegistryEntryGetPath(entry, kIOServicePlane, cpath) + ioregService.ioDisplayLocation = String(cString: cpath) + if let unmanagedDisplayAttrs = IORegistryEntryCreateCFProperty(entry, "DisplayAttributes" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let displayAttrs = unmanagedDisplayAttrs.takeRetainedValue() as? NSDictionary { + ioregService.displayAttributes = displayAttrs + if let productAttrs = displayAttrs.value(forKey: "ProductAttributes") as? NSDictionary { + if let manufacturerID = productAttrs.value(forKey: "ManufacturerID") as? String { + ioregService.manufacturerID = manufacturerID + } + if let productName = productAttrs.value(forKey: "ProductName") as? String { + ioregService.productName = productName + } + if let serialNumber = productAttrs.value(forKey: "SerialNumber") as? Int64 { + ioregService.serialNumber = serialNumber + } + if let alphanumericSerialNumber = productAttrs.value(forKey: "AlphanumericSerialNumber") as? String { + ioregService.alphanumericSerialNumber = alphanumericSerialNumber + } } } - if let unmanagedTransport = IORegistryEntryCreateCFProperty(service, "Transport" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let transport = unmanagedTransport.takeRetainedValue() as? NSDictionary { + if let unmanagedTransport = IORegistryEntryCreateCFProperty(entry, "Transport" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let transport = unmanagedTransport.takeRetainedValue() as? NSDictionary { if let upstream = transport.value(forKey: "Upstream") as? String { ioregService.transportUpstream = upstream } @@ -224,18 +220,16 @@ class Arm64DDC: NSObject { return ioregService } - // Sets up the service in an IOregService if it is found using the provided io_service_t pointing to a DCPAVServiceProxy item in the ioreg tree - private static func setIORegServiceDCPAVServiceProxy(service: io_service_t, ioregService: inout IOregService) { - if let unmanagedLocation = IORegistryEntryCreateCFProperty(service, "Location" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let location = unmanagedLocation.takeRetainedValue() as? String { + static func setIORegServiceDCPAVServiceProxy(entry: io_service_t, ioregService: inout IOregService) { + if let unmanagedLocation = IORegistryEntryCreateCFProperty(entry, "Location" as CFString, kCFAllocatorDefault, IOOptionBits(kIORegistryIterateRecursively)), let location = unmanagedLocation.takeRetainedValue() as? String { ioregService.location = location if location == "External" { - ioregService.service = IOAVServiceCreateWithService(kCFAllocatorDefault, service)?.takeRetainedValue() as IOAVService + ioregService.service = IOAVServiceCreateWithService(kCFAllocatorDefault, entry)?.takeRetainedValue() as IOAVService } } } - // Returns IOAVSerivces with associated display properties for matching logic - private static func getIoregServicesForMatching() -> [IOregService] { + static func getIoregServicesForMatching() -> [IOregService] { var serviceLocation = 0 var ioregServicesForMatching: [IOregService] = [] let ioregRoot: io_registry_entry_t = IORegistryGetRootEntry(kIOMasterPortDefault) @@ -250,49 +244,32 @@ class Arm64DDC: NSObject { guard IORegistryEntryCreateIterator(ioregRoot, "IOService", IOOptionBits(kIORegistryIterateRecursively), &iterator) == KERN_SUCCESS else { return ioregServicesForMatching } + let keyDCPAVServiceProxy = "DCPAVServiceProxy" + let keysFramebuffer = ["AppleCLCD2", "IOMobileFramebufferShim"] while true { - if let objectOfInterest = ioregIterateToNextObjectOfInterest(interests: ["AppleCLCD2", "DCPAVServiceProxy"], iterator: &iterator) { - if objectOfInterest.name == "AppleCLCD2", objectOfInterest.service != IO_OBJECT_NULL { - ioregService = self.getIORegServiceAppleCDC2Properties(service: objectOfInterest.service) - serviceLocation += 1 - ioregService.serviceLocation = serviceLocation - } - if objectOfInterest.name == "DCPAVServiceProxy", objectOfInterest.service != IO_OBJECT_NULL { - self.setIORegServiceDCPAVServiceProxy(service: objectOfInterest.service, ioregService: &ioregService) - ioregServicesForMatching.append(ioregService) - } - } else { + guard let objectOfInterest = ioregIterateToNextObjectOfInterest(interests: [keyDCPAVServiceProxy] + keysFramebuffer, iterator: &iterator) else { break } + if keysFramebuffer.contains(objectOfInterest.name) { + ioregService = self.getIORegServiceAppleCDC2Properties(entry: objectOfInterest.entry) + serviceLocation += 1 + ioregService.serviceLocation = serviceLocation + } else if objectOfInterest.name == keyDCPAVServiceProxy { + self.setIORegServiceDCPAVServiceProxy(entry: objectOfInterest.entry, ioregService: &ioregService) + ioregServicesForMatching.append(ioregService) + } } return ioregServicesForMatching } - // Check if display is a dummy - private static func checkIfDummy(ioregService: IOregService) -> Bool { - // This is a well known dummy plug + static func checkIfDummy(ioregService: IOregService) -> Bool { if ioregService.manufacturerID == "AOC", ioregService.productName == "28E850" { return true } return false } - // Check if it is problematic to enable DDC on the display - private static func checkIfDiscouraged(ioregService: IOregService) -> Bool { - var modelIdentifier = "" - let platformExpertDevice = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")) - if let modelData = IORegistryEntryCreateCFProperty(platformExpertDevice, "model" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? Data, let modelIdentifierCString = String(data: modelData, encoding: .utf8)?.cString(using: .utf8) { - modelIdentifier = String(cString: modelIdentifierCString) - } - // First service location of M1 Mac Mini & Macbook Pro HDMI is broken for DDC communication - let ddcBlockedModels = [ - "Macmini9", // Mac mini M1 2020 - "MacBookPro18", // Macbook Pro M1 Pro/Max 2021 (14", 16") - ] - let isBlockedModel = ddcBlockedModels.contains { $0.starts(with: modelIdentifier) } - if ioregService.transportDownstream == "HDMI", ioregService.serviceLocation == 1, isBlockedModel { - return true - } - return false + static func checkIfDiscouraged(ioregService _: IOregService) -> Bool { + false } } diff --git a/MonitorControl/Support/DisplayManager.swift b/MonitorControl/Support/DisplayManager.swift index 832258d..b828125 100644 --- a/MonitorControl/Support/DisplayManager.swift +++ b/MonitorControl/Support/DisplayManager.swift @@ -312,10 +312,10 @@ class DisplayManager { for otherDisplay in self.getOtherDisplays() where otherDisplay.identifier == serviceMatch.displayID && serviceMatch.service != nil { otherDisplay.arm64avService = serviceMatch.service os_log("Display service match successful for display %{public}@", type: .info, String(serviceMatch.displayID)) - if serviceMatch.isDiscouraged { + if serviceMatch.discouraged { os_log("Display %{public}@ is flagged as discouraged by Arm64DDC.", type: .info, String(serviceMatch.displayID)) otherDisplay.isDiscouraged = true - } else if serviceMatch.isDummy { + } else if serviceMatch.dummy { os_log("Display %{public}@ is flagged as dummy by Arm64DDC.", type: .info, String(serviceMatch.displayID)) otherDisplay.isDiscouraged = true otherDisplay.isDummy = true