Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / tests / test_nfc.c
1 /*
2 * Copyright (C) 2012 Jolla Ltd.
3 * Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com>
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 */
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23 #include <getopt.h>
24
25 #include <hardware/hardware.h>
26 #include <hardware/nfc.h>
27 #include <libnfc-nxp/phLibNfc.h>
28 #include <libnfc-nxp/phDal4Nfc_messageQueueLib.h>
29
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;
38
39 static void *messageThreadFunc(void *arg)
40 {
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);
47 if (ret == -1) {
48 fprintf(stderr, "Failed to receive message from NFC stack.\n");
49 continue;
50 }
51
52 switch (message.msg.eMsgType) {
53 case PH_LIBNFC_DEFERREDCALL_MSG: {
54 phLibNfc_DeferredCall_t *msg = (phLibNfc_DeferredCall_t *)message.msg.pMsgData;
55 if (msg->pCallback)
56 msg->pCallback(msg->pParameter);
57 break;
58 }
59 default:
60 fprintf(stderr, "Unknown message type %d.", message.msg.eMsgType);
61 }
62
63 pthread_cond_signal(&cond);
64 }
65
66 return 0;
67 }
68
69 static pthread_t createMessageThread(void *arg)
70 {
71 pthread_t thread_id;
72 int error = pthread_create(&thread_id, NULL, messageThreadFunc, arg);
73 if (error != 0)
74 return 0;
75
76 return thread_id;
77 }
78
79 static void terminateMessageThread(int clientId)
80 {
81 messageThreadRunning = 0;
82
83 phDal4Nfc_Message_Wrapper_t message;
84 phLibNfc_DeferredCall_t *msg;
85
86 msg = (phLibNfc_DeferredCall_t *)malloc(sizeof(phLibNfc_DeferredCall_t));
87 msg->pCallback = 0;
88 msg->pParameter = 0;
89 message.msg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
90 message.msg.pMsgData = msg;
91 message.msg.Size = sizeof(phLibNfc_DeferredCall_t);
92
93 phDal4Nfc_msgsnd(clientId, &message, sizeof(phLibNfc_Message_t), 0);
94 }
95
96 void initializeCallback(void *pContext, NFCSTATUS status)
97 {
98 NFCSTATUS *callbackStatus = (NFCSTATUS *)pContext;
99 *callbackStatus = status;
100 }
101
102 void discoveryNotificationCallback(void *pContext, phLibNfc_RemoteDevList_t *psRemoteDevList,
103 uint8_t uNofRemoteDev, NFCSTATUS status)
104 {
105 if (status == NFCSTATUS_DESELECTED) {
106 fprintf(stderr, "Target deselected\n");
107 } else {
108 fprintf(stderr, "Discovered %d targets\n", uNofRemoteDev);
109
110 uint8_t i;
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);
115 }
116 numberOfDiscoveredTargets = uNofRemoteDev;
117 discoveredTargets = psRemoteDevList;
118 targetStatus = status;
119 }
120 }
121
122 void discoveryCallback(void *pContext, NFCSTATUS status)
123 {
124 fprintf(stderr, "discoveryCallback %d\n", status);
125 }
126
127 void remoteDevConnectCallback(void *pContext, phLibNfc_Handle hRemoteDev,
128 phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
129 {
130 targetStatus = status;
131 connectedRemoteDevInfo = psRemoteDevInfo;
132 }
133
134 void remoteDevNdefReadCheckCallback(void *pContext, phLibNfc_ChkNdef_Info_t Ndef_Info,
135 NFCSTATUS status)
136 {
137 ndefInfo = Ndef_Info;
138 targetStatus = status;
139 }
140
141 void remoteDevNdefReadCallback(void *pContext, NFCSTATUS status)
142 {
143 targetStatus = status;
144 }
145
146 void testNfc(int readNdefMessages)
147 {
148 printf("Starting test_nfc.\n");
149
150 const hw_module_t *hwModule = 0;
151 nfc_pn544_device_t *nfcDevice = 0;
152
153 printf("Finding NFC hardware module.\n");
154 hw_get_module(NFC_HARDWARE_MODULE_ID, &hwModule);
155 assert(hwModule != NULL);
156
157 printf("Opening NFC device.\n");
158 assert(nfc_pn544_open(hwModule, &nfcDevice) == 0);
159 assert(nfcDevice != 0);
160
161 assert(nfcDevice->num_eeprom_settings != 0);
162 assert(nfcDevice->eeprom_settings);
163
164 printf("Configuring NFC driver.\n");
165 phLibNfc_sConfig_t driverConfig;
166 driverConfig.nClientId = phDal4Nfc_msgget(0, 0600);
167 assert(driverConfig.nClientId);
168
169 void *hwRef;
170 NFCSTATUS status = phLibNfc_Mgt_ConfigureDriver(&driverConfig, &hwRef);
171 assert(hwRef);
172 assert(status == NFCSTATUS_SUCCESS);
173
174 pthread_t messageThread = createMessageThread(&driverConfig.nClientId);
175
176 printf("Initializing NFC stack.\n");
177 NFCSTATUS callbackStatus = 0xFFFF;
178 status = phLibNfc_Mgt_Initialize(hwRef, initializeCallback, &callbackStatus);
179 assert(status == NFCSTATUS_PENDING);
180
181 pthread_mutex_lock(&mut);
182 while (callbackStatus == 0xFFFF)
183 pthread_cond_wait(&cond, &mut);
184 pthread_mutex_unlock(&mut);
185
186 assert(callbackStatus == NFCSTATUS_SUCCESS);
187
188 printf("Getting NFC stack capabilities.\n");
189 phLibNfc_StackCapabilities_t capabilities;
190 status = phLibNfc_Mgt_GetstackCapabilities(&capabilities, &callbackStatus);
191 assert(status == NFCSTATUS_SUCCESS);
192
193 printf("NFC capabilities:\n"
194 "\tHAL version: %u\n"
195 "\tFW version: %u\n"
196 "\tHW version: %u\n"
197 "\tModel: %u\n"
198 "\tHCI version: %u\n"
199 "\tVendor: %s\n"
200 "\tFull version: %u %u\n"
201 "\tFW Update: %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);
209
210 if (readNdefMessages) {
211 /* Start tag discovery */
212 phLibNfc_Registry_Info_t registryInfo;
213
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;
222
223 int context;
224 status = phLibNfc_RemoteDev_NtfRegister(&registryInfo, discoveryNotificationCallback, &context);
225 assert(status == NFCSTATUS_SUCCESS);
226
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;
239
240 targetStatus = 0xFFFF;
241 status = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_CONFIG, discoveryConfig,
242 discoveryCallback, &context);
243
244 for (;;) {
245 pthread_mutex_lock(&mut);
246 while (targetStatus == 0xFFFF)
247 pthread_cond_wait(&cond, &mut);
248 pthread_mutex_unlock(&mut);
249
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);
260
261 if (targetStatus == NFCSTATUS_SUCCESS) {
262 targetStatus = 0xFFFF;
263 status = phLibNfc_Ndef_CheckNdef(discoveredTargets[0].hTargetDev,
264 remoteDevNdefReadCheckCallback, &context);
265
266 pthread_mutex_lock(&mut);
267 while (targetStatus == 0xFFFF)
268 pthread_cond_wait(&cond, &mut);
269 pthread_mutex_unlock(&mut);
270
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);
277
278 targetStatus = 0xFFFF;
279 status = phLibNfc_Ndef_Read(discoveredTargets[0].hTargetDev, &ndefBuffer,
280 phLibNfc_Ndef_EBegin, remoteDevNdefReadCallback, &context);
281
282 pthread_mutex_lock(&mut);
283 while (targetStatus == 0xFFFF)
284 pthread_cond_wait(&cond, &mut);
285 pthread_mutex_unlock(&mut);
286
287 if (targetStatus == NFCSTATUS_SUCCESS) {
288 int i;
289 fprintf(stderr, "NDEF: ");
290 for (i = 0; i < ndefBuffer.length; ++i)
291 fprintf(stderr, "%02x", ndefBuffer.buffer[i]);
292 fprintf(stderr, "\n");
293 }
294
295 free(ndefBuffer.buffer);
296 }
297 }
298 }
299 }
300
301 if (status == NFCSTATUS_FAILED) {
302 fprintf(stderr, "Failed to connect to remote device\n");
303 break;
304 }
305
306 targetStatus = 0xFFFF;
307 status = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_RESUME, discoveryConfig,
308 discoveryCallback, &context);
309 assert(status == NFCSTATUS_SUCCESS || status == NFCSTATUS_PENDING);
310 }
311 }
312
313 printf("Deinitializing NFC stack.\n");
314 callbackStatus = 0xFFFF;
315 status = phLibNfc_Mgt_DeInitialize(hwRef, initializeCallback, &callbackStatus);
316 assert(status == NFCSTATUS_PENDING);
317
318 pthread_mutex_lock(&mut);
319 while (callbackStatus == 0xFFFF)
320 pthread_cond_wait(&cond, &mut);
321 pthread_mutex_unlock(&mut);
322
323 assert(callbackStatus == NFCSTATUS_SUCCESS);
324
325 terminateMessageThread(driverConfig.nClientId);
326 pthread_join(messageThread, NULL);
327
328 printf("Unconfiguring NFC driver.\n");
329 status = phLibNfc_Mgt_UnConfigureDriver(hwRef);
330 assert(status == NFCSTATUS_SUCCESS);
331
332 int result = phDal4Nfc_msgctl(driverConfig.nClientId, 0, 0);
333 assert(result == 0);
334
335 printf("Closing NFC device.\n");
336 nfc_pn544_close(nfcDevice);
337 }
338
339 int main(int argc, char **argv)
340 {
341 int opt;
342 int readNdefMessages = 0;
343 int restartOnFailure = 0;
344
345 while ((opt = getopt(argc, argv, "nrh")) != -1) {
346 switch (opt) {
347 case 'n':
348 readNdefMessages = 1;
349 fprintf(stdout, "Reading NDEF messages from targets\n");
350 break;
351 case 'r':
352 restartOnFailure = 1;
353 readNdefMessages = 1;
354 fprintf(stdout, "Restarting on NDEF read failure, implies -n\n");
355 break;
356 case 'h':
357 default:
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]);
361 return 1;
362 }
363 }
364
365 do {
366 testNfc(readNdefMessages);
367 } while (restartOnFailure && readNdefMessages);
368
369 return 0;
370 }