2 * Copyright (C) 2012 Jolla Ltd.
3 * Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
25 #include <hardware/hardware.h>
26 #include <hardware/nfc.h>
27 #include <libnfc-nxp/phLibNfc.h>
28 #include <libnfc-nxp/phDal4Nfc_messageQueueLib.h>
30 static int messageThreadRunning
= 0;
31 static int numberOfDiscoveredTargets
= 0;
32 static phLibNfc_RemoteDevList_t
*discoveredTargets
= 0;
33 static NFCSTATUS targetStatus
= 0xFFFF;
34 static phLibNfc_sRemoteDevInformation_t
*connectedRemoteDevInfo
= 0;
35 static phLibNfc_ChkNdef_Info_t ndefInfo
;
36 static pthread_mutex_t mut
= PTHREAD_MUTEX_INITIALIZER
;
37 static pthread_cond_t cond
= PTHREAD_COND_INITIALIZER
;
39 static void *messageThreadFunc(void *arg
)
41 int *clientId
= (int *)arg
;
42 messageThreadRunning
= 1;
43 while (messageThreadRunning
) {
44 phDal4Nfc_Message_Wrapper_t message
;
45 int ret
= phDal4Nfc_msgrcv(*clientId
, &message
,
46 sizeof(phLibNfc_Message_t
), 0, 0);
48 fprintf(stderr
, "Failed to receive message from NFC stack.\n");
52 switch (message
.msg
.eMsgType
) {
53 case PH_LIBNFC_DEFERREDCALL_MSG
: {
54 phLibNfc_DeferredCall_t
*msg
= (phLibNfc_DeferredCall_t
*)message
.msg
.pMsgData
;
56 msg
->pCallback(msg
->pParameter
);
60 fprintf(stderr
, "Unknown message type %d.", message
.msg
.eMsgType
);
63 pthread_cond_signal(&cond
);
69 static pthread_t
createMessageThread(void *arg
)
72 int error
= pthread_create(&thread_id
, NULL
, messageThreadFunc
, arg
);
79 static void terminateMessageThread(int clientId
)
81 messageThreadRunning
= 0;
83 phDal4Nfc_Message_Wrapper_t message
;
84 phLibNfc_DeferredCall_t
*msg
;
86 msg
= (phLibNfc_DeferredCall_t
*)malloc(sizeof(phLibNfc_DeferredCall_t
));
89 message
.msg
.eMsgType
= PH_LIBNFC_DEFERREDCALL_MSG
;
90 message
.msg
.pMsgData
= msg
;
91 message
.msg
.Size
= sizeof(phLibNfc_DeferredCall_t
);
93 phDal4Nfc_msgsnd(clientId
, &message
, sizeof(phLibNfc_Message_t
), 0);
96 void initializeCallback(void *pContext
, NFCSTATUS status
)
98 NFCSTATUS
*callbackStatus
= (NFCSTATUS
*)pContext
;
99 *callbackStatus
= status
;
102 void discoveryNotificationCallback(void *pContext
, phLibNfc_RemoteDevList_t
*psRemoteDevList
,
103 uint8_t uNofRemoteDev
, NFCSTATUS status
)
105 if (status
== NFCSTATUS_DESELECTED
) {
106 fprintf(stderr
, "Target deselected\n");
108 fprintf(stderr
, "Discovered %d targets\n", uNofRemoteDev
);
111 for (i
= 0; i
< uNofRemoteDev
; ++i
) {
112 fprintf(stderr
, "Target[%d]\n\tType: %d\n\tSession: %d\n", i
,
113 psRemoteDevList
[i
].psRemoteDevInfo
->RemDevType
,
114 psRemoteDevList
[i
].psRemoteDevInfo
->SessionOpened
);
116 numberOfDiscoveredTargets
= uNofRemoteDev
;
117 discoveredTargets
= psRemoteDevList
;
118 targetStatus
= status
;
122 void discoveryCallback(void *pContext
, NFCSTATUS status
)
124 fprintf(stderr
, "discoveryCallback %d\n", status
);
127 void remoteDevConnectCallback(void *pContext
, phLibNfc_Handle hRemoteDev
,
128 phLibNfc_sRemoteDevInformation_t
*psRemoteDevInfo
, NFCSTATUS status
)
130 targetStatus
= status
;
131 connectedRemoteDevInfo
= psRemoteDevInfo
;
134 void remoteDevNdefReadCheckCallback(void *pContext
, phLibNfc_ChkNdef_Info_t Ndef_Info
,
137 ndefInfo
= Ndef_Info
;
138 targetStatus
= status
;
141 void remoteDevNdefReadCallback(void *pContext
, NFCSTATUS status
)
143 targetStatus
= status
;
146 void testNfc(int readNdefMessages
)
148 printf("Starting test_nfc.\n");
150 const hw_module_t
*hwModule
= 0;
151 nfc_pn544_device_t
*nfcDevice
= 0;
153 printf("Finding NFC hardware module.\n");
154 hw_get_module(NFC_HARDWARE_MODULE_ID
, &hwModule
);
155 assert(hwModule
!= NULL
);
157 printf("Opening NFC device.\n");
158 assert(nfc_pn544_open(hwModule
, &nfcDevice
) == 0);
159 assert(nfcDevice
!= 0);
161 assert(nfcDevice
->num_eeprom_settings
!= 0);
162 assert(nfcDevice
->eeprom_settings
);
164 printf("Configuring NFC driver.\n");
165 phLibNfc_sConfig_t driverConfig
;
166 driverConfig
.nClientId
= phDal4Nfc_msgget(0, 0600);
167 assert(driverConfig
.nClientId
);
170 NFCSTATUS status
= phLibNfc_Mgt_ConfigureDriver(&driverConfig
, &hwRef
);
172 assert(status
== NFCSTATUS_SUCCESS
);
174 pthread_t messageThread
= createMessageThread(&driverConfig
.nClientId
);
176 printf("Initializing NFC stack.\n");
177 NFCSTATUS callbackStatus
= 0xFFFF;
178 status
= phLibNfc_Mgt_Initialize(hwRef
, initializeCallback
, &callbackStatus
);
179 assert(status
== NFCSTATUS_PENDING
);
181 pthread_mutex_lock(&mut
);
182 while (callbackStatus
== 0xFFFF)
183 pthread_cond_wait(&cond
, &mut
);
184 pthread_mutex_unlock(&mut
);
186 assert(callbackStatus
== NFCSTATUS_SUCCESS
);
188 printf("Getting NFC stack capabilities.\n");
189 phLibNfc_StackCapabilities_t capabilities
;
190 status
= phLibNfc_Mgt_GetstackCapabilities(&capabilities
, &callbackStatus
);
191 assert(status
== NFCSTATUS_SUCCESS
);
193 printf("NFC capabilities:\n"
194 "\tHAL version: %u\n"
198 "\tHCI version: %u\n"
200 "\tFull version: %u %u\n"
202 capabilities
.psDevCapabilities
.hal_version
, capabilities
.psDevCapabilities
.fw_version
,
203 capabilities
.psDevCapabilities
.hw_version
, capabilities
.psDevCapabilities
.model_id
,
204 capabilities
.psDevCapabilities
.hci_version
,
205 capabilities
.psDevCapabilities
.vendor_name
,
206 capabilities
.psDevCapabilities
.full_version
[NXP_FULL_VERSION_LEN
-1],
207 capabilities
.psDevCapabilities
.full_version
[NXP_FULL_VERSION_LEN
-2],
208 capabilities
.psDevCapabilities
.firmware_update_info
);
210 if (readNdefMessages
) {
211 /* Start tag discovery */
212 phLibNfc_Registry_Info_t registryInfo
;
214 registryInfo
.MifareUL
= 1;
215 registryInfo
.MifareStd
= 1;
216 registryInfo
.ISO14443_4A
= 1;
217 registryInfo
.ISO14443_4B
= 1;
218 registryInfo
.Jewel
= 1;
219 registryInfo
.Felica
= 1;
220 registryInfo
.NFC
= 1;
221 registryInfo
.ISO15693
= 1;
224 status
= phLibNfc_RemoteDev_NtfRegister(®istryInfo
, discoveryNotificationCallback
, &context
);
225 assert(status
== NFCSTATUS_SUCCESS
);
227 phLibNfc_sADD_Cfg_t discoveryConfig
;
228 discoveryConfig
.NfcIP_Mode
= phNfc_eP2P_ALL
;
229 discoveryConfig
.NfcIP_Target_Mode
= 0x0E;
230 discoveryConfig
.Duration
= 300000;
231 discoveryConfig
.NfcIP_Tgt_Disable
= 0;
232 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableIso14443A
= 1;
233 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableIso14443B
= 1;
234 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableFelica212
= 1;
235 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableFelica424
= 1;
236 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableIso15693
= 1;
237 discoveryConfig
.PollDevInfo
.PollCfgInfo
.EnableNfcActive
= 1;
238 discoveryConfig
.PollDevInfo
.PollCfgInfo
.DisableCardEmulation
= 1;
240 targetStatus
= 0xFFFF;
241 status
= phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_CONFIG
, discoveryConfig
,
242 discoveryCallback
, &context
);
245 pthread_mutex_lock(&mut
);
246 while (targetStatus
== 0xFFFF)
247 pthread_cond_wait(&cond
, &mut
);
248 pthread_mutex_unlock(&mut
);
250 fprintf(stderr
, "Discovered %d targets\n", numberOfDiscoveredTargets
);
251 if (numberOfDiscoveredTargets
> 0) {
252 targetStatus
= 0xFFFF;
253 status
= phLibNfc_RemoteDev_Connect(discoveredTargets
[0].hTargetDev
,
254 remoteDevConnectCallback
, &context
);
255 if (status
== NFCSTATUS_PENDING
) {
256 pthread_mutex_lock(&mut
);
257 while (targetStatus
== 0xFFFF)
258 pthread_cond_wait(&cond
, &mut
);
259 pthread_mutex_unlock(&mut
);
261 if (targetStatus
== NFCSTATUS_SUCCESS
) {
262 targetStatus
= 0xFFFF;
263 status
= phLibNfc_Ndef_CheckNdef(discoveredTargets
[0].hTargetDev
,
264 remoteDevNdefReadCheckCallback
, &context
);
266 pthread_mutex_lock(&mut
);
267 while (targetStatus
== 0xFFFF)
268 pthread_cond_wait(&cond
, &mut
);
269 pthread_mutex_unlock(&mut
);
271 if (targetStatus
== NFCSTATUS_SUCCESS
&&
272 (ndefInfo
.NdefCardState
== PHLIBNFC_NDEF_CARD_READ_WRITE
||
273 ndefInfo
.NdefCardState
== PHLIBNFC_NDEF_CARD_READ_ONLY
)) {
274 phLibNfc_Data_t ndefBuffer
;
275 ndefBuffer
.length
= ndefInfo
.MaxNdefMsgLength
;
276 ndefBuffer
.buffer
= malloc(ndefBuffer
.length
);
278 targetStatus
= 0xFFFF;
279 status
= phLibNfc_Ndef_Read(discoveredTargets
[0].hTargetDev
, &ndefBuffer
,
280 phLibNfc_Ndef_EBegin
, remoteDevNdefReadCallback
, &context
);
282 pthread_mutex_lock(&mut
);
283 while (targetStatus
== 0xFFFF)
284 pthread_cond_wait(&cond
, &mut
);
285 pthread_mutex_unlock(&mut
);
287 if (targetStatus
== NFCSTATUS_SUCCESS
) {
289 fprintf(stderr
, "NDEF: ");
290 for (i
= 0; i
< ndefBuffer
.length
; ++i
)
291 fprintf(stderr
, "%02x", ndefBuffer
.buffer
[i
]);
292 fprintf(stderr
, "\n");
295 free(ndefBuffer
.buffer
);
301 if (status
== NFCSTATUS_FAILED
) {
302 fprintf(stderr
, "Failed to connect to remote device\n");
306 targetStatus
= 0xFFFF;
307 status
= phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_RESUME
, discoveryConfig
,
308 discoveryCallback
, &context
);
309 assert(status
== NFCSTATUS_SUCCESS
|| status
== NFCSTATUS_PENDING
);
313 printf("Deinitializing NFC stack.\n");
314 callbackStatus
= 0xFFFF;
315 status
= phLibNfc_Mgt_DeInitialize(hwRef
, initializeCallback
, &callbackStatus
);
316 assert(status
== NFCSTATUS_PENDING
);
318 pthread_mutex_lock(&mut
);
319 while (callbackStatus
== 0xFFFF)
320 pthread_cond_wait(&cond
, &mut
);
321 pthread_mutex_unlock(&mut
);
323 assert(callbackStatus
== NFCSTATUS_SUCCESS
);
325 terminateMessageThread(driverConfig
.nClientId
);
326 pthread_join(messageThread
, NULL
);
328 printf("Unconfiguring NFC driver.\n");
329 status
= phLibNfc_Mgt_UnConfigureDriver(hwRef
);
330 assert(status
== NFCSTATUS_SUCCESS
);
332 int result
= phDal4Nfc_msgctl(driverConfig
.nClientId
, 0, 0);
335 printf("Closing NFC device.\n");
336 nfc_pn544_close(nfcDevice
);
339 int main(int argc
, char **argv
)
342 int readNdefMessages
= 0;
343 int restartOnFailure
= 0;
345 while ((opt
= getopt(argc
, argv
, "nrh")) != -1) {
348 readNdefMessages
= 1;
349 fprintf(stdout
, "Reading NDEF messages from targets\n");
352 restartOnFailure
= 1;
353 readNdefMessages
= 1;
354 fprintf(stdout
, "Restarting on NDEF read failure, implies -n\n");
358 fprintf(stderr
, "\n Usage: %s \n"
359 "\t-n Read NDEF message from targets,\n"
360 "\t-r Restart on NDEF read failure.\n", argv
[0]);
366 testNfc(readNdefMessages
);
367 } while (restartOnFailure
&& readNdefMessages
);