Temporarily disable macOS capture of USB RFID reader(s)

Hello.

I am attempting to wrap the C library libnfc as a Swift library. This is not for use on macOS - it's mainly for use on Linux (Raspberry Pi).

I have a USB reader and my code appears to work so far, however the code/test/debug cycle is suboptimal if I'm running the code on the Pi.

As I use a Mac for day-to-day coding, I'd prefer to use Xcode and my Mac for development. MacOS appears to capture the NFC hardware for its own frameworks and attempting to open a connection to the USB device gives a Unable to claim USB interface (Permission denied) error.

ioreg shows that the hardware is claimed by an Apple framework:

"UsbExclusiveOwner" = "pid 10946, com.apple.ifdbun"

Is there a way to temporarily over-ride that system and use the hardware myself? I've tried Googling but most of the replies are out of date and Claude's advice launchctl unload /System/Library/LaunchDaemons/com.apple.ifdreader.plist doesn't appear to work...

I'm wary of disabling SIP - is there a simple way to have access to the hardware myself?

Thanks.

Answered by DTS Engineer in 871995022

Is there a way to temporarily override that system and use the hardware myself? I've tried Googling, but most of the replies are out of date, and Claude's advice launchctl unload /System/Library/LaunchDaemons/com.apple.ifdreader.plist doesn't appear to work...

I haven't specifically tested this, but you should be able to disable this with launchctl. The "modern" commands for this would be:

Disable:
sudo launchctl disable system/com.apple.ifdreader
Enable:
sudo launchctl disable system/com.apple.ifdreader

You can also check the state of things by running this command:

sudo launchctl print system

Which will have output like this near the end of its output:

...
	disabled services = {
		...
		"com.apple.ifdreader" => disabled
	}
...

A few notes on this:

  • Disabling any service is inherently dangerous. Our services are designed to operate as relatively independent processes, so the system will probably continue to work, but disabling the "wrong" service can absolutely render your machine unusable. If you're going to mess with this stuff, you should plan for the possibility of catastrophic failure [1]. I don't know what this particular service does (to be honest, I haven't really looked) and don't plan on looking, as this is a case where you should use your own judgement and care.

  • I'd recommend ensuring that any service you're trying to disable is NOT running when you try and disable it. Strictly speaking, I think "launchctl" should terminate the service if it's running, but I don't recommend relying on that. There are a ton of edge cases, and it's very easy to end up wasting time thinking it "didn't work" when what actually happened was "it did work, but the service ended up continuing to run because <insert confusing edge case you probably didn't care about>".

Finally, I will note that this is just one approach among many. For example, a codeless DEXT can be used from the "opposite" direction, by modifying the hardware's IOKit "appearance" such that this it's not longer recognized by the target service. I outlined the launchctl because it's the easiest approach for a "one off" case when you don't care about the component that would normally run. That doesn't mean it's the best approach for all cases.

[1] For ~25 years, (when I started doing KEXT development on OS X), all of my machines have always had (at least) two admin users— my primary account ("kevine") and a second admin account ("despair") that I basically "never" log into. The ONLY reason that second account exists is to allow me to easily access the account if/when something goes so badly wrong that my primary account is no longer functional. I've only used that second account a handful of times, but it's been REALLY handy when I needed it.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

Is there a way to temporarily override that system and use the hardware myself? I've tried Googling, but most of the replies are out of date, and Claude's advice launchctl unload /System/Library/LaunchDaemons/com.apple.ifdreader.plist doesn't appear to work...

I haven't specifically tested this, but you should be able to disable this with launchctl. The "modern" commands for this would be:

Disable:
sudo launchctl disable system/com.apple.ifdreader
Enable:
sudo launchctl disable system/com.apple.ifdreader

You can also check the state of things by running this command:

sudo launchctl print system

Which will have output like this near the end of its output:

...
	disabled services = {
		...
		"com.apple.ifdreader" => disabled
	}
...

A few notes on this:

  • Disabling any service is inherently dangerous. Our services are designed to operate as relatively independent processes, so the system will probably continue to work, but disabling the "wrong" service can absolutely render your machine unusable. If you're going to mess with this stuff, you should plan for the possibility of catastrophic failure [1]. I don't know what this particular service does (to be honest, I haven't really looked) and don't plan on looking, as this is a case where you should use your own judgement and care.

  • I'd recommend ensuring that any service you're trying to disable is NOT running when you try and disable it. Strictly speaking, I think "launchctl" should terminate the service if it's running, but I don't recommend relying on that. There are a ton of edge cases, and it's very easy to end up wasting time thinking it "didn't work" when what actually happened was "it did work, but the service ended up continuing to run because <insert confusing edge case you probably didn't care about>".

Finally, I will note that this is just one approach among many. For example, a codeless DEXT can be used from the "opposite" direction, by modifying the hardware's IOKit "appearance" such that this it's not longer recognized by the target service. I outlined the launchctl because it's the easiest approach for a "one off" case when you don't care about the component that would normally run. That doesn't mean it's the best approach for all cases.

[1] For ~25 years, (when I started doing KEXT development on OS X), all of my machines have always had (at least) two admin users— my primary account ("kevine") and a second admin account ("despair") that I basically "never" log into. The ONLY reason that second account exists is to allow me to easily access the account if/when something goes so badly wrong that my primary account is no longer functional. I've only used that second account a handful of times, but it's been REALLY handy when I needed it.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks Kevin.

'despair' is a particularly good name for that account...

Temporarily disable macOS capture of USB RFID reader(s)
 
 
Q