1bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly/*
2bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly *
4bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * you may not use this file except in compliance with the License.
6bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * You may obtain a copy of the License at
7bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly *
8bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly *
10bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * Unless required by applicable law or agreed to in writing, software
11bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * See the License for the specific language governing permissions and
14bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly * limitations under the License.
15bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly */
16bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
17bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly#define LOG_TAG "NdefRecord"
18bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
191af97f0b78663eae0877644cc5f19bdbd9d033c7Nick Pelly#include <stdlib.h>
201af97f0b78663eae0877644cc5f19bdbd9d033c7Nick Pelly
21bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly#include "jni.h"
22bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly#include "JNIHelp.h"
23bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
24bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly#include "android_nfc.h"
25bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
26bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly#include <utils/Log.h>
27bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
28bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pellynamespace android {
29bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
30bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pellystatic jbyteArray android_nfc_NdefRecord_generate(
31bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        JNIEnv *e, jobject o, jshort flags, jshort tnf, jbyteArray type,
32bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        jbyteArray id, jbyteArray payload)
33bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly{
34bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    uint32_t status;
35bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    phFriNfc_NdefRecord_t record;
36bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    uint32_t buf_size;
37bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    uint32_t record_size;
38bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    uint8_t *buf = NULL;
39bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    jbyteArray result = NULL;
40bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
41bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    /* Prepare NDEF record structure */
42bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.Flags = (uint8_t)flags;
43bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.Tnf = (uint8_t)tnf;
44bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.TypeLength = (uint32_t)e->GetArrayLength(type);
45bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.Type = (uint8_t *)e->GetByteArrayElements(type, NULL);
46bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.IdLength = (uint32_t)e->GetArrayLength(id);
47bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.Id = (uint8_t *)e->GetByteArrayElements(id, NULL);
48bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.PayloadLength = (uint32_t)e->GetArrayLength(payload);
49bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    record.PayloadData = (uint8_t *)e->GetByteArrayElements(payload, NULL);
50bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
51bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    buf_size = record.PayloadLength + record.IdLength + record.TypeLength + 8;
52bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
53bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    buf = (uint8_t*)malloc(buf_size);
54bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    if (buf == NULL)
55bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        goto end;
56bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
575629d51f221adad107a509570ab2c739d1bf1a23Jeff Hamilton    TRACE("phFriNfc_NdefRecord_Generate()");
58bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
59bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    status = phFriNfc_NdefRecord_Generate(&record, buf, buf_size,
60bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly            &record_size);
61bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
62bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    if (status) {
63bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        LOGE("phFriNfc_NdefRecord_Generate() returned 0x%04x", status);
64bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        goto end;
65bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    }
665629d51f221adad107a509570ab2c739d1bf1a23Jeff Hamilton    TRACE("phFriNfc_NdefRecord_Generate() returned 0x%04x", status);
67bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
68bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    result = e->NewByteArray(record_size);
69bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    if (result == NULL)
70bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        goto end;
71bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
72bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    e->SetByteArrayRegion(result, 0, record_size, (jbyte *)buf);
73bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
74bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pellyend:
75bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    e->ReleaseByteArrayElements(type, (jbyte *)record.Type, JNI_ABORT);
76bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    e->ReleaseByteArrayElements(id, (jbyte *)record.Id, JNI_ABORT);
77bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    e->ReleaseByteArrayElements(payload, (jbyte *)record.PayloadData, JNI_ABORT);
78bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
79bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    if(buf)
80bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly        free(buf);
81bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
82bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    return result;
83bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly}
84bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
85dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneaustatic jint android_nfc_NdefRecord_parseNdefRecord(JNIEnv *e, jobject o,
86dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        jbyteArray array)
87dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau{
88dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    uint16_t status;
89dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jbyte *raw_record;
90dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jsize raw_record_size;
91dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jint ret = -1;
92dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    phFriNfc_NdefRecord_t record;
93dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
948bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    jfieldID mType, mId, mPayload, mTnf, mFlags;
95dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jbyteArray type = NULL;
96dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jbyteArray id = NULL;
97dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jbyteArray payload = NULL;
98dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
99dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    jclass record_cls = e->GetObjectClass(o);
100dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
101dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    raw_record_size = e->GetArrayLength(array);
102dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    raw_record = e->GetByteArrayElements(array, NULL);
103dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (raw_record == NULL) {
104dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        goto clean_and_return;
105dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
106dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
1075629d51f221adad107a509570ab2c739d1bf1a23Jeff Hamilton    TRACE("phFriNfc_NdefRecord_Parse()");
108dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    status = phFriNfc_NdefRecord_Parse(&record, (uint8_t *)raw_record);
109dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (status) {
110dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        LOGE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
111dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        goto clean_and_return;
112dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
1135629d51f221adad107a509570ab2c739d1bf1a23Jeff Hamilton    TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
114dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
115dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    /* Set TNF field */
116dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    mTnf = e->GetFieldID(record_cls, "mTnf", "S");
117dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetShortField(o, mTnf, record.Tnf);
118dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
119dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    /* Set type field */
120dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    mType = e->GetFieldID(record_cls, "mType", "[B");
121dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    type = e->NewByteArray(record.TypeLength);
122dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (type == NULL) {
123dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        goto clean_and_return;
124dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
125dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetByteArrayRegion(type, 0, record.TypeLength,
126dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau            (jbyte *)record.Type);
127dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetObjectField(o, mType, type);
128dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
129dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    /* Set id field */
130dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    mId = e->GetFieldID(record_cls, "mId", "[B");
131dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    id = e->NewByteArray(record.IdLength);
132dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (id == NULL) {
133dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        goto clean_and_return;
134dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
135dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetByteArrayRegion(id, 0, record.IdLength,
136dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau            (jbyte *)record.Id);
137dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetObjectField(o, mId, id);
138dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
139dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    /* Set payload field */
140dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    mPayload = e->GetFieldID(record_cls, "mPayload", "[B");
141dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    payload = e->NewByteArray(record.PayloadLength);
142dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (payload == NULL) {
143dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        goto clean_and_return;
144dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
1458bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen
146dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetByteArrayRegion(payload, 0, record.PayloadLength,
147dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau            (jbyte *)record.PayloadData);
148dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    e->SetObjectField(o, mPayload, payload);
149dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
1508bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    /* Set flags field */
1518bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    mFlags = e->GetFieldID(record_cls, "mFlags", "B");
152ef565c43939d9ce417f0064852badb91ae669e77Martijn Coenen    e->SetByteField(o, mFlags, record.Flags);
1538bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen
154dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    ret = 0;
155dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
156dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneauclean_and_return:
157dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (type != NULL) {
158dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        e->DeleteLocalRef(type);
159dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
160dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (id != NULL) {
161dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        e->DeleteLocalRef(id);
162dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
163dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (payload != NULL) {
164dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        e->DeleteLocalRef(payload);
165dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
166dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    if (raw_record != NULL) {
167dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        e->ReleaseByteArrayElements(array, raw_record, JNI_ABORT);
168dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    }
169dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
170dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    return ret;
171dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau}
172dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau
173bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pellystatic JNINativeMethod gMethods[] = {
174bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    {"generate", "(SS[B[B[B)[B", (void *)android_nfc_NdefRecord_generate},
175dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    {"parseNdefRecord", "([B)I", (void *)android_nfc_NdefRecord_parseNdefRecord},
176bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly};
177bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
178bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pellyint register_android_nfc_NdefRecord(JNIEnv *e)
179bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly{
180bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly    return jniRegisterNativeMethods(e, "android/nfc/NdefRecord", gMethods, NELEM(gMethods));
181bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly}
182bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly
183bc21fdefdfbeba1754c6cd339c7dd8e8f1d6fd48Nick Pelly} // namespace android
184