Understand the role of drivers in bridging the gap between software and hardware, ensuring smooth hardware functionality.

Drivers Documentation

Post

Replies

Boosts

Views

Activity

Control HID USB Device from iPad?
I have a custom HID USB device that I can control on Mac with IOKit via the default HID MacOS driver. I am using IOHIDManager to detect it and send reports to it. I would like to extend this capability to iPad but the full IOKit framework is not supported on iOS/iPadOS. I saw that USBDriverKit is now supported on iPads with an M1 chip or newer. But, both MacOS and Windows can operate the device with their generic HID driver. As such, having to create a whole custom driver to interact with an HID device on iOS is really overkill. Would registering it in the MFi Program and operating it with the External Accessory framework be the correct route to take here? Or is there another framework for controlling HID devices on iPad over USB that I am not aware of?
2
0
848
Dec ’23
IOServiceOpen Keeps Returning kIOReturnUnsupported
I have a custom HID device that works on Windows totally fine with the default HID driver. The HID device knows how to accept string commands to control it and respond accordingly. I am trying to control it on Mac using IOKit. I am able to get the io_service_t reference to the IOHIDInterface for the device from the I/ORegistery. I use this to instantiate a class to represent the device. But when I try to establish a connection to the service, I keep getting -536870201 which corresponds to kIOReturnUnsupported. I'm not entirely sure what I am doing wrong here and I wasn't able to find anything online that could really help.
1
0
502
Dec ’23
Metal Device Architecture on macOS versions before Sonoma
Hello, The latest version of Metal (on macOS 14) seems to have the instance property for the Metal device architecture. I was curious how this could be achieved on versions of macOS prior to 14 programatically? xcrun metal-arch The above command provides exactly what I need. I was thinking that I could use Metal and IOKit to grab the architecture, but I am lead to believe that there is some kind of mapping in the metal-arch tool and it may not be that easy. Any help would be greatly appreciated. Thanks.
1
0
504
Dec ’23
Removing a system extension from a correctly-signed and setup "uninstaller" app fails
Hey folks, I have an application that ships a CoreMedia I/O system extension to create a virtual camera. We separately ship an "uninstaller" app, which is a notarised AppKit app. This uninstaller removes the app, containers, and the system extension via the following API: let request = OSSystemExtensionRequest.deactivationRequest(forExtensionWithIdentifier: pluginIdentifier, queue: .main) request.delegate = self OSSystemExtensionManager.shared.submitRequest(request) The OSSystemExtensionRequest API does correctly deliver metadata via propertiesRequest(forExtensionWithIdentifier: …), but when we attempt to remove the extension using the above snippet, we get a failure OSSystemExtensionError.extensionNotFound. The uninstaller app is signed with the same entitlements and certificate as the host app. It also embeds a copy of the system extension as required by the API. I think the crux of the issue is: Should this be expected to work? We're all code-signed correctly etc, and the only difference is that the removal request is coming from an app with a different bundle identifier to the one that installed it start with. Thanks!
2
0
515
Nov ’23
IOHIDDeviceSetReport only works one time
I'm using IOKit to connect to a custom USB HID device. I'm using XCode 14 and running Swift/SwiftUI. So far I have had great success reading from the device with IOHIDDeviceGetReport and this can be done repeatedly with no issues. However, when I use IOHIDDeviceSetReport, I can only successfully set the report to the device one time correctly but any subsequent call to this function would just end up with an I/O Timeout. Any calls using IOHIDDeviceGetReport still works fine so the USB Device is still functioning correctly, but I couldn't receive any additional IOHIDDeviceSetReport call. If I unplug the USB and plug it in again, I can once again successfully send a command. This is, of course, not very practical for the end user to have to unplug and plug the device in after a single set command, and I don't quite understand what's going on with this. Here's my SetOutputReport function to call the IOHIDDeviceSetReport. The IOHIDDevice must already be connected and opened before calling this function so it's not nil. I don't have this "one shot send command" problem on the PC (Windows 7, 10, 11) or Android (v.11,12,13,14) implementation of this Custom USB HID device. It seems like there's something at the lower level of IOHIDDeviceSetReport on macOS which might be done differently than what's available on the PC or Android. Many searches on the web yielded no useful results. There's an IOHIDDeviceSetReportWithCallback function and it also seems only to work one time as well. private func SetOutputReport(dev: IOHIDDevice? ,reportID: Int, data:[UInt8], reportLength: Int) -> String{ let inputReportID = reportID var buffer = data buffer[0] = UInt8(inputReportID) let bufferPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: buffer.count) bufferPointer.initialize(from: &buffer, count: buffer.count) //print(bufferPointer[0]) let bufferLength: CFIndex = buffer.count var success: IOReturn = kIOReturnError if(dev != nil){ success = IOHIDDeviceSetReport(dev!, kIOHIDReportTypeOutput, CFIndex(buffer[0]), bufferPointer, bufferLength) } print("Set report result \(krToString(success))") return krToString(success) }
1
0
646
Nov ’23
How to develop a driver extension for a USB mass storage device
I am currently in the process of developing a DEXT for a USB based external mass storage device using the USBDriverKit framework. IOUSBHostInterface is used as the provider to communicate with the interface's endpoints and I am successful in it. As per the IOUSBHostInterface documentation, To use a host interface object, call Open to create a new session between the interface and your driver. After successfully opening your session, you can request information from the interface and set up pipes to communicate with the interface's endpoints. Remember to close the session you opened in the Stop method of your driver. However, calling Open gains exclusive access to the USB interface and does not allow other services to access the interface. Also, to let go of the exclusive access, Close method can be called but in the Stop method which is called only once during the lifecycle of the extension (when the DEXT is unloaded). As a result of this, Apple's mass storage related KEXTs (media and partition related specifically) do not match the interface and so the filesystem of the drive in question does not get mounted whenever the DEXT has matched the interface. Is this exclusive access a limitation of USBDriverkit or is there any way to get around this issue in this case?
2
0
628
Nov ’23
Capturing ipv6 traffic with AppProxyProvider on MacOS
I have implemented an AppProxyProvider (NETransparentProxyProvider) and I am able to capture traffic with it. I am also able to define network rules allowing me to exclude some traffic: let settings = NETransparentProxyNetworkSettings(tunnelRemoteAddress: "127.0.0.1:8080") settings.includedNetworkRules = [ NENetworkRule(remoteNetwork: NWHostEndpoint(hostname: "0.0.0.0", port: "0", remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound) ] Now the documentation states that if I want to capture localhost traffic, I need to explicitly add the following rule: NENetworkRule(remoteNetwork: NWHostEndpoint(hostname: "127.0.0.0", port: "0", remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound) and if I want to capture ipv6 localhost address: NENetworkRule(remoteNetwork: NWHostEndpoint(hostname: "::1", port: "0", remotePrefix: 128, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound) All this works great. Now I am having trouble capturing external ipv6 traffic. For example my ISP supports ipv6 and facebook.com resolves to 2a03:2880:f128:181:face:b00c:0:25de on my machine. I am unable to write any rule allowing me to capture with the system extension such traffic. Either I get errors that the network mask cannot be greater than 32 or the traffic simply doesn't flow through the extension. Here's an example request that I would like to capture: curl https://facebook.com -kvp * Trying [2a03:2880:f128:181:face:b00c:0:25de]:443... * Connected to facebook.com (2a03:2880:f128:181:face:b00c:0:25de) port 443 (#0) * ALPN: offers h2,http/1.1 * (304) (OUT), TLS handshake, Client hello (1): * (304) (IN), TLS handshake, Server hello (2): * (304) (IN), TLS handshake, Unknown (8): * (304) (IN), TLS handshake, Certificate (11): * (304) (IN), TLS handshake, CERT verify (15): * (304) (IN), TLS handshake, Finished (20): * (304) (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 * ALPN: server accepted h2 * Server certificate: * subject: C=US; ST=California; L=Menlo Park; O=Meta Platforms, Inc.; CN=*.facebook.com * start date: Aug 26 00:00:00 2023 GMT * expire date: Nov 24 23:59:59 2023 GMT * issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA * SSL certificate verify ok. * using HTTP/2 * h2 [:method: GET] * h2 [:scheme: https] * h2 [:authority: facebook.com] * h2 [:path: /] * h2 [user-agent: curl/8.1.2] * h2 [accept: */*] * Using Stream ID: 1 (easy handle 0x7fcb5c011e00) > GET / HTTP/2 > Host: facebook.com > User-Agent: curl/8.1.2 > Accept: */* > < HTTP/2 301 < location: https://www.facebook.com/ < strict-transport-security: max-age=15552000; preload < content-type: text/html; charset="utf-8" < x-fb-debug: uWVEw8FZUIXozHae5VgKvIDY5lgH/4Aph+h+nJNJpIr7jFZIFGy9LRLGCSwPudcFBdi4Mf4rLaKsNGCBxHDmrA== < content-length: 0 < date: Fri, 17 Nov 2023 14:14:03 GMT < alt-svc: h3=":443"; ma=86400 < * Connection #0 to host facebook.com left intact Can this be achieved?
3
0
482
Nov ’23
Connection between client and DriverKit
In a project, I'm using the DriverKit(and HIDDriverKit) framework. I have encountered a problem in the connection between the client app and the driver, which is implemented by the "IOKit" framework. By calling the function "IOServiceGetMatchingServices" the value of "iterator" returns correctly and then communication with the driver is done. However, after releasing the version on the TestFlight, on some systems, the value of the "iterator" returned 0 and it is not possible to communicate with the driver. I checked the status of the activated driver with the command "systemextensionsctl list" and there are no problems on the driver side and the values of "Enabled" and "Active" are starred. AppSandbox = True, SIP: enable ret = IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceNameMatching(dextIdentifier), &iterator); if (ret != kIOReturnSuccess) { goto fail; } while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) { ret = IOServiceOpen(service, mach_task_self(), 0, &connection); if(ret == kIOReturnSuccess) { break; } else { syslog(LOG_WARNING, "IDmelonLog LIB: Can't open service"); } IOObjectRelease(service); }
3
0
622
Nov ’23
Driver kit issue with OS 17.1
In my application, I have used DriverKit USB Transport - VendorID. Now whenever I am trying to install my application using driver kit development profile, it throws me error that profile is not valid. Now, If I try to install the app using Adhoc profile, then I am able to install it. Can you update us, is there any changes are there in 17.1 OS with development profile.
2
0
393
Nov ’23
Check from installing app if Full Disk Access has been enabled?
I have a macOS app that installs an endpoint system extension. After the user clicks "Allow" to allow it to be installed, the user must still scroll up to the "Full Disk Access" section and enable full disk access for the system extension. It is easy for the user to forget to do this. Is there an API (or other easy way) for the installing app to check whether the endpoint system extension has been granted full disk access? I would like to display some big message in the GUI saying "You must enable Full Disk Access" until they do.
1
0
577
Nov ’23
How to let the system take over a device after the DriverKit process exits?
I have created a USB filter using Mac DriverKit, but the filter is unable to retrieve configuration information during startup. After the USB filter has started and registered the service, my app can send the configuration information to the filter. Therefore, I would like to know if there is a way to exit the USB filter and allow the system to take control of the USB device once the filter has exited. I have tried calling Terminate(0), but it did not work as even after the USB filter exited, the Finder still couldn't display the USB device.
0
0
431
Nov ’23
Strange behavior of IOServiceNameMatching(..)
I'm trying to find extension by name with following code: static const char* dextIdentifier = "someDextName"; CFMutableDictionaryRef cfd = IOServiceNameMatching(dextIdentifier); int nMatch = (int)CFDictionaryGetCount(cfd); printf("nMatch=%d\n",nMatch); const void *keys[nMatch], *values[nMatch]; CFDictionaryGetKeysAndValues(cfd, keys, values); for(int e=0; e < nMatch; e++) { char key[100] = "", value[100] = ""; if(CFStringGetCString(reinterpret_cast<CFStringRef>(keys[e]), key, sizeof(key), kCFStringEncodingASCII)) { printf("Key: %s\n",key); } if(CFStringGetCString(reinterpret_cast<CFStringRef>(values[e]), value, sizeof(value), kCFStringEncodingASCII)) { printf("Value: %s\n",key); } } Regardless of dextIdentifier value IOServiceNameMatching always returns single record (nMatch = 1), where key = "IONameMatch" and value = It doesn't matter whether the specified extension name exists or not There is the single extension in the system, according to 'systemextensionsctl list' command
1
0
458
Nov ’23
Suspending USB Device
I'm working on a system management tool that should be able to Allow/Deny mass storage and portable devices. In case if it is a USB flash drive I can detect Mount events using Endpoint Security framework. Then using IOServiceGetMatchingServices I can find the actual device that is trying to mount new volume, check if it is an allowed device and Allow or Deny mount. But in case if it is an iPhone/iPad or Android device I can't rely on that solution as they don't mount new volumes but user can copy files to the phone. To cover this case I could respond with Deny for the ES_EVENT_TYPE_AUTH_IOKIT_OPEN event. But at that moment I know nothing about the device, only its class which is the same for a mouse and for iPhone. I can add a notification for adding new USB devices, but then I would need somehow to understand that it is a phone/tablet and disconnect or suspend needed USB Device. How could I disconnect or suspend a USB Device having only io_object_t?
6
0
809
Nov ’23
How does the driverkit serve as a bridge between hardware and the system?
I want to use DriverKit to develop a USBDriver, which serves as a bridge between USB devices and the system. All messages between USB devices and the system will be forwarded through the USBDriver. Can anyone give me some tips or suggestions? What API should I use? I couldn't find anything like this in the documentation or sample code. class MyUSBDriver: public IOUserClient { public: virtual bool init() override; virtual kern_return_t Start(IOService * provider) override; virtual kern_return_t Stop(IOService * provider) override; virtual void free() override; virtual kern_return_t GetRegistryEntryID(uint64_t * registryEntryID) override; virtual kern_return_t NewUserClient(uint32_t type, IOUserClient** userClient) override; virtual kern_return_t ExternalMethod(uint64_t selector, IOUserClientMethodArguments* arguments, const IOUserClientMethodDispatch* dispatch, OSObject* target, void* reference) override; }; I am now able to retrieve the device descriptor in the Start method IOUSBHostDevice *device = OSDynamicCast(IOUSBHostDevice, provider); if (device) { const IOUSBDeviceDescriptor *deviceDescriptor = device->CopyDeviceDescriptor(); if (deviceDescriptor) { uint16_t idVendor = deviceDescriptor->idVendor; uint16_t idProduct = deviceDescriptor->idProduct; uint8_t iSerialNumber = deviceDescriptor->iSerialNumber; IOUSBHostFreeDescriptor(deviceDescriptor); } }
0
0
429
Nov ’23
Missing API function in DriverKit for canceling timer event source
Hi, I'm working on a project that requires porting my KEXT driver to DriverKit system extension ( DEXT ). I've managed to re-write most of functions using DriverKit but I couldn't found a function for cancelling a scheduled timer. What I try to make is waiting for an interrupt with a timeout period. And if the interrupt arrives in certain time period I need to cancel timeout timer and send async response to the user app. I'm also open to the suggestions. Here is the code fragment for IOKit that I need to convert to DriverKit // ... initialization code fragment ( error handling parts deleted ) m_timeout_timer = IOTimerEventSource::timerEventSource(this, timer_fired_pc_recv); IOReturn result = m_workLoop->addEventSource(timer); // ... starting the timeout counter m_timeout_timer->setTimeoutMS(timeout_in_ms); // ... some time later (cancel part) m_timeout_timer->cancelTimeout(); And equivalent code in DriverKit // ... initialization code fragment ( error handling parts deleted ) ret = IOTimerDispatchSource::Create(ivars->default_dispatch_queue, &ivars->timer_dispatchSource); // starting timer timer_dispatchSource->WakeAtTime(kIOTimerClockMonotonicRaw, currentTime + fiveSecondsInNanoSeconds, twoSecondsInNanoSeconds); // missing part here I did see the member method Cancel in IOTimerDispatchSource but it is kind of termination to the lifetime of IOTimerDispatchSource
0
0
426
Oct ’23
Notarized Endpoint app, full disk access, Ventura Intel
I have an app that installs an endpoint system extension, and I have the app notarized. I can install the endpoint system extension and enable Full Disk Access fine on Ventura, Apple Silicon Sonoma, Apple Silicon But I cannot enable Full Disk Access on Ventura, Intel In System Settings, when I try to slide toggle switch on to enable full disk access, the toggle slides right back to off. In previous development versions, I could enable Full Disk Access on the Intel machine. Any idea why I cannot enable Full Disk Access on Ventura/Intel for my endpoint system extension in my notarized app? One additional observation, the name displayed in the Full Disk Access section is different between the Apple Silicon and Intel Macs. On Apple Silicon, only the final part of the Bundle ID is shown in Full Disk Access: endpointagent On Intel, the full Bundle ID is shown: com.MyCompany.MyApp.endpointagent Don't know if it matters, but I thought I'd point that out.
4
0
602
Oct ’23
Endpoint System Extension, full disk access, "allow"
I have an endpoint system extension that monitors exec system calls. It works fine, but I have to follow a very specific order when installing it. When I (the user) click to install, I get the option to open System Settings. There, I am presented with an option to "Allow" the endpoint application. If I: (1) click "Allow" and then (2) enable full disk access The application runs but doesn't get exec events. Console shows the error message Failed to open service: 0xe00002d8: Caller lacks TCC authorization for Full Disk Access Even after enabling full disk access (after allowing the extension to be installed), I do not get the exec events. To resolve this, I have to uninstall the endpoint system extension and reinstall it. (Note: If I first grant full disk access and then allow the endpoint system extension to be installed, everything works fine, but I suspect most users will now follow this happy path.) Is there a way to smooth this out, so that once full disk access is granted, the endpoint system extension gets events without needing to uninstall and reinstall the endpoint agent?
2
0
776
Oct ’23