Nfcd

From iPhone Development Wiki
Revision as of 12:37, 29 September 2015 by Peterfillmore (talk | contribs)

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

The core objects in it are:

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

NFDaemon - (void)XPCConnection:(id) didReceiveCommand:(id)

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 send 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, no idea at the moment

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 some_object) { });
    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); 
	printf("Sending object: %s\n", xpc_copy_description(object));
        xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, object);
        printf("Received reply object: %s\n\n", xpc_copy_description(reply));
        sleep(1);
    }

    return 0;
}

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

NFDaemon - (int)q_registerConnection:(XPCConnection) info:()

NFDaemon - (unsigned int)q_unregisterConnection:(XPCConnection)

This functions checks for an existing controller for the

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

Then when it finds the appropriate controller then calls the unregister function for it.