Nfcd

From iPhone Development Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

nfcd is a daemon running under the mobile user. It handles the communications between PassKit and the underlying hardware and libraries.

Core objects

  • NFDaemon
  • NFFieldDetectController
  • NFCoreTelephonyConnection
  • NFPowerManager
  • NFAbstractController
  • NFCardEmulationController
  • NFSecureElementController

Launchd plist

{
    EnablePressuredExit = 1;
    EnableTransactions = 1;
    ExitTimeOut = 45;
    Label = "com.apple.nfcd";
    MachServices =     {
        "com.apple.nfcd" = 1;
    };
    ProcessType = Interactive;
    Program = "/usr/libexec/nfcd";
    UserName = mobile;
}

Where the XPC service is registered under the "com.apple.nfcd" name

Supported XPC Commands

ID Command
1 q_registerConnection:info:
2 q_unregisterConnection:
3-64 send command to SE controller
65 q_updateSecureElementPowerState
66 _seIsInRestrictedMode
67 restrictedModeChanged
68-239 callSEContoller
240 setDeviceString
241 q_getControllerInfo
242 q_getSecureElementInfo
243 q_getBoosterInfo
244 q_readBoosterRegister
245 q_sendBoosterCommand
246 q_triggerAssertion
>247 throw error

Sending XPC Commands

Four XPC keys are sent for the XPC command:

  • NFMsgObject - dictionary containing values to sent to receiving objects
  • NFMsgType - uint64, sending is a 0, receiving a 1
  • NFMsgCode - uint64, "command" as described above
  • NFMsgId - uint64, undetermined

Example of XPC command to the nfcd:

#include <xpc/xpc.h>

int main(int argc, char **argv, char **envp) {
	// Create connection to mach service
	xpc_connection_t connection = xpc_connection_create_mach_service("com.apple.nfcd", NULL, 0);
	xpc_connection_set_event_handler(connection, ^(xpc_object_t object) {
		char *description = xpc_copy_description(object);
		printf("Sending object: %s\n", description);
		free(description);
	});
	xpc_connection_resume(connection);

	while (true) {
		// Send message to mach service, and wait for a response
		xpc_object_t msgobject = xpc_dictionary_create(NULL,NULL,0); 
		xpc_object_t object = xpc_dictionary_create(NULL, NULL, 0);
		xpc_dictionary_set_int64(msgobject, "Controller", 6);
		xpc_dictionary_set_value(object, "NFMsgObject", msgobject);
		xpc_dictionary_set_uint64(object, "NFMsgType", 0x00); 
		xpc_dictionary_set_uint64(object, "NFMsgCode", 0x01); 
		xpc_dictionary_set_uint64(object, "NFMsgId", 17);

		char *description = xpc_copy_description(object);
		printf("Sending object: %s\n", description);
		free(description);

		xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, object);
		description = xpc_copy_description(object);
		printf("Received reply object: %s\n\n", description);
		free(description);
		sleep(1);
	}

	return 0;
}

see https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/xpc_dictionary_set_uint64.3.html

NFDaemon methods

Signature -(void)XPCConnection:(id)connection didReceiveCommand:(id)command;
Available in 8.0 - 9.0.1
Signature -(int)q_registerConnection:(id)connection info:(id)info;
Available in 8.0 - 9.0.1

This function checks for an existing controller

  • [NFCardEmulationController embeddedCardEmulationController]
  • [NFCardEmulationController UICCCardEmulationController]
  • [NFSecureElementController seController]
  • [NFFieldDetectController fieldDetectController]

When it finds the appropriate controller it calls the unregister function for it.

Signature -(unsigned int)q_unregisterConnection:(id)connection;
Available in 8.0 - 9.0.1