blob: e236d006e6ccdd969f8bb01320ab3f72e5169e34 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <semaphore.h>
#include "com_android_nfc.h"
static sem_t *nfc_jni_ndef_tag_sem;
static phLibNfc_Data_t nfc_jni_ndef_rw;
static NFCSTATUS nfc_jni_cb_status = NFCSTATUS_FAILED;
/* Shared with NfcTag module */
extern uint8_t nfc_jni_is_ndef;
extern uint8_t * nfc_jni_ndef_buf;
extern uint32_t nfc_jni_ndef_buf_len;
namespace android {
static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status)
{
LOG_CALLBACK("nfc_jni_tag_rw_callback", status);
nfc_jni_cb_status = status;
sem_post(nfc_jni_ndef_tag_sem);
}
static jbyteArray com_android_nfc_NativeNdefTag_doRead(JNIEnv *e,
jobject o)
{
phLibNfc_Handle handle = 0;
jbyteArray buf = NULL;
NFCSTATUS status;
CONCURRENCY_LOCK();
handle = nfc_jni_get_nfc_tag_handle(e, o);
nfc_jni_ndef_rw.length = nfc_jni_ndef_buf_len;
nfc_jni_ndef_rw.buffer = nfc_jni_ndef_buf;
TRACE("phLibNfc_Ndef_Read()");
REENTRANCE_LOCK();
status = phLibNfc_Ndef_Read( handle,
&nfc_jni_ndef_rw,
phLibNfc_Ndef_EBegin,
nfc_jni_tag_rw_callback,
(void *)e);
REENTRANCE_UNLOCK();
if(status != NFCSTATUS_PENDING)
{
LOGE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
goto clean_and_return;
}
TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
/* Wait for callback response */
sem_wait(nfc_jni_ndef_tag_sem);
if(nfc_jni_cb_status != NFCSTATUS_SUCCESS)
{
goto clean_and_return;
}
buf = e->NewByteArray(nfc_jni_ndef_rw.length);
e->SetByteArrayRegion(buf, 0, nfc_jni_ndef_rw.length,
(jbyte *)nfc_jni_ndef_rw.buffer);
clean_and_return:
CONCURRENCY_UNLOCK();
return buf;
}
static jboolean com_android_nfc_NativeNdefTag_doWrite(JNIEnv *e,
jobject o, jbyteArray buf)
{
NFCSTATUS status;
jboolean result = JNI_FALSE;
CONCURRENCY_LOCK();
phLibNfc_Handle handle = nfc_jni_get_nfc_tag_handle(e, o);
nfc_jni_ndef_rw.length = (uint32_t)e->GetArrayLength(buf);
nfc_jni_ndef_rw.buffer = (uint8_t *)e->GetByteArrayElements(buf, NULL);
TRACE("phLibNfc_Ndef_Write()");
REENTRANCE_LOCK();
status = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)e);
REENTRANCE_UNLOCK();
if(status != NFCSTATUS_PENDING)
{
LOGE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
goto clean_and_return;
}
TRACE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
/* Wait for callback response */
sem_wait(nfc_jni_ndef_tag_sem);
if(nfc_jni_cb_status != NFCSTATUS_SUCCESS)
{
goto clean_and_return;
}
result = JNI_TRUE;
clean_and_return:
if (result != JNI_TRUE)
{
e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT);
}
CONCURRENCY_UNLOCK();
return result;
}
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] =
{
{"doRead", "()[B",
(void *)com_android_nfc_NativeNdefTag_doRead},
{"doWrite", "([B)Z",
(void *)com_android_nfc_NativeNdefTag_doWrite},
};
int register_com_android_nfc_NativeNdefTag(JNIEnv *e)
{
nfc_jni_ndef_tag_sem = (sem_t *)malloc(sizeof(sem_t));
if(sem_init(nfc_jni_ndef_tag_sem, 0, 0) == -1)
return -1;
return jniRegisterNativeMethods(e,
"com/android/nfc/NativeNdefTag",
gMethods, NELEM(gMethods));
}
} // namespace android