I have verified that creating a new DriverKit project in Xcode 12.5, adding a single .cpp file, with a single #include , fails to build with the same errors.
This worked in previous Xcode versions (version 11, and version 12.4).
Post
Replies
Boosts
Views
Activity
This appears to have been fixed in a subsequent release of Big Sur.
Can you provide a pointer to documentation on how to package an application for the app store? I'm building the app bundle outside of Xcode because the installation application and driverkit extension are separate projects.
I can build either pkg or dmg for ad hoc distribution and get them notarized.
What difference in that for doing an App Store submission?
A diff between the .iig.cpp files generated by Xcode 11 and Xcode 12 show that there is a substantial change at the lines where the error is indicated from the build log:
				case Comm_TxAvailable_ID:
				 {						union {
								void (Comm::*fIn)(IODataQueueDispatchSource_DataAvailable_Args);
								IODataQueueDispatchSource::DataAvailable_Handler handler;
						} map;
						map.fIn = &Comm::TxAvailable_Impl;
						ret = IODataQueueDispatchSource::DataAvailable_Invoke(rpc, self, map.handler);
						ret = IODataQueueDispatchSource::DataAvailable_Invoke(rpc, self, SimpleMemberFunctionCast(IODataQueueDispatchSource::DataAvailable_Handler, *self, &Comm::TxAvailable_Impl), OSTypeID(OSAction_Comm_TxAvailable));
						 break;
				 }
The creation of the iig.cpp files is automatic. The base class iig file is unchanged. From my perspective the only change is Xcode 11 was automatically updated to Xcode 12 and I can no longer build or test.
I have verified the same behaviour on both my Catalina based development system and my Big Sur (on Intel) development system.
GetDataLength() has been deprecated, look at the DriverKit-20 API, you'll find getDataLength().
Unfortunately, Catalina does not (currently) support DriverKit-20, so you will need to compile with GetDataLength() for Catalina and getDataLength() for Big Sur.
I assume that it is a bug that Big Sur returns an error for GetDataLength() as it is marked as deprecated not removed in the documentation.
Disable SIP - System Integrity Protection.
My mistake, I thought SetInterfaceEnable() returned a boolean.
What I am seeing is kIOReturnUnsupported.
Is your log showing the result from SetInterfaceEnable(true), which is being called twice?
I am getting true returned twice if I do that.
One difference is that I am doing ReportLinkStatus(kIOUserNetworkLinkStatusActive,..) after the RegisterEthernetInterface() call and RegisterService() call. And then SetInterfaceEnable().
Is your GetMaxTransferUnit() succeeding? I get kioReturnUnsupported for that and SetMTU().
I have yet to see any sign of packets arriving from the network layer on the TxSubmissionQueue.
I can get an empty packet from the RxSubmissionQueue, but only using the DequeuePackets() function, DequeuePacket() always fails. Also the DequeuePackets() function fails the first time but later (second received transfer) it succeeds, and continues to work after than.
Finally found this in the documentation: https://developer.apple.com/documentation/driverkit/queuename?language=occ
With this example, where the relevant QUEUENAME(...) is only seen in the sample code window when you slide the bottom scrollbar over :-(
TxComplete (OSAction						*action,
						uint32_t						 ioCompletionIndex,
						uint32_t						 ioCompletionCount,
						const uint32_t			 actualByteCountArray[kIOUSBHostPipeBundlingMax],
						int									actualByteCountArrayCount,
						const kern_return_t	statusArray[kIOUSBHostPipeBundlingMax],
						int									statusArrayCount) TYPE(IOUSBHostPipe::CompleteAsyncIOBundled) QUEUENAME(tx_pipe_dq);
You need to call OSSystermExtensionRequest.activationRequest() multiple times. This code fragment looks for a Resources/driverlist.json file and then loads the driver extensions defined there.
func _activate(_ bundleIdentifier: String) {
				let request = OSSystemExtensionRequest.activationRequest(
						forExtensionWithIdentifier: bundleIdentifier,
						queue: .main
				)
				request.delegate = self
				OSSystemExtensionManager.shared.submitRequest(request)
		func activate( ) {
				let list = Bundle.main.decode("driverlist.json")
				for driver in list {
						_activate( driver.name)
				}	
		}	
Sample driverlist.json file:
[ { "name": "com.belcarra.driverkit" }]
Here is the logging from my code. It is successful in getting the interface registered. But so far I have not been able to push any data into the Rx queues or getting anything from the Tx queues.
[result = IOUserNetworkPacketBufferPool::Create(this, "usb_net_pool", 64, 64, 2048, &ivars->pool)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_tx_net_dq", 0, 0, &ivars->txSubmissionDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkTxSubmissionQueue::Create(ivars->pool, this, 16, 0, ivars->txSubmissionDispatchQueue, &ivars->txSubmissionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("tx_net_dq", ivars->txSubmissionDispatchQueue)] kIOReturnSuccess
[result = CreateActionTxAvailable(sizeof(void *), &ivars->txSubmitAction)] kIOReturnSuccess
[result = ivars->txSubmissionQueue->CopyDataQueue(&ivars->txDataQueueDispatchSource)] kIOReturnSuccess
[result = ivars->txDataQueueDispatchSource->SetDataAvailableHandler(ivars->txSubmitAction)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_tx_pipe_dq", 0, 0, &ivars->txCompleteDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkTxCompletionQueue::Create(ivars->pool, this, 16, 0, ivars->txCompleteDispatchQueue, &ivars->txCompletionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("tx_pipe_dq", ivars->txCompleteDispatchQueue)] kIOReturnSuccess
[result = CreateActionTxComplete(sizeof(void *), &ivars->txCompleteAction)] kIOReturnSuccess
[result = IOUserNetworkRxSubmissionQueue::Create(ivars->pool, this, 0x400, 0, 0, &ivars->rxSubmissionQueue)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_rx_pipe_dq", 0, 0, &ivars->rxCompleteDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkRxCompletionQueue::Create(ivars->pool, this, 16, 0, ivars->rxCompleteDispatchQueue, &ivars->rxCompletionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("rx_pipe_dq", ivars->rxCompleteDispatchQueue)] kIOReturnSuccess
[result = RegisterEthernetInterface(DataMacAddress, ivars->pool, ivars->queues, 4)] kIOReturnSuccess
[result = ReportAvailableMediaTypes(mediaTypes, 1)] kIOReturnSuccess
Possibly not quite best practice, but I use this script to remove the test app, cleanup the driver extension directory and reboot quickly. YMMV.
#!/bin/bash
set -x
rm -rf /Applications/USBApp.app
This appears to do the same as:
systemextensionsctl reset
echo 'ROOTPASSWDHERE' | sudo -S rm -rf /Library/DriverExtensions/* /Library/SystemExtensions/* /Library/SystemExtensions/.staging
echo 'ROOTPASSWDHERE' | sudo -S reboot
Thanks, I was hoping to avoid having to have a helper application running. That would of course work.
I don't believe we use any of the deprecated KPI's, this will be a simple NetworkingDriverkit Driver Extension.
Yes, we have review the USBApp example.
It is incomplete and even contains the comments:
// WWDC slides don't show the full function
// i.e. this is still unfinished.
The usb (and all driverkit) documentation contains little information other than the names of the functions and their arguements.
Apple previously released sample USB networking drivers in source that provided enough information to understand how to setup the I/O properly.
I have the configuration descriptor parsing working and had determined that the new strategy was as you outlined above.
The KEXT being ported used a similar strategy to implement a single virtual network interface that was shared by 1 to N physical devices. I.e. instead of N network interfaces being created.
The serviceMatching() was used by the data KEXT to find the virtual network KEXT.
I have been able to load both a virtual DEXT to and USB DEXT successfully. But need to determine how they can find each other and transfer data between them.