Post not yet marked as solved
We are experimenting with DriverKit on macOS while DriverKit is still in beta on iPadOS. We want to build a Driver for iPad that will allow to communicate our iPad App with USB device.
What we did:
Configured and implemented a driver that uses USBDriverKit::IOUSBHostInterface as provider. This driver is automatically matched/started by macOS when we plug our device into USB port. Next we utilised USBDriverKit::IOUSBHostPipe to send/receive data from our device. We print data from device in logs for now.
Studied Communicating Between a DriverKit Extension and a Client App
Configured and implemented a driver that based on IOUserClient and allows to open communication channel by macOs App using IOServiceOpen API. Driver has callback to pass data to macOS Client App.
Currently we want to combine 2 drivers and pass data received from USB device to our client App using callback. Unfortunately, we stuck since now we have 2 instances of driver:
First instance is automatically run by macOS when device is plugged
Second instance is created when we are connecting from Client App and virtual kern_return_t NewUserClient(uint32_t type, IOUserClient** userClient) method is called.
So we can't use second instance to do USB device communication since it has wrong provider(IOUserClient) in kern_return_t Start(IOService * provider) but we need IOUSBHostInterface to start:
ivars->interface = OSDynamicCast(IOUSBHostInterface, provider);
if(ivars->interface == NULL) {
ret = kIOReturnNoDevice;
goto Exit;
}
Are we doing it wrong? Maybe instead of automatic matching for IOUSBHostInterface we should do it manually from UserClient driver or use another approach?
As we learned we have to create a new service instance in NewUserClient method and can't return driver that was run by OS:
kern_return_t IMPL(MyDriver, NewUserClient)
{
kern_return_t ret = kIOReturnSuccess;
IOService* client = nullptr;
ret = Create(this, "UserClientProperties", &client);
if (ret != kIOReturnSuccess)
{
goto Exit;
}
*userClient = OSDynamicCast(IOUserClient, client);
if (*userClient == NULL)
{
client->release();
ret = kIOReturnError;
goto Exit;
}
Exit:
return ret;
}
BTW, maybe there is much easier way to forward data from USB device to iPadOS App?
Post not yet marked as solved
I am working on a DriverKit system extension that handles some kind of USB Ethernet adapter.
I'm trying to receive data from a Bulk endpoint. Each USB transfer should be up to 512kB, but the actual size of the transfer is not known in advance.
What I do is the following:
Allocate an IOBufferMemoryDescriptor with IOUSBHostInterface::CreateIOBuffer:
ret = ivars->interface->CreateIOBuffer(kIOMemoryDirectionIn, 524288, &b->buffer);
Create an OSAction to be used as transfer complete callback:
ret = CreateActionReadComplete(0, &b->action);
Start the I/O request:
ret = ivars->pipe->AsyncIO(b->buffer, 524288, b->action, 0);
At that point, I see that instead of starting a single 524288 bytes transfer, it starts 14 36864 bytes transfers and a 8192 bytes one. Which will absolutely not work with the USB device.
Is there a transfer size limit I am not aware of?
Post not yet marked as solved
We followed WWDC Session: System Extensions and DriverKit and recreated a code to do USB device communication via IOUSBHostPipe:
struct MyDriver_IVars {
IOUSBHostInterface *interface;
IOUSBHostPipe *inPipe;
OSAction *ioCompleteCallback;
IOBufferMemoryDescriptor *inData;
uint16_t maxPacketSize;
};
kern_return_t
IMPL(MyDriver, Start)
{
...
ivars->maxPacketSize = 64;
ret = ivars->interface->CreateIOBuffer(
kIOMemoryDirectionInOut,
ivars->maxPacketSize,
&ivars->inData);
ret = CreateActionReadComplete(0, &ivars->ioCompleteCallback);
ret = ivars->inPipe->AsyncIO(ivars->inData,
ivars->maxPacketSize,
ivars->ioCompleteCallback,
0);
...
}
Our Driver is started by OS when device is connected. We see that ReadComplete callback is called:
void IMPL(MyDriver, ReadComplete)
{
Log("ReadComplete() - status - %d; bytes count - %d", status, actualByteCount);
}
However it's not obvious how to read data received in this callback. I suspect that we should use IOBufferMemoryDescriptor *inData but we didn't find any good example/sample and documentation is poor.
Our callback is called only once. It's not clear how to read a series of data from device? Should we create some loop and call inPipe->AsyncIO from callback?
Also it would be helpful to see how to pass data to device. I hope we should fill IOBufferMemoryDescriptor *inData.
Post not yet marked as solved
Earlier this week, I requested a DriverKit entitlement (#801892899). Just wanted to see if there was an expected ETA on such requests.
Thank you,
Neal
Post not yet marked as solved
We requested com.apple.developer.driverkit.transport.usb entitlement a few days ago and it looks like it was granted since we see(can select) it at:
App Id -> Additional Capabilities Tab -> DriverKit USB Transport - Vendor ID.
We tried to choose both options at Additional Entitlements page
Default and Driver Kit and System Extension Template for **** Mac Dev. Generated profile displays DriverKit USB Transport - Vendor ID in Enabled Capabilities in browser. However downloaded profile doesn't include com.apple.developer.driverkit.transport.usb. As a result our Driver fails to start and in Console we see:
Driver: Unsatisfied entitlements: com.apple.developer.driverkit.transport.usb
/Library/SystemExtensions/675FA894-8985-4D86-B0FF-B892B9AEA27B/Driver.dext/Driver signature not valid: -67671
BTW, we tried to modify existing profile and create a new one.
Did we miss something? Is any way to check entitlement status with Apple support?
Post not yet marked as solved
I understand that a
Company’s hardware vendor ID
is required for requesting Entitlements for DriverKit. Does this means DriverKit is only targeted for hardware vendors?
Does Apple allows third party (not the hardware vendor) entitlements for DriverKit? Our company is exploring the development of generic open source drivers on iPad for label printers such as those by Zebra. Is this allowed?
Post not yet marked as solved
I watched the session multiple times, but it just gives a high level overview that doesn't really say much about this very exciting and complex new feature. It only mentions actually talking to the driver in passing with a single sentence "apps use the IOKit framework to open user clients". Then the presenter says for an example of that we can check out "communicating between a driverkit extension and a client app", which is a macOS app that doesn't even use IOKit, and trying to import IOKit into an iPadOS target doesn't work anyway because the framework is not there.
Am I missing something, or is this simply not available in Xcode 14 seed 1? Release notes don't mention anything either, and docs are only updated to reflect that some of this stuff is now available on iPadOS 16...
Post not yet marked as solved
I have a requirement where I need to monitor writes/reads from arbitrary USB devices. Can I do it with USBDriverKit?
Post not yet marked as solved
Hi,
I need to develop a cross-plateform driver extension (similar to a Windows Audio Processing Object (APO)) for an Audio Device and I'm struggling with associating the driver to a USB Audio Device.
I'm using the SimpleAudioDriver example and override the device_uid with the Product ID and the manufacturer_uid with the Vendor ID.
As I understand it with this documentation :
https://developer.apple.com/news/?id=zk5xdwbn
it should associate my driver with the device but it creates a new device.
If you have any hints, please get back to me.
Thanks.
Post not yet marked as solved
When connecting the USB type C ver3.1 display port output of a laptop to the lightning interface of an iPhone, how could I use the SW API on the iPhone to capture the image output of the laptop screen?
Post not yet marked as solved
Hi folks,
I'm developing a real-time audio engine that runs on macOS but has also an iPad version that enables control of the macOS app using a touch screen.
I want to share control data between the iPad app and the macOS app without using Wi-Fi. As a real-time thing, it would be great to be able to use a thunderbolt cable.
Is there a way of doing it? Where can I find more info?
Thanks for your time.
Post not yet marked as solved
How hard would it be to use a Catalina driver for an audio interface to create a driver for Monterey or Big Sur? Tascam discontinued updates for my two interfaces (same models, used as aggregate device)
Post not yet marked as solved
audio port not working on Lenovo docking station. Sound setting only options is "Lenovo-usb-audio". And this is not working.
Post not yet marked as solved
I get the following errors when running the code below in a sandboxed app (it works when not sandboxed) and I have the com.apple.security.device.usb entitlement enabled.
Error:Unable to open io_service_t object and create user client. with reason: IOServiceOpen failed.
Error Domain=IOUSBHostErrorDomain Code=-536870174 "Failed to create IOUSBHostObject." UserInfo={NSLocalizedRecoverySuggestion=, NSLocalizedDescription=Failed to create IOUSBHostObject., NSLocalizedFailureReason=IOServiceOpen failed.}
import Foundation
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
import IOKit.serial
import IOUSBHost
import IOUSBHost.IOUSBHostInterface
class USBService {
enum UsbError: Error {
case noDeviceMatched
case deviceCriteriaNotUnique
}
init() {
}
func getDevice(idVendor: Int?, idProduct: Int?) throws {
let deviceSearchPattern: [IOUSBHostMatchingPropertyKey : Int] = [
.vendorID : idVendor!,
.productID : idProduct!,
]
let deviceDomain = [ "IOProviderClass": "IOUSBHostDevice" ]
let searchRequest = (deviceSearchPattern as NSDictionary).mutableCopy() as! NSMutableDictionary
searchRequest.addEntries(from: deviceDomain)
let service = IOServiceGetMatchingService(kIOMasterPortDefault, searchRequest)
guard service != 0 else {
throw UsbError.noDeviceMatched
}
let device = try IOUSBHostDevice.init(__ioService: service, options: [], queue: nil, interestHandler: nil)
print(device.deviceDescriptor?.pointee.idProduct)
}
}
Post not yet marked as solved
I have purchased the USB C hub by gravity and it has the ethernet port which is not appearing in my network settings. I have tried to see if it could be added but cant find anything. I have heard people talk about drivers but not sure what drivers or even if i need them. They dont say anything on the gravity website. Can anyone help?
Post not yet marked as solved
Hello
We have a USB camera. My Mac can recognize it and we can get frames with any software. There is a physical button on it and the vendor says the camera is UVC-compliant. But button doesn't work anyway.
I captured some USB traffic data and saw that it has two interfaces. One for streaming and other one for interrupting (like button click). I read UVC 1.5 standards to understand it and it is working like written in UVC 1.5. So, I can get a data with an interrupt transfer when clicking the button.
I checked these two interfaces, they use UVCAssistant for driver(System Extension). I tried to use libusb, I can get data from button click. But for frames I had to use libuvc, but it wasn't work for my camera (I think it is related with USB descriptor parsing in libuvc).
I thought that I should write a driver for single interface and so second interface will use same UVC assistant driver and first interface will use my driver.
I wrote a driver and it matches with first interface. But second interface is empty (unhandled by any driver). I want to load UVCAssistant for second interface of USB port.
How can I do this?
Output before loading my driver
After loading:
IOKitPersonalities that I used:
Post not yet marked as solved
Hey,
We are developing a dext that would like to match with all USB devices, no matter the vendor. We use VendorID = * in the plist of the Dext to help achieve this when running it locally without entitlements.
I know that the transport.usb entitlement requires a list of Vendor id's, but is it possible to receive an entitlement which is suitable for all VID's?
Kind of like this:
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<string>*</string>
</dict>
</array>
Thanks
Post not yet marked as solved
I requested “USB transport " and "userclient-access" entitlements to Apple and they has approved. Apple team said I should create entitlement file and "transport.usb" entitlement should contain Vendor ID. I created also AppID and Provisionig profiles. After that, I build the Xcode project and the application doesn't work.
I have two questions.
Provisioning profile contains transport.usb entitlement "without" Vendor ID. Should it contain Vendor ID too?
When I create AppID, I can choose "Additional Capabilities", but I can not find "userclient-access". How can I set the entitlement?
Post not yet marked as solved
Dear All,
I have looked for on this forum an answer to this question : it seems complicated and also depend of the MAC OS version.
In fact, my team has developed an USB device.
This device works on Windows OS. We have sold the product, it works on different OS versions (7, 10 and 11)
This device works also on raspberry PI (linux core).
Into these both OS, the product is detected like a serial port : I can use basic application of check that my product is perfectly functional.
Now I want use it on MAC OS, my device appears into the list of USB components connected to my MAC.
However I'm not able to indicate (or force) the serial port.
I read lot of things, kext? ,,, could depend of MAC version however I cannot found a clear process to help me to install a virtual COM on my MAC OS.
Do you have link to other forum (more hardware may be)?
Do you have any technical documentation about this topic?
regards,
fu154
Post not yet marked as solved
I have noticed that although System Report shows 2 USB 3.1 busses on the USB device tree only one of the busses is used whenever a device is plugged in to one of the ports. Is the other bus reserved for internal use or is it possible to have it used by an external device?