1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License.
6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at
7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software
11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and
14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License.
15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly#include <semaphore.h>
18b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau#include <errno.h>
192534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes#include <ScopedLocalRef.h>
202534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes#include <ScopedPrimitiveArray.h>
21f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly#include "com_android_nfc.h"
2397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen#include "phNfcHalTypes.h"
24f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
25c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic phLibNfc_Data_t nfc_jni_ndef_rw;
26f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellystatic phLibNfc_Handle handle;
27c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellyuint8_t *nfc_jni_ndef_buf = NULL;
28c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellyuint32_t nfc_jni_ndef_buf_len = 0;
29f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3004a29c85c9bdbf0b25171332013934c3436ab0ecDaniel Tomasextern uint8_t device_connected_flag;
31f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
32f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellynamespace android {
33f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3407c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomasextern phLibNfc_Handle storedHandle;
3507c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas
3621545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pellyextern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat);
371b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenenextern void nfc_jni_reset_timeout_values();
38f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
39f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
40f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Callbacks
41f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
42c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status)
43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
44b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
45c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_tag_rw_callback", status);
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
47b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
48b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
49b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
52c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic void nfc_jni_connect_callback(void *pContext,
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle hRemoteDev,
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
56b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
57c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_connect_callback", status);
58f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
59b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
60b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
61319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   if (pCallbackData->pContext != NULL) {
62319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen       // Store the remote dev info ptr in the callback context
63319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen       // Note that this ptr will remain valid, it is tied to a statically
64319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen       // allocated buffer in libnfc.
65319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen       phLibNfc_sRemoteDevInformation_t** ppRemoteDevInfo =
66319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen           (phLibNfc_sRemoteDevInformation_t**)pCallbackData->pContext;
67319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen       *ppRemoteDevInfo = psRemoteDevInfo;
68319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   }
69319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
70b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
71f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
73c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic void nfc_jni_checkndef_callback(void *pContext,
74f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_ChkNdef_Info_t info, NFCSTATUS status)
75f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
76b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
77c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_checkndef_callback", status);
783ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   phLibNfc_ChkNdef_Info_t* pNdefInfo = (phLibNfc_ChkNdef_Info_t*) (pCallbackData->pContext);
79f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   if(status == NFCSTATUS_OK)
80f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
81c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      if(nfc_jni_ndef_buf)
82f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      {
83c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly         free(nfc_jni_ndef_buf);
84f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      }
85c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      nfc_jni_ndef_buf_len = info.MaxNdefMsgLength;
86c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      nfc_jni_ndef_buf = (uint8_t*)malloc(nfc_jni_ndef_buf_len);
873ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen      if (pNdefInfo != NULL) *pNdefInfo = info;
8841368d81f3076ac903693951f1d5cdba756f33fcMartijn Coenen   }
8941368d81f3076ac903693951f1d5cdba756f33fcMartijn Coenen   else {
903ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen      if (pNdefInfo != NULL) {
913ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen        memset(pNdefInfo, 0, sizeof(*pNdefInfo));
923ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen      }
93f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
94f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
95b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
96b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
97b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
98f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
99f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
100c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic void nfc_jni_disconnect_callback(void *pContext,
101f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle hRemoteDev, NFCSTATUS status)
102f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
103b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
104c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_disconnect_callback", status);
105f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
106c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   if(nfc_jni_ndef_buf)
107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
108c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      free(nfc_jni_ndef_buf);
109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
110c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_buf = NULL;
111c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_buf_len = 0;
112f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
113b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
114b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
115b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
118c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic void nfc_jni_async_disconnect_callback(void *pContext,
119f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle hRemoteDev, NFCSTATUS status)
120f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
121c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_async_disconnect_callback", status);
122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
123c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   if(nfc_jni_ndef_buf)
124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
125c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      free(nfc_jni_ndef_buf);
126f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
127c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_buf = NULL;
128c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_buf_len = 0;
129f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
131c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic phNfc_sData_t *nfc_jni_transceive_buffer;
132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
133c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pellystatic void nfc_jni_transceive_callback(void *pContext,
134f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
136b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
137c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   LOG_CALLBACK("nfc_jni_transceive_callback", status);
1382534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes
139c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_transceive_buffer = pResBuffer;
140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
141b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
142b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
143b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
146b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneaustatic void nfc_jni_presencecheck_callback(void *pContext, NFCSTATUS status)
147b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau{
148b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
149b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   LOG_CALLBACK("nfc_jni_presencecheck_callback", status);
150b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
151b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Report the callback status and wake up the caller */
152b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   pCallbackData->status = status;
153b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   sem_post(&pCallbackData->sem);
154b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau}
155b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1560aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenenstatic void nfc_jni_formatndef_callback(void *pContext, NFCSTATUS status)
1570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen{
1580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
1590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   LOG_CALLBACK("nfc_jni_formatndef_callback", status);
1600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1610aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   /* Report the callback status and wake up the caller */
1620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   pCallbackData->status = status;
1630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   sem_post(&pCallbackData->sem);
1640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen}
1650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenenstatic void nfc_jni_readonly_callback(void *pContext, NFCSTATUS status)
16703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen{
16803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
16903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   LOG_CALLBACK("nfc_jni_readonly_callback", status);
17003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
17103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   /* Report the callback status and wake up the caller */
17203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   pCallbackData->status = status;
17303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   sem_post(&pCallbackData->sem);
17403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen}
17503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/* Functions */
17713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellystatic jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e,
178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   jobject o)
179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   NFCSTATUS status;
181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle handle = 0;
182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   jbyteArray buf = NULL;
183b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_LOCK();
186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
187b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
188b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (!nfc_cb_data_init(&cb_data, NULL))
189b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
190b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
191b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
192b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
193ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
195c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_rw.length = nfc_jni_ndef_buf_len;
196c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_rw.buffer = nfc_jni_ndef_buf;
197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
198ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_Read()");
199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_LOCK();
200c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   status = phLibNfc_Ndef_Read(handle, &nfc_jni_ndef_rw,
2012534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                               phLibNfc_Ndef_EBegin,
2022534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                               nfc_jni_tag_rw_callback,
203b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau                               (void *)&cb_data);
204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_UNLOCK();
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   if(status != NFCSTATUS_PENDING)
206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
207afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
210ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2112534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes
212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Wait for callback response */
213b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(sem_wait(&cb_data.sem))
214b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
215afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
216b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
217b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
219b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(cb_data.status != NFCSTATUS_SUCCESS)
220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
224c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   buf = e->NewByteArray(nfc_jni_ndef_rw.length);
225c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   e->SetByteArrayRegion(buf, 0, nfc_jni_ndef_rw.length,
226c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly      (jbyte *)nfc_jni_ndef_rw.buffer);
227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyclean_and_return:
229b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_UNLOCK();
231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   return buf;
233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
2342534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes
235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellystatic jboolean com_android_nfc_NativeNfcTag_doWrite(JNIEnv *e,
237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   jobject o, jbyteArray buf)
238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   NFCSTATUS   status;
240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   jboolean    result = JNI_FALSE;
241b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
243ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o);
244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_LOCK();
246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
247b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
248b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (!nfc_cb_data_init(&cb_data, NULL))
249b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
250b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
251b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
252b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
253c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_rw.length = (uint32_t)e->GetArrayLength(buf);
254c2fdb614879c601b5162d5d93d705b05c7b1e072Nick Pelly   nfc_jni_ndef_rw.buffer = (uint8_t *)e->GetByteArrayElements(buf, NULL);
255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
256ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_Write()");
257ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("Ndef Handle :0x%x\n",handle);
258ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("Ndef buffer length : %d", nfc_jni_ndef_rw.length);
259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_LOCK();
260b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   status = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)&cb_data);
261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_UNLOCK();
262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   if(status != NFCSTATUS_PENDING)
263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
264afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
267ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Wait for callback response */
270b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(sem_wait(&cb_data.sem))
271b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
272afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
273b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
274b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
276b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(cb_data.status != NFCSTATUS_SUCCESS)
277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   result = JNI_TRUE;
282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyclean_and_return:
28414df195961abcd98263f5e03c5b17e96c5889a07Martijn Coenen   e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT);
28514df195961abcd98263f5e03c5b17e96c5889a07Martijn Coenen
286b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_UNLOCK();
288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   return result;
289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
291319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen/*
292319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen *  Utility to recover poll bytes from target infos
293319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen */
2943dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenenvoid set_target_pollBytes(JNIEnv *e, jobject tag,
295319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
296319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen{
2972534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(tag));
2982534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    jfieldID f = e->GetFieldID(tag_cls.get(), "mTechPollBytes", "[[B");
299d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen
3002534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jobjectArray> existingPollBytes(e, (jobjectArray) e->GetObjectField(tag, f));
3012534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    if (existingPollBytes.get() != NULL) {
302d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen        return;
303d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen    }
304d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen
3052534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    jfieldID techListField = e->GetFieldID(tag_cls.get(), "mTechList", "[I");
3062534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jintArray> techList(e, (jintArray) e->GetObjectField(tag, techListField));
3072534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedIntArrayRO techIds(e, techList.get());
3082534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    int techListLength = techIds.size();
309319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
3102534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0));
3112534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get()));
3122534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jobjectArray> techPollBytes(e, e->NewObjectArray(techListLength, byteArrayClass.get(), NULL));
313319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
314319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen    for (int tech = 0; tech < techListLength; tech++) {
3152534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes        switch(techIds[tech])
316319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen        {
317319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO14443-3A: ATQA/SENS_RES */
318319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO14443_3A:
31993e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                if (psRemoteDevInfo->RemDevType == phNfc_eJewel_PICC) {
32093e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                    // Jewel ATQA is not read and stored by the PN544, but it is fixed
32193e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                    // at {0x00, 0x0C} in the spec. So eJewel can safely be
32293e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                    // translated to {0x00, 0x0C}.
32393e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                    const static jbyte JewelAtqA[2] = {0x00, 0x0C};
3242534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    pollBytes.reset(e->NewByteArray(2));
3252534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*) JewelAtqA);
3262534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                } else {
3272534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA)));
3282534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA),
32993e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                                          (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA);
33093e639baa0b64f85a66bb2ed944583df815b276dMartijn Coenen                }
331319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
332319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES */
333319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO14443_3B:
3342534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData)
3352534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo)));
3362534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
337319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData);
3382534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
339319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo),
340319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo);
341319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
342319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) */
343319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_FELICA:
3442534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm)
3452534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode)));
3462534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
347319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm);
3482534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
349319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode),
350319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode);
351319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
352319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO15693: response flags (1 byte), DSFID (1 byte) */
353319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO15693:
3542534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
3552534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)));
3562534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
357319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
3582534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
359319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
360319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
361319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
362319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            default:
3632534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                pollBytes.reset(e->NewByteArray(0));
364319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
365319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen        }
3662534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes        e->SetObjectArrayElement(techPollBytes.get(), tech, pollBytes.get());
367319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen    }
368319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
3692534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    e->SetObjectField(tag, f, techPollBytes.get());
370319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen}
371319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
372319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen/*
373319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen *  Utility to recover activation bytes from target infos
374319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen */
3753dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenenvoid set_target_activationBytes(JNIEnv *e, jobject tag,
376319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
377319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen{
3782534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(tag));
379d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen
3802534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    jfieldID f = e->GetFieldID(tag_cls.get(), "mTechActBytes", "[[B");
3812534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jobjectArray> existingActBytes(e, (jobjectArray) e->GetObjectField(tag, f));
3822534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    if (existingActBytes.get() != NULL) {
383d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen        return;
384d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen    }
385d6a675eeecb5074c8a822353cb89762f8c6cc4bdMartijn Coenen
3862534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    jfieldID techListField = e->GetFieldID(tag_cls.get(), "mTechList", "[I");
3872534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jintArray> techList(e, (jintArray) e->GetObjectField(tag, techListField));
3882534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedIntArrayRO techIds(e, techList.get());
3892534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    int techListLength = techIds.size();
390319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
3912534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0));
3922534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get()));
3932534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    ScopedLocalRef<jobjectArray> techActBytes(e, e->NewObjectArray(techListLength, byteArrayClass.get(), 0));
394319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
395319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen    for (int tech = 0; tech < techListLength; tech++) {
3962534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes        switch(techIds[tech]) {
397319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
398319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO14443-3A: SAK/SEL_RES */
399319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO14443_3A:
4002534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                actBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak)));
4012534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(actBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak),
402319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak);
403319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
404319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS */
405319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO14443-3B & ISO14443-4: HiLayerResp */
406319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO14443_4:
407319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                // Determine whether -A or -B
408319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_B_PICC ||
4092534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) {
4102534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    actBytes.reset(e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength));
4112534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    e->SetByteArrayRegion(actBytes.get(), 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength,
412319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerResp);
4132534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                } else if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC ||
4142534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        psRemoteDevInfo->RemDevType == phNfc_eISO14443_4A_PICC) {
4152534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    actBytes.reset(e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength));
4162534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                    e->SetByteArrayRegion(actBytes.get(), 0,
417319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                          psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength,
418319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                          (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppData);
419319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                }
420319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
421319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            /* ISO15693: response flags (1 byte), DSFID (1 byte) */
422319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            case TARGET_TYPE_ISO15693:
4232534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                actBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
4242534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                        + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)));
4252534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(actBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
426319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
4272534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                e->SetByteArrayRegion(actBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
428319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
429319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
430319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
431319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen            default:
4322534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes                actBytes.reset(e->NewByteArray(0));
433319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen                break;
434319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen        }
4352534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes        e->SetObjectArrayElement(techActBytes.get(), tech, actBytes.get());
436319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen    }
4372534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes    e->SetObjectField(tag, f, techActBytes.get());
438319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen}
439319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
4402c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomasstatic jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e,
441bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen   jobject o, phLibNfc_Handle handle)
442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
4432c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   jint status;
444b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
445319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_LOCK();
448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
449b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
450319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
451b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
4522c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_NOT_ENOUGH_MEMORY;
453b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
454b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
455b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
456ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_RemoteDev_Connect(RW)");
457f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_LOCK();
458ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   storedHandle = handle;
459b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback,(void *)&cb_data);
460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_UNLOCK();
461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   if(status != NFCSTATUS_PENDING)
462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
463afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
466ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Wait for callback response */
469b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(sem_wait(&cb_data.sem))
470b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
471afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
4722c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_ABORTED;
473b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
474b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
4752c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas
4762c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   status = cb_data.status;
4772c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   TRACE("phLibNfc_RemoteDev_Connect() - Status code = %d", status);
4782c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas
479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Connect Status */
4802c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   if(status != NFCSTATUS_SUCCESS)
481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
485319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   // Success, set poll & act bytes
486319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   set_target_pollBytes(e, o, pRemDevInfo);
487319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen   set_target_activationBytes(e, o, pRemDevInfo);
488319fc851b61dd975e2309219ed13e21d3e167bddMartijn Coenen
489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyclean_and_return:
490b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_UNLOCK();
4922c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   return status;
493f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4952c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomasstatic jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e,
49678d140e347337074b38dea417d10beb58948106bMartijn Coenen   jobject o, phLibNfc_Handle handle)
49778d140e347337074b38dea417d10beb58948106bMartijn Coenen{
4982c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   jint status;
49978d140e347337074b38dea417d10beb58948106bMartijn Coenen   struct nfc_jni_callback_data cb_data;
50078d140e347337074b38dea417d10beb58948106bMartijn Coenen   phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
50178d140e347337074b38dea417d10beb58948106bMartijn Coenen   CONCURRENCY_LOCK();
50278d140e347337074b38dea417d10beb58948106bMartijn Coenen
50378d140e347337074b38dea417d10beb58948106bMartijn Coenen   /* Create the local semaphore */
50478d140e347337074b38dea417d10beb58948106bMartijn Coenen   if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
50578d140e347337074b38dea417d10beb58948106bMartijn Coenen   {
5062c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_NOT_ENOUGH_MEMORY;
50778d140e347337074b38dea417d10beb58948106bMartijn Coenen      goto clean_and_return;
50878d140e347337074b38dea417d10beb58948106bMartijn Coenen   }
50978d140e347337074b38dea417d10beb58948106bMartijn Coenen
51078d140e347337074b38dea417d10beb58948106bMartijn Coenen   TRACE("phLibNfc_RemoteDev_ReConnect(RW)");
51178d140e347337074b38dea417d10beb58948106bMartijn Coenen   REENTRANCE_LOCK();
51278d140e347337074b38dea417d10beb58948106bMartijn Coenen   storedHandle = handle;
51378d140e347337074b38dea417d10beb58948106bMartijn Coenen   status = phLibNfc_RemoteDev_ReConnect(handle, nfc_jni_connect_callback,(void *)&cb_data);
51478d140e347337074b38dea417d10beb58948106bMartijn Coenen   REENTRANCE_UNLOCK();
51578d140e347337074b38dea417d10beb58948106bMartijn Coenen   if(status != NFCSTATUS_PENDING)
51678d140e347337074b38dea417d10beb58948106bMartijn Coenen   {
517afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
51878d140e347337074b38dea417d10beb58948106bMartijn Coenen      goto clean_and_return;
51978d140e347337074b38dea417d10beb58948106bMartijn Coenen   }
52078d140e347337074b38dea417d10beb58948106bMartijn Coenen   TRACE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
52178d140e347337074b38dea417d10beb58948106bMartijn Coenen
52278d140e347337074b38dea417d10beb58948106bMartijn Coenen   /* Wait for callback response */
52378d140e347337074b38dea417d10beb58948106bMartijn Coenen   if(sem_wait(&cb_data.sem))
52478d140e347337074b38dea417d10beb58948106bMartijn Coenen   {
525afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
5262c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_ABORTED;
52778d140e347337074b38dea417d10beb58948106bMartijn Coenen      goto clean_and_return;
52878d140e347337074b38dea417d10beb58948106bMartijn Coenen   }
52978d140e347337074b38dea417d10beb58948106bMartijn Coenen
5302c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   status = cb_data.status;
5312c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas
53278d140e347337074b38dea417d10beb58948106bMartijn Coenen   /* Connect Status */
5332c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   if(status != NFCSTATUS_SUCCESS)
53478d140e347337074b38dea417d10beb58948106bMartijn Coenen   {
53578d140e347337074b38dea417d10beb58948106bMartijn Coenen      goto clean_and_return;
53678d140e347337074b38dea417d10beb58948106bMartijn Coenen   }
53778d140e347337074b38dea417d10beb58948106bMartijn Coenen
53878d140e347337074b38dea417d10beb58948106bMartijn Coenenclean_and_return:
53978d140e347337074b38dea417d10beb58948106bMartijn Coenen   nfc_cb_data_deinit(&cb_data);
54078d140e347337074b38dea417d10beb58948106bMartijn Coenen   CONCURRENCY_UNLOCK();
5412c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   return status;
54278d140e347337074b38dea417d10beb58948106bMartijn Coenen}
54378d140e347337074b38dea417d10beb58948106bMartijn Coenen
5442c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomasstatic jint com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e,
545aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen   jobject o)
546aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen{
547aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen    // Reconnect is provided by libnfc by just calling connect again
548aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen    // on the same handle.
5490a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen    int libNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o);
5500a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen    if (libNfcType != -1) {
5510a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen        // Note that some tag types are stateless, hence we do not reconnect
5520a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen        // those. Currently those are the Jewel and Iso15693 technologies.
5530a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen        if ((libNfcType != phNfc_eJewel_PICC) && (libNfcType != phNfc_eISO15693_PICC)) {
554bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            phLibNfc_Handle handle = nfc_jni_get_connected_handle(e,o);
555bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return com_android_nfc_NativeNfcTag_doConnect(e, o, handle);
556bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen        }
557bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen        else {
5582c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas            return NFCSTATUS_SUCCESS;
559bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen        }
560bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen    }
561bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen    else {
5622c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas        return NFCSTATUS_REJECTED;
563bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen    }
564aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen}
565aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
566aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
56713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellystatic jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o)
568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
569f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle handle = 0;
570f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   NFCSTATUS status;
571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   jboolean result = JNI_FALSE;
572b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
574f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_LOCK();
575f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
576ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
57707c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas
578b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
579b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (!nfc_cb_data_init(&cb_data, NULL))
580b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
581b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
582b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
583b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
58407c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas   /* Reset the stored handle */
58507c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas   storedHandle = 0;
58607c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas
5871b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen   nfc_jni_reset_timeout_values();
5881b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
589f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Disconnect */
590ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("Disconnecting from tag (%x)", handle);
5912534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes
592809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen   if (handle == -1) {
593809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen       // Was never connected to any tag, exit
594809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen       result = JNI_TRUE;
595afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block       ALOGE("doDisconnect() - Target already disconnected");
596809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen       nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
597809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen       goto clean_and_return;
598809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen   }
599809fdd1fce70e8ec65601a2910fd11a4dde7268dMartijn Coenen
600ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    TRACE("phLibNfc_RemoteDev_Disconnect(%x)", handle);
60148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    REENTRANCE_LOCK();
60248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE,
603b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau                                          nfc_jni_disconnect_callback, (void *)&cb_data);
60448819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    REENTRANCE_UNLOCK();
60507c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas
60607c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas    if(status == NFCSTATUS_TARGET_NOT_CONNECTED)
60707c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas    {
60807c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas        result = JNI_TRUE;
609ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        TRACE("phLibNfc_RemoteDev_Disconnect() - Target already disconnected");
61007c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas        goto clean_and_return;
61107c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas    }
61248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    if(status != NFCSTATUS_PENDING)
61348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
614afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block        ALOGE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
61548819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas        nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
61648819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas        goto clean_and_return;
61748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
618ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
61948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
62048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    /* Wait for callback response */
621b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    if(sem_wait(&cb_data.sem))
622b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    {
623afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
624b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau       goto clean_and_return;
625b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    }
6262534d9a546f24435d9dab8168f9ea5bf8ca1eb9bElliott Hughes
62748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    /* Disconnect Status */
628b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    if(cb_data.status != NFCSTATUS_SUCCESS)
62948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
63048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas        goto clean_and_return;
63148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
63204a29c85c9bdbf0b25171332013934c3436ab0ecDaniel Tomas
63348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    result = JNI_TRUE;
634f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
635f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyclean_and_return:
63604a29c85c9bdbf0b25171332013934c3436ab0ecDaniel Tomas    /* Reset device connected flag */
63704a29c85c9bdbf0b25171332013934c3436ab0ecDaniel Tomas    device_connected_flag = 0;
638b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_UNLOCK();
640f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   return result;
641f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
64397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenenstatic uint16_t
64497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenencrc_16_ccitt1( uint8_t* msg, size_t len, uint16_t init )
64597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen{
64697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint16_t b, crc = init;
64797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
64897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    do {
64997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        b = *msg++ ^ (crc & 0xFF);
65097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        b ^= (b << 4) & 0xFF;
65197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        crc = (crc >> 8) ^ (b << 8) ^ (b << 3) ^ (b >> 4);
65297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    } while( --len );
65397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
65497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    return crc;
65597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen}
65697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
65797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenenstatic void
65897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenennfc_insert_crc_a( uint8_t* msg, size_t len )
65997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen{
66097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint16_t crc;
66197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
66297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    crc = crc_16_ccitt1( msg, len, 0x6363 );
66397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    msg[len] = crc & 0xFF;
66497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    msg[len + 1] = (crc >> 8) & 0xFF;
66597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen}
66697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
66797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenenstatic void
66897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenennfc_get_crc_a( uint8_t* msg, size_t len, uint8_t* byte1, uint8_t* byte2)
66997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen{
67097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint16_t crc;
67197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
67297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    crc = crc_16_ccitt1( msg, len, 0x6363 );
67397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    *byte1 = crc & 0xFF;
67497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    *byte2 = (crc >> 8) & 0xFF;
67597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen}
67697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
67797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenenstatic bool
67897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenencrc_valid( uint8_t* msg, size_t len)
67997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen{
68097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint8_t crcByte1, crcByte2;
68197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
68297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    nfc_get_crc_a(nfc_jni_transceive_buffer->buffer,
68397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          len - 2, &crcByte1, &crcByte2);
68497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
68597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    if (msg[len - 2] == crcByte1 &&
68697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          msg[len - 1] == crcByte2) {
68797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        return true;
68897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    }
68997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    else {
69097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        return false;
69197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    }
69297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
69397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen}
694bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen
69513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellystatic jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e,
6969d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen   jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost)
697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
69848819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    uint8_t offset = 0;
69997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    // buf is the pointer to the JNI array and never overwritten,
70097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    // outbuf is passed into the transceive - it may be pointed to new memory
70197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    // to be extended with CRC.
70297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint8_t *buf = NULL;
70348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    uint32_t buflen;
70497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
70597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint8_t *outbuf = NULL;
70697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    uint32_t outlen;
70748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    phLibNfc_sTransceiveInfo_t transceive_info;
70848819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    jbyteArray result = NULL;
70948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    int res;
710ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen    phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o);
71148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    NFCSTATUS status;
712b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    struct nfc_jni_callback_data cb_data;
7136d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen    int selectedTech = 0;
7140a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen    int selectedLibNfcType = 0;
7156d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen    jint* technologies = NULL;
71697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    bool checkResponseCrc = false;
71748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
7189d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    jint *targetLost;
7199d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    if (statusTargetLost != NULL) {
7209d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        targetLost = e->GetIntArrayElements(statusTargetLost, 0);
7219d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        if (targetLost != NULL) {
7229d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen            *targetLost = 0;
7239d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        }
7249d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    } else {
7259d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        targetLost = NULL;
7269d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    }
7279d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen
728bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen    memset(&transceive_info, 0, sizeof(transceive_info));
72948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    CONCURRENCY_LOCK();
73048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
731b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    /* Create the local semaphore */
732b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    if (!nfc_cb_data_init(&cb_data, NULL))
733b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    {
734b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau       goto clean_and_return;
735b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    }
736b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
737bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen    selectedTech = nfc_jni_get_connected_technology(e, o);
7380a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen    selectedLibNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o);
73948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
74097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL);
74197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    buflen = outlen = (uint32_t)e->GetArrayLength(data);
74248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
7436d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen    switch (selectedTech) {
7446d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_FELICA:
7456d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.cmd.FelCmd = phNfc_eFelica_Raw;
7466d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.addr = 0;
7476d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
7486d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_MIFARE_CLASSIC:
7496d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_MIFARE_UL:
75097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          if (raw) {
75197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              transceive_info.cmd.MfCmd = phHal_eMifareRaw;
75297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              transceive_info.addr = 0;
75397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              // Need to add in the crc here
75497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              outbuf = (uint8_t*)malloc(buflen + 2);
75597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              outlen += 2;
75697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              memcpy(outbuf, buf, buflen);
75797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              nfc_insert_crc_a(outbuf, buflen);
75897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
75997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              checkResponseCrc = true;
76097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          } else {
76197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              offset = 2;
76297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
76397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen              transceive_info.addr = (uint8_t)buf[1];
76497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          }
7656d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
7666d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_ISO14443_3A:
7670a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen          // Check which libnfc type
7680a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen          if (selectedLibNfcType == phNfc_eJewel_PICC) {
7690a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen              // For the Jewel pipe, CRC is automatically computed
7700a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen              transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw;
7710a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen              transceive_info.addr = 0;
7720a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen          } else {
7731cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen              if (raw) {
7741cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  // Use Mifare Raw to implement a standard
7751cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  // ISO14443-3A transceive, with CRC added
7761cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  transceive_info.cmd.MfCmd = phHal_eMifareRaw;
7771cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  transceive_info.addr = 0;
7781cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  // Need to add in the crc here
7791cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  outbuf = (uint8_t*)malloc(buflen + 2);
7801cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  outlen += 2;
7811cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  memcpy(outbuf, buf, buflen);
7821cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  nfc_insert_crc_a(outbuf, buflen);
7831cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen
7841cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  checkResponseCrc = true;
7851cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen              } else {
7861cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  // Use the mifare pipe
7871cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  offset = 2;
7881cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
7891cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen                  transceive_info.addr = (uint8_t)buf[1];
7901cbf328d5e4dd6b06b877d3c5753c150f2c409fbMartijn Coenen              }
79197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
79297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          }
7936d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
7946d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_ISO14443_4:
7956d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
7966d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.addr = 0;
7976d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
7986d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_ISO15693:
7996d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.cmd.Iso15693Cmd = phNfc_eIso15693_Cmd;
8006d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          transceive_info.addr = 0;
8016d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
8026d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        case TARGET_TYPE_UNKNOWN:
80397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        case TARGET_TYPE_ISO14443_3B:
80497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          // Not supported
80597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen          goto clean_and_return;
8066d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen        default:
8076d11530887a3e6f30fa21d01bc0de5cdbd0218eaMartijn Coenen          break;
80848819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
81097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    transceive_info.sSendData.buffer = outbuf + offset;
81197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    transceive_info.sSendData.length = outlen - offset;
81248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
81348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    transceive_info.sRecvData.length = 1024;
81448819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    if(transceive_info.sRecvData.buffer == NULL)
81548819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
816f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
81748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
819ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    TRACE("phLibNfc_RemoteDev_Transceive()");
82048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    REENTRANCE_LOCK();
82148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
822b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau         nfc_jni_transceive_callback, (void *)&cb_data);
82348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    REENTRANCE_UNLOCK();
82448819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    if(status != NFCSTATUS_PENDING)
82548819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
826afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
8279d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen      if ((targetLost != NULL) && (status == NFCSTATUS_TARGET_LOST)) {
8289d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen          *targetLost = 1;
8299d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen      }
830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
83148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
832ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    TRACE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
83348819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
83448819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    /* Wait for callback response */
835b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    if(sem_wait(&cb_data.sem))
836b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    {
837afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
838b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau       goto clean_and_return;
839b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    }
84048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
841b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    if(cb_data.status != NFCSTATUS_SUCCESS)
84248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
8439d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        if ((targetLost != NULL) && (cb_data.status == NFCSTATUS_TARGET_LOST)) {
8449d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen            *targetLost = 1;
8459d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        }
84648819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas        goto clean_and_return;
84748819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
84848819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas
84997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    /* Copy results back to Java *
85097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen     * In case of NfcA and raw, also check the CRC in the response
85197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen     * and cut it off in the returned data.
85297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen     */
853ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen    if ((nfc_jni_transceive_buffer->length > 2) && checkResponseCrc) {
85497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        if (crc_valid(nfc_jni_transceive_buffer->buffer, nfc_jni_transceive_buffer->length)) {
85597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen            result = e->NewByteArray(nfc_jni_transceive_buffer->length - 2);
85697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen            if (result != NULL) {
85797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                e->SetByteArrayRegion(result, 0,
85897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                 nfc_jni_transceive_buffer->length - 2,
85997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                 (jbyte *)nfc_jni_transceive_buffer->buffer);
86097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen            }
86197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        }
86297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    } else {
86397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        result = e->NewByteArray(nfc_jni_transceive_buffer->length);
86497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        if (result != NULL) {
86597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen            e->SetByteArrayRegion(result, 0,
86697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen             nfc_jni_transceive_buffer->length,
86797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen             (jbyte *)nfc_jni_transceive_buffer->buffer);
86897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        }
86948819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
870b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneauclean_and_return:
87148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    if(transceive_info.sRecvData.buffer != NULL)
87248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    {
873f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      free(transceive_info.sRecvData.buffer);
87448819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    }
875f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
87697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    if ((outbuf != buf) && (outbuf != NULL)) {
87797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        // Buf was extended and re-alloced with crc bytes, free separately
87897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        free(outbuf);
87997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen    }
88097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
88148819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    e->ReleaseByteArrayElements(data,
88297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen      (jbyte *)buf, JNI_ABORT);
883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
8849d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    if (targetLost != NULL) {
8859d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
8869d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen    }
8879d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen
888b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau    nfc_cb_data_deinit(&cb_data);
889b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
89048819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    CONCURRENCY_UNLOCK();
891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
89248819102064977c3e37e18fd6db9a6022c01300cDaniel Tomas    return result;
893f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
894f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
895f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenenstatic jint com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *e, jobject o,
896f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen        jint libnfcType, jint javaType)
897f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen{
898f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen    jint ndefType =  NDEF_UNKNOWN_TYPE;
899f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen
900f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen    switch (libnfcType) {
901f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eJewel_PICC:
902f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              ndefType = NDEF_TYPE1_TAG;
903f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
904f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO14443_3A_PICC:
905f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              ndefType = NDEF_TYPE2_TAG;;
906f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
907f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eFelica_PICC:
908f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              ndefType = NDEF_TYPE3_TAG;
909f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
910f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO14443_A_PICC:
911f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO14443_4A_PICC:
912f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO14443_B_PICC:
913f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO14443_4B_PICC:
914f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              ndefType = NDEF_TYPE4_TAG;
915f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
916f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eMifare_PICC:
917f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              if (javaType == TARGET_TYPE_MIFARE_UL) {
918f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                  ndefType = NDEF_TYPE2_TAG;
919f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              } else {
920f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                  ndefType = NDEF_MIFARE_CLASSIC_TAG;
921f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              }
922f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
923f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          case phNfc_eISO15693_PICC:
924e8848005e3c79df26d8cdc4228220205eaeffe4fMartijn Coenen              ndefType = NDEF_ICODE_SLI_TAG;
925e8848005e3c79df26d8cdc4228220205eaeffe4fMartijn Coenen              break;
926f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen          default:
927f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              ndefType = NDEF_UNKNOWN_TYPE;
928f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen              break;
929f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen    }
930f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen    return ndefType;
931f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen}
932f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen
9332c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomasstatic jint com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo)
934f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   phLibNfc_Handle handle = 0;
9362c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   jint status;
9373ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   phLibNfc_ChkNdef_Info_t sNdefInfo;
938b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
9393ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   jint *ndef = e->GetIntArrayElements(ndefinfo, 0);
9403ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   int apiCardState = NDEF_MODE_UNKNOWN;
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_LOCK();
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
944b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
945b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (!nfc_cb_data_init(&cb_data, NULL))
946b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
9472c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_NOT_ENOUGH_MEMORY;
948b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
949b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
9503ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   cb_data.pContext = &sNdefInfo;
951b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
952ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
954ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_CheckNdef()");
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_LOCK();
956b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   status = phLibNfc_Ndef_CheckNdef(handle, nfc_jni_checkndef_callback,(void *)&cb_data);
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   REENTRANCE_UNLOCK();
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   if(status != NFCSTATUS_PENDING)
959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
960afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
963ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
964b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   /* Wait for callback response */
966b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(sem_wait(&cb_data.sem))
967b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
968afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
9692c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas      status = NFCSTATUS_ABORTED;
970b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
971b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
9732c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   status = cb_data.status;
9742c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   TRACE("phLibNfc_Ndef_CheckNdef() - Status code = %d", status);
9752c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas
9762c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   if (status != NFCSTATUS_SUCCESS)
977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      goto clean_and_return;
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   }
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
9813ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   ndef[0] = sNdefInfo.MaxNdefMsgLength;
9823ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   // Translate the card state to know values for the NFC API
9833ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   switch (sNdefInfo.NdefCardState) {
984eb5976d83844fbe1b16d951c781abe35b4305606Martijn Coenen       case PHLIBNFC_NDEF_CARD_INITIALISED:
9853ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           apiCardState = NDEF_MODE_READ_WRITE;
9863ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           break;
987eb5976d83844fbe1b16d951c781abe35b4305606Martijn Coenen       case PHLIBNFC_NDEF_CARD_READ_ONLY:
9883ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           apiCardState = NDEF_MODE_READ_ONLY;
9893ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           break;
990eb5976d83844fbe1b16d951c781abe35b4305606Martijn Coenen       case PHLIBNFC_NDEF_CARD_READ_WRITE:
9913ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           apiCardState = NDEF_MODE_READ_WRITE;
9923ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           break;
993eb5976d83844fbe1b16d951c781abe35b4305606Martijn Coenen       case PHLIBNFC_NDEF_CARD_INVALID:
9943ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           apiCardState = NDEF_MODE_UNKNOWN;
9953ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen           break;
9963ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   }
9973ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   ndef[1] = apiCardState;
9983ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyclean_and_return:
10003ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen   e->ReleaseIntArrayElements(ndefinfo, ndef, 0);
1001b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   CONCURRENCY_UNLOCK();
10032c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   return status;
1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1006b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneaustatic jboolean com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv *e, jobject o)
1007b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau{
1008b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   phLibNfc_Handle handle = 0;
1009b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   NFCSTATUS status;
1010b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   jboolean result = JNI_FALSE;
1011b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   struct nfc_jni_callback_data cb_data;
1012b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1013b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   CONCURRENCY_LOCK();
1014b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1015b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   /* Create the local semaphore */
1016b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (!nfc_cb_data_init(&cb_data, NULL))
1017b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
1018b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
1019b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
1020b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau
1021ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
1022b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1023ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_RemoteDev_CheckPresence()");
1024b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   REENTRANCE_LOCK();
1025b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   status = phLibNfc_RemoteDev_CheckPresence(handle, nfc_jni_presencecheck_callback, (void *)&cb_data);
1026b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   REENTRANCE_UNLOCK();
102707c19c3098f1d98c1c1a9e9f28aad22bd62a72a9Daniel Tomas
1028b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   if(status != NFCSTATUS_PENDING)
1029b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   {
1030afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1031b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau      goto clean_and_return;
1032b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   }
1033ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton   TRACE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1034b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1035b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   /* Wait for callback response */
1036b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if(sem_wait(&cb_data.sem))
1037b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   {
1038afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1039b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau      goto clean_and_return;
1040b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   }
1041b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1042b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   if (cb_data.status == NFCSTATUS_SUCCESS)
1043b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   {
1044b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau       result = JNI_TRUE;
1045b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   }
1046b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1047b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauclean_and_return:
1048b78172c6c46957cc37786b690db9bc854b26b7f9Sylvain Fonteneau   nfc_cb_data_deinit(&cb_data);
104904a29c85c9bdbf0b25171332013934c3436ab0ecDaniel Tomas
1050b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   CONCURRENCY_UNLOCK();
105197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen
1052b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   return result;
1053b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau}
1054f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1055841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenenstatic jboolean com_android_nfc_NativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv *e,
1056841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        jobject o, jbyteArray pollBytes, jbyteArray actBytes)
1057eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen{
1058841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen    // Determines whether this is a formatable IsoDep tag - currently only NXP DESFire
1059841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen    // is supported.
1060eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen    jboolean result = JNI_FALSE;
1061eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen
1062841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen    // DESfire has one sak byte and 2 ATQA bytes
1063841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen    if (pollBytes != NULL && (e->GetArrayLength(pollBytes) >= 2) &&
1064841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            actBytes != NULL && (e->GetArrayLength(actBytes) >= 1)) {
1065841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        jbyte* poll = e->GetByteArrayElements(pollBytes, NULL);
1066841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        jbyte* act = e->GetByteArrayElements(actBytes, NULL);
1067841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        if (act[0] == 0x20 && poll[1] == 0x03) {
1068841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
1069841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            // Identifies as DESfire, use get version cmd to be sure
1070841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            jbyteArray versionCmd = e->NewByteArray(5);
1071841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd);
1072841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            jbyteArray respBytes = com_android_nfc_NativeNfcTag_doTransceive(e, o,
1073841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                        versionCmd, JNI_TRUE, NULL);
1074841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen            if (respBytes != NULL) {
1075841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // Check whether the response matches a typical DESfire
1076841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // response.
1077841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // libNFC even does more advanced checking than we do
1078841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // here, and will only format DESfire's with a certain
1079841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // major/minor sw version and NXP as a manufacturer.
1080841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // We don't want to do such checking here, to avoid
1081841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // having to change code in multiple places.
1082841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // A succesful (wrapped) DESFire getVersion command returns
1083841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // 9 bytes, with byte 7 0x91 and byte 8 having status
1084841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                // code 0xAF (these values are fixed and well-known).
1085841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                int respLength = e->GetArrayLength(respBytes);
1086841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                jbyte* resp = e->GetByteArrayElements(respBytes, NULL);
1087841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                if (respLength == 9 && resp[7] == (jbyte)0x91 &&
1088841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                        resp[8] == (jbyte)0xAF) {
108973cc851dcb7d026015f6f91ab9336e5c042b8ac1Martijn Coenen                    result = JNI_TRUE;
109073cc851dcb7d026015f6f91ab9336e5c042b8ac1Martijn Coenen                }
1091841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen                e->ReleaseByteArrayElements(respBytes, (jbyte *)resp, JNI_ABORT);
109273cc851dcb7d026015f6f91ab9336e5c042b8ac1Martijn Coenen            }
1093841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        }
1094841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        e->ReleaseByteArrayElements(pollBytes, (jbyte *)poll, JNI_ABORT);
1095841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen        e->ReleaseByteArrayElements(actBytes, (jbyte *)act, JNI_ABORT);
1096eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen    }
1097eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen
1098841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen    return result;
1099eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen}
1100eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen
11010aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenenstatic jboolean com_android_nfc_NativeNfcTag_doNdefFormat(JNIEnv *e, jobject o, jbyteArray key)
11020aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen{
11030aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   phLibNfc_Handle handle = 0;
11040aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   NFCSTATUS status;
11050aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   phNfc_sData_t keyBuffer;
11060aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   jboolean result = JNI_FALSE;
11070aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   struct nfc_jni_callback_data cb_data;
11080aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11090aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   CONCURRENCY_LOCK();
11100aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11110aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   /* Create the local semaphore */
11120aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   if (!nfc_cb_data_init(&cb_data, NULL))
11130aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   {
11140aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen      goto clean_and_return;
11150aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   }
11160aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1117ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
11180aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11190aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   keyBuffer.buffer = (uint8_t *)e->GetByteArrayElements(key, NULL);
11200aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   keyBuffer.length = e->GetArrayLength(key);
11210aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   TRACE("phLibNfc_RemoteDev_FormatNdef()");
11220aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   REENTRANCE_LOCK();
11230aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   status = phLibNfc_RemoteDev_FormatNdef(handle, &keyBuffer, nfc_jni_formatndef_callback, (void *)&cb_data);
11240aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   REENTRANCE_UNLOCK();
11250aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11260aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   if(status != NFCSTATUS_PENDING)
11270aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   {
1128afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
11290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen      goto clean_and_return;
11300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   }
11310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   TRACE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
11320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   /* Wait for callback response */
11340aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   if(sem_wait(&cb_data.sem))
11350aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   {
1136afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
11370aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen      goto clean_and_return;
11380aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   }
11390aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11400aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   if (cb_data.status == NFCSTATUS_SUCCESS)
11410aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   {
11420aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen       result = JNI_TRUE;
11430aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   }
11440aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
11450aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenenclean_and_return:
11460aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   e->ReleaseByteArrayElements(key, (jbyte *)keyBuffer.buffer, JNI_ABORT);
11470aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   nfc_cb_data_deinit(&cb_data);
11480aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   CONCURRENCY_UNLOCK();
11490aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   return result;
11500aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen}
1151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1152ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenenstatic jboolean com_android_nfc_NativeNfcTag_doMakeReadonly(JNIEnv *e, jobject o, jbyteArray key)
115303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen{
115403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   phLibNfc_Handle handle = 0;
115503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   NFCSTATUS status;
115603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   jboolean result = JNI_FALSE;
115703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   struct nfc_jni_callback_data cb_data;
1158ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   phNfc_sData_t keyBuffer;
115903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
116003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   CONCURRENCY_LOCK();
116103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
116203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   /* Create the local semaphore */
116303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   if (!nfc_cb_data_init(&cb_data, NULL))
116403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   {
116503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen      goto clean_and_return;
116603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   }
116703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
116803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   handle = nfc_jni_get_connected_handle(e, o);
1169ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   keyBuffer.buffer = (uint8_t *)e->GetByteArrayElements(key, NULL);
1170ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   keyBuffer.length = e->GetArrayLength(key);
117103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   TRACE("phLibNfc_ConvertToReadOnlyNdef()");
117203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   REENTRANCE_LOCK();
1173ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   status = phLibNfc_ConvertToReadOnlyNdef(handle, &keyBuffer, nfc_jni_readonly_callback,
1174ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen           (void *)&cb_data);
117503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   REENTRANCE_UNLOCK();
117603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
117703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   if(status != NFCSTATUS_PENDING)
117803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   {
1179afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("pphLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
118003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen      goto clean_and_return;
118103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   }
118203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   TRACE("phLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
118303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
118403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   /* Wait for callback response */
118503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   if(sem_wait(&cb_data.sem))
118603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   {
1187afc8705e932af9a3a27239b0ca6fdb2026f15dfcSteve Block      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
118803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen      goto clean_and_return;
118903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   }
119003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
119103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   if (cb_data.status == NFCSTATUS_SUCCESS)
119203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   {
119303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen       result = JNI_TRUE;
119403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   }
119503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
119603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenenclean_and_return:
1197ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   e->ReleaseByteArrayElements(key, (jbyte *)keyBuffer.buffer, JNI_ABORT);
119803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   nfc_cb_data_deinit(&cb_data);
119903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   CONCURRENCY_UNLOCK();
120003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen   return result;
120103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen}
1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * JNI registration.
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellystatic JNINativeMethod gMethods[] =
1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
12072c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   {"doConnect", "(I)I",
120813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly      (void *)com_android_nfc_NativeNfcTag_doConnect},
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {"doDisconnect", "()Z",
121013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly      (void *)com_android_nfc_NativeNfcTag_doDisconnect},
12112c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   {"doReconnect", "()I",
1212aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen      (void *)com_android_nfc_NativeNfcTag_doReconnect},
12132c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   {"doHandleReconnect", "(I)I",
121478d140e347337074b38dea417d10beb58948106bMartijn Coenen      (void *)com_android_nfc_NativeNfcTag_doHandleReconnect},
12159d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen   {"doTransceive", "([BZ[I)[B",
121613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly      (void *)com_android_nfc_NativeNfcTag_doTransceive},
1217f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen   {"doGetNdefType", "(II)I",
1218f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen      (void *)com_android_nfc_NativeNfcTag_doGetNdefType},
12192c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas   {"doCheckNdef", "([I)I",
1220b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau      (void *)com_android_nfc_NativeNfcTag_doCheckNdef},
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {"doRead", "()[B",
122213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly      (void *)com_android_nfc_NativeNfcTag_doRead},
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   {"doWrite", "([B)Z",
122413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly      (void *)com_android_nfc_NativeNfcTag_doWrite},
1225b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau   {"doPresenceCheck", "()Z",
1226b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau      (void *)com_android_nfc_NativeNfcTag_doPresenceCheck},
1227841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen   {"doIsIsoDepNdefFormatable", "([B[B)Z",
1228841409b8ad298d34de24e584f3c152f023c3d2f4Martijn Coenen      (void *)com_android_nfc_NativeNfcTag_doIsIsoDepNdefFormatable},
12290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen   {"doNdefFormat", "([B)Z",
12300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen      (void *)com_android_nfc_NativeNfcTag_doNdefFormat},
1231ff07dc2bb156d62f447bc3613d6df339fa09794cMartijn Coenen   {"doMakeReadonly", "([B)Z",
123203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen      (void *)com_android_nfc_NativeNfcTag_doMakeReadonly},
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly};
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
123513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyint register_com_android_nfc_NativeNfcTag(JNIEnv *e)
1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly{
1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly   return jniRegisterNativeMethods(e,
1238642ab20c81425ba93e206d2a30602cd67ae8bd38Martijn Coenen      "com/android/nfc/dhimpl/NativeNfcTag",
1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly      gMethods, NELEM(gMethods));
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly}
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly} // namespace android
1243