I have a driver project where I'm opening and closing a connection to a custom driver.
If I do what I think I need to be doing to unmap the memory, when I try to open the service again, it fails. If I skip the step where I do that unmapping, the service opens successfully.
If I call unmap() before trying to call openConnection() again, it will fail with a -308 error return code. If I skip that call to unmap(), it works and I'm able to communicate with my device.
Here's the code where I open the service:
public func openConnection() throws {
guard !isOpen else { return }
// Open device
var connection: io_connect_t = IO_OBJECT_NULL
var result = IOServiceOpen(device, mach_task_self_, 0, &connection)
if result != kIOReturnSuccess {
NSLog("Failed opening device with error: 0x%08x.\n", result);
throw NSError.cdc_kernelReturnErrorWithError(result)
}
defer { IOConnectRelease(connection) }
if device == IO_OBJECT_NULL || connection == IO_OBJECT_NULL {
throw NSError.cdc_kernelReturnErrorWithError(result)
}
let receiveDataMappedMemory = ClientDriverMappedMemory(connection: connection, memoryType: MappedMemoryType_ReceiveDataBuffer)
try receiveDataMappedMemory.map()
let transmitDataMappedMemory = ClientDriverMappedMemory(connection: connection, memoryType: MappedMemoryType_TransmitDataBuffer)
try transmitDataMappedMemory.map()
// Setup async notification
IONotificationPortSetDispatchQueue(dataReceivedPort, dataReceivedQueue)
let callbackPort = IONotificationPortGetMachPort(dataReceivedPort)
let input = DataStruct(foo: 0, bar: 0)
var output = DataStruct(foo: 0, bar: 0)
var outputSize = MemoryLayout<DataStruct>.size
// Trampoline to C function because I don't quite know how to make this work in Swift
result = setupCallback(self, connection, callbackPort, input, &output, &outputSize)
if result != kIOReturnSuccess {
NSLog("Error registering async callback with driver: \(result)");
throw NSError.cdc_kernelReturnErrorWithError(result)
}
self.connection = connection
self.receivedDataMappedMemory = receiveDataMappedMemory
self.transmitDataMappedMemory = transmitDataMappedMemory
}
map() and unmap() functions:
- (BOOL)mapWithError:(NSError **)error
{
error = error ?: &(NSError * __autoreleasing){ nil };
kern_return_t result = IOConnectMapMemory64(self.connection,
self.memoryType,
mach_task_self(),
&_address,
&_size,
kIOMapAnywhere);
if (result != kIOReturnSuccess) {
*error = [NSError cdc_kernelReturnErrorWithError:result];
return NO;
}
self.mapped = YES;
return YES;
}
- (BOOL)unmapWithError:(NSError **)error
{
error = error ?: &(NSError * __autoreleasing){ nil };
kern_return_t result = IOConnectUnmapMemory64(self.connection,
self.memoryType,
mach_task_self(),
_address);
if (result != kIOReturnSuccess) {
*error = [NSError cdc_kernelReturnErrorWithError:result];
return NO;
}
self.mapped = NO;
return YES;
}
Any insights? What all should I be doing to close the service? Why would the unmapping create this issue or what else could the -308 error be indicated has gone wrong?