mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 19:25:43 +00:00
2ef55ccc43
From 2c1e87a8e1018f2c1d9f8825e36d1478a8a409bc Mon Sep 17 00:00:00 2001 --- dom/nfc/gonk/Nfc.js | 22 ++++++--- dom/nfc/gonk/NfcGonkMessage.h | 9 ---- dom/nfc/gonk/NfcMessageHandler.cpp | 91 +++++++++++++++++++------------------- dom/nfc/gonk/NfcOptions.h | 2 +- dom/webidl/NfcOptions.webidl | 16 ++++++- 5 files changed, 76 insertions(+), 64 deletions(-)
410 lines
12 KiB
C++
410 lines
12 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "NfcMessageHandler.h"
|
|
#include <binder/Parcel.h>
|
|
#include "mozilla/dom/MozNDEFRecordBinding.h"
|
|
#include "nsDebug.h"
|
|
#include "NfcGonkMessage.h"
|
|
#include "NfcOptions.h"
|
|
#include "mozilla/unused.h"
|
|
|
|
#include <android/log.h>
|
|
#define NMH_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "NfcMessageHandler", args)
|
|
|
|
using namespace android;
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
|
|
static const char* kChangeRFStateResponse = "ChangeRFStateResponse";
|
|
static const char* kReadNDEFResponse = "ReadNDEFResponse";
|
|
static const char* kWriteNDEFResponse = "WriteNDEFResponse";
|
|
static const char* kMakeReadOnlyResponse = "MakeReadOnlyResponse";
|
|
static const char* kFormatResponse = "FormatResponse";
|
|
static const char* kTransceiveResponse = "TransceiveResponse";
|
|
|
|
static const char* kInitializedNotification = "InitializedNotification";
|
|
static const char* kTechDiscoveredNotification = "TechDiscoveredNotification";
|
|
static const char* kTechLostNotification = "TechLostNotification";
|
|
static const char* kHCIEventTransactionNotification =
|
|
"HCIEventTransactionNotification";
|
|
|
|
bool
|
|
NfcMessageHandler::Marshall(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
bool result;
|
|
switch (aOptions.mType) {
|
|
case NfcRequestType::ChangeRFState:
|
|
result = ChangeRFStateRequest(aParcel, aOptions);
|
|
break;
|
|
case NfcRequestType::ReadNDEF:
|
|
result = ReadNDEFRequest(aParcel, aOptions);
|
|
break;
|
|
case NfcRequestType::WriteNDEF:
|
|
result = WriteNDEFRequest(aParcel, aOptions);
|
|
break;
|
|
case NfcRequestType::MakeReadOnly:
|
|
result = MakeReadOnlyRequest(aParcel, aOptions);
|
|
break;
|
|
case NfcRequestType::Format:
|
|
result = FormatRequest(aParcel, aOptions);
|
|
break;
|
|
case NfcRequestType::Transceive:
|
|
result = TransceiveRequest(aParcel, aOptions);
|
|
break;
|
|
default:
|
|
result = false;
|
|
break;
|
|
};
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::Unmarshall(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
mozilla::unused << htonl(aParcel.readInt32()); // parcel size
|
|
int32_t type = aParcel.readInt32();
|
|
bool isNotification = type >> 31;
|
|
int32_t msgType = type & ~(1 << 31);
|
|
|
|
return isNotification ? ProcessNotification(msgType, aParcel, aOptions) :
|
|
ProcessResponse(msgType, aParcel, aOptions);
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ProcessResponse(int32_t aType, const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
bool result;
|
|
switch (aType) {
|
|
case NfcResponse::ChangeRFStateRsp:
|
|
result = ChangeRFStateResponse(aParcel, aOptions);
|
|
break;
|
|
case NfcResponse::ReadNDEFRsp:
|
|
result = ReadNDEFResponse(aParcel, aOptions);
|
|
break;
|
|
case NfcResponse::WriteNDEFRsp: // Fall through.
|
|
case NfcResponse::MakeReadOnlyRsp:
|
|
case NfcResponse::FormatRsp:
|
|
result = GeneralResponse(aType, aParcel, aOptions);
|
|
break;
|
|
case NfcResponse::TransceiveRsp:
|
|
result = TransceiveResponse(aParcel, aOptions);
|
|
break;
|
|
default:
|
|
result = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ProcessNotification(int32_t aType, const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
bool result;
|
|
switch (aType) {
|
|
case NfcNotification::Initialized:
|
|
result = InitializeNotification(aParcel, aOptions);
|
|
break;
|
|
case NfcNotification::TechDiscovered:
|
|
result = TechDiscoveredNotification(aParcel, aOptions);
|
|
break;
|
|
case NfcNotification::TechLost:
|
|
result = TechLostNotification(aParcel, aOptions);
|
|
break;
|
|
case NfcNotification::HCIEventTransaction:
|
|
result = HCIEventTransactionNotification(aParcel, aOptions);
|
|
break;
|
|
default:
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::GeneralResponse(const int32_t aResponse, const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
const char* type;
|
|
switch (aResponse) {
|
|
case NfcResponse::WriteNDEFRsp:
|
|
type = kWriteNDEFResponse;
|
|
break;
|
|
case NfcResponse::MakeReadOnlyRsp:
|
|
type = kMakeReadOnlyResponse;
|
|
break;
|
|
case NfcResponse::FormatRsp:
|
|
type = kFormatResponse;
|
|
break;
|
|
default:
|
|
NMH_LOG("Nfcd, unknown general aResponse %d", aResponse);
|
|
return false;
|
|
}
|
|
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(type);
|
|
aOptions.mErrorCode = aParcel.readInt32();
|
|
aOptions.mSessionId = aParcel.readInt32();
|
|
|
|
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
|
aOptions.mRequestId = mRequestIdQueue[0];
|
|
mRequestIdQueue.RemoveElementAt(0);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ChangeRFStateRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::ChangeRFState));
|
|
aParcel.writeInt32(aOptions.mRfState);
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ChangeRFStateResponse(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kChangeRFStateResponse);
|
|
aOptions.mErrorCode = aParcel.readInt32();
|
|
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
|
aOptions.mRequestId = mRequestIdQueue[0];
|
|
mRequestIdQueue.RemoveElementAt(0);
|
|
|
|
aOptions.mRfState = aParcel.readInt32();
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ReadNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::ReadNDEF));
|
|
aParcel.writeInt32(aOptions.mSessionId);
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ReadNDEFResponse(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kReadNDEFResponse);
|
|
aOptions.mErrorCode = aParcel.readInt32();
|
|
aOptions.mSessionId = aParcel.readInt32();
|
|
|
|
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
|
aOptions.mRequestId = mRequestIdQueue[0];
|
|
mRequestIdQueue.RemoveElementAt(0);
|
|
|
|
if (aOptions.mErrorCode == NfcErrorCode::Success) {
|
|
ReadNDEFMessage(aParcel, aOptions);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::TransceiveRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::Transceive));
|
|
aParcel.writeInt32(aOptions.mSessionId);
|
|
aParcel.writeInt32(aOptions.mTechnology);
|
|
|
|
uint32_t length = aOptions.mCommand.Length();
|
|
aParcel.writeInt32(length);
|
|
|
|
void* data = aParcel.writeInplace(length);
|
|
memcpy(data, aOptions.mCommand.Elements(), length);
|
|
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::TransceiveResponse(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kTransceiveResponse);
|
|
aOptions.mErrorCode = aParcel.readInt32();
|
|
aOptions.mSessionId = aParcel.readInt32();
|
|
|
|
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
|
aOptions.mRequestId = mRequestIdQueue[0];
|
|
mRequestIdQueue.RemoveElementAt(0);
|
|
|
|
if (aOptions.mErrorCode == NfcErrorCode::Success) {
|
|
ReadTransceiveResponse(aParcel, aOptions);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::WriteNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::WriteNDEF));
|
|
aParcel.writeInt32(aOptions.mSessionId);
|
|
aParcel.writeInt32(aOptions.mIsP2P);
|
|
WriteNDEFMessage(aParcel, aOptions);
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::MakeReadOnlyRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::MakeReadOnly));
|
|
aParcel.writeInt32(aOptions.mSessionId);
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::FormatRequest(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::Format));
|
|
aParcel.writeInt32(aOptions.mSessionId);
|
|
mRequestIdQueue.AppendElement(aOptions.mRequestId);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::InitializeNotification(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kInitializedNotification);
|
|
aOptions.mStatus = aParcel.readInt32();
|
|
aOptions.mMajorVersion = aParcel.readInt32();
|
|
aOptions.mMinorVersion = aParcel.readInt32();
|
|
|
|
if (aOptions.mMajorVersion != NFCD_MAJOR_VERSION ||
|
|
aOptions.mMinorVersion != NFCD_MINOR_VERSION) {
|
|
NMH_LOG("NFCD version mismatched. majorVersion: %d, minorVersion: %d",
|
|
aOptions.mMajorVersion, aOptions.mMinorVersion);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::TechDiscoveredNotification(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kTechDiscoveredNotification);
|
|
aOptions.mSessionId = aParcel.readInt32();
|
|
aOptions.mIsP2P = aParcel.readInt32();
|
|
|
|
int32_t techCount = aParcel.readInt32();
|
|
aOptions.mTechList.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(techCount)), techCount);
|
|
|
|
int32_t idCount = aParcel.readInt32();
|
|
aOptions.mTagId.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(idCount)), idCount);
|
|
|
|
int32_t ndefMsgCount = aParcel.readInt32();
|
|
if (ndefMsgCount != 0) {
|
|
ReadNDEFMessage(aParcel, aOptions);
|
|
}
|
|
|
|
int32_t ndefInfo = aParcel.readInt32();
|
|
if (ndefInfo) {
|
|
aOptions.mTagType = aParcel.readInt32();
|
|
aOptions.mMaxNDEFSize = aParcel.readInt32();
|
|
aOptions.mIsReadOnly = aParcel.readInt32();
|
|
aOptions.mIsFormatable = aParcel.readInt32();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::TechLostNotification(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kTechLostNotification);
|
|
aOptions.mSessionId = aParcel.readInt32();
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::HCIEventTransactionNotification(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
aOptions.mType = NS_ConvertUTF8toUTF16(kHCIEventTransactionNotification);
|
|
|
|
aOptions.mOriginType = aParcel.readInt32();
|
|
aOptions.mOriginIndex = aParcel.readInt32();
|
|
|
|
int32_t aidLength = aParcel.readInt32();
|
|
aOptions.mAid.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(aidLength)), aidLength);
|
|
|
|
int32_t payloadLength = aParcel.readInt32();
|
|
aOptions.mPayload.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(payloadLength)), payloadLength);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ReadNDEFMessage(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
int32_t recordCount = aParcel.readInt32();
|
|
aOptions.mRecords.SetCapacity(recordCount);
|
|
|
|
for (int i = 0; i < recordCount; i++) {
|
|
int32_t tnf = aParcel.readInt32();
|
|
NDEFRecordStruct record;
|
|
record.mTnf = static_cast<TNF>(tnf);
|
|
|
|
int32_t typeLength = aParcel.readInt32();
|
|
record.mType.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(typeLength)), typeLength);
|
|
|
|
int32_t idLength = aParcel.readInt32();
|
|
record.mId.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(idLength)), idLength);
|
|
|
|
int32_t payloadLength = aParcel.readInt32();
|
|
record.mPayload.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(payloadLength)), payloadLength);
|
|
|
|
aOptions.mRecords.AppendElement(record);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::WriteNDEFMessage(Parcel& aParcel, const CommandOptions& aOptions)
|
|
{
|
|
int recordCount = aOptions.mRecords.Length();
|
|
aParcel.writeInt32(recordCount);
|
|
for (int i = 0; i < recordCount; i++) {
|
|
const NDEFRecordStruct& record = aOptions.mRecords[i];
|
|
aParcel.writeInt32(static_cast<int32_t>(record.mTnf));
|
|
|
|
void* data;
|
|
|
|
aParcel.writeInt32(record.mType.Length());
|
|
data = aParcel.writeInplace(record.mType.Length());
|
|
memcpy(data, record.mType.Elements(), record.mType.Length());
|
|
|
|
aParcel.writeInt32(record.mId.Length());
|
|
data = aParcel.writeInplace(record.mId.Length());
|
|
memcpy(data, record.mId.Elements(), record.mId.Length());
|
|
|
|
aParcel.writeInt32(record.mPayload.Length());
|
|
data = aParcel.writeInplace(record.mPayload.Length());
|
|
memcpy(data, record.mPayload.Elements(), record.mPayload.Length());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
NfcMessageHandler::ReadTransceiveResponse(const Parcel& aParcel, EventOptions& aOptions)
|
|
{
|
|
uint32_t length = aParcel.readInt32();
|
|
|
|
aOptions.mResponse.AppendElements(
|
|
static_cast<const uint8_t*>(aParcel.readInplace(length)), length);
|
|
|
|
return true;
|
|
}
|