/* * Copyright (C) 2016 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. */ #ifndef _NANOHUB_HAL_H_ #define _NANOHUB_HAL_H_ #include <mutex> #include <thread> #include <list> #include <hardware/context_hub.h> #include <nanohub/nanohub.h> //as per protocol #define MAX_RX_PACKET 128 #define MAX_TX_PACKET 128 #define APP_FROM_HOST_EVENT_ID 0x000000F8 #define APP_FROM_HOST_CHRE_EVENT_ID 0x000000F9 #define ENDPOINT_UNSPECIFIED 0xFFFE #define ENDPOINT_BROADCAST 0xFFFF namespace android { namespace nanohub { void dumpBuffer(const char *pfx, const hub_app_name_t &appId, uint32_t evtId, uint16_t endpoint, const void *data, size_t len, int status = 0); struct nano_message_chre { HostMsgHdrChre hdr; uint8_t data[MAX_RX_PACKET]; } __attribute__((packed)); struct nano_message_raw { HostMsgHdr hdr; uint8_t data[MAX_RX_PACKET]; } __attribute__((packed)); union nano_message { struct nano_message_chre chre; struct nano_message_raw raw; } __attribute__((packed)); class HubMessage : public hub_message_t { std::unique_ptr<uint8_t> data_; public: uint32_t message_transaction_id; uint16_t message_endpoint; HubMessage(const HubMessage &other) = delete; HubMessage &operator = (const HubMessage &other) = delete; HubMessage(const hub_app_name_t *name, uint32_t typ, uint32_t transaction_id, uint16_t endpoint, const void *data, uint32_t len) { app_name = *name; message_type = typ; message_len = len; message = data; message_transaction_id = transaction_id; message_endpoint = endpoint; if (len > 0 && data != nullptr) { data_ = std::unique_ptr<uint8_t>(new uint8_t[len]); memcpy(data_.get(), data, len); message = data_.get(); } } HubMessage(const hub_app_name_t *name, uint32_t typ, uint16_t endpoint, const void *data, uint32_t len) : HubMessage(name, typ, 0, endpoint, data, len) { } HubMessage(const hub_message_t *msg, uint32_t transaction_id, uint16_t endpoint) { app_name = msg->app_name; message_type = msg->message_type; message_len = msg->message_len; message = msg->message; message_transaction_id = transaction_id; message_endpoint = endpoint; if (msg->message_len > 0 && msg->message != nullptr) { data_ = std::unique_ptr<uint8_t>(new uint8_t[msg->message_len]); memcpy(data_.get(), msg->message, msg->message_len); message = data_.get(); } } HubMessage(HubMessage &&other) { *this = (HubMessage &&)other; } HubMessage &operator = (HubMessage &&other) { *static_cast<hub_message_t *>(this) = static_cast<hub_message_t>(other); message_transaction_id = other.message_transaction_id; message_endpoint = other.message_endpoint; data_ = std::move(other.data_); other.message = nullptr; other.message_len = 0; return *this; } }; typedef int Contexthub_callback(uint32_t hub_id, const HubMessage &rxed_msg, void *cookie); class NanoHub { std::mutex mLock; bool mAppQuit; std::mutex mAppTxLock; std::condition_variable mAppTxCond; std::list<HubMessage> mAppTxQueue; std::thread mPollThread; std::thread mAppThread; Contexthub_callback *mMsgCbkFunc; int mThreadClosingPipe[2]; int mFd; // [0] is read end void * mMsgCbkData; NanoHub(); ~NanoHub(); void reset() { mThreadClosingPipe[0] = -1; mThreadClosingPipe[1] = -1; mFd = -1; mMsgCbkData = nullptr; mMsgCbkFunc = nullptr; mAppQuit = false; } void* runAppTx(); void* runDeviceRx(); int openHub(); int closeHub(); static NanoHub *hubInstance() { static NanoHub theHub; return &theHub; } int doSubscribeMessages(uint32_t hub_id, Contexthub_callback *cbk, void *cookie); int doSendToNanohub(uint32_t hub_id, const hub_message_t *msg, uint32_t transaction_id, uint16_t endpoint); int doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len, uint32_t messageType = 0, uint16_t endpoint = ENDPOINT_UNSPECIFIED); void doSendToApp(HubMessage &&msg); void doDumpAppInfo(std::string &result); static constexpr unsigned int FL_MESSAGE_TRACING = 1; unsigned int mFlags = 0; public: // debugging interface static bool messageTracingEnabled() { return hubInstance()->mFlags & FL_MESSAGE_TRACING; } static unsigned int getDebugFlags() { return hubInstance()->mFlags; } static void setDebugFlags(unsigned int flags) { hubInstance()->mFlags = flags; } static void dumpAppInfo(std::string &result) { hubInstance()->doDumpAppInfo(result); } // messaging interface // define callback to invoke for APP messages static int subscribeMessages(uint32_t hub_id, Contexthub_callback *cbk, void *cookie) { return hubInstance()->doSubscribeMessages(hub_id, cbk, cookie); } // all messages from APP go here static int sendToNanohub(uint32_t hub_id, const hub_message_t *msg, uint32_t transaction_id, uint16_t endpoint) { return hubInstance()->doSendToNanohub(hub_id, msg, transaction_id, endpoint); } // passes message to kernel driver directly static int sendToDevice(const hub_app_name_t *name, const void *data, uint32_t len, uint32_t transactionId) { return hubInstance()->doSendToDevice(*name, data, len, transactionId, ENDPOINT_UNSPECIFIED); } // passes message to APP via callback static void sendToApp(HubMessage &&msg) { hubInstance()->doSendToApp((HubMessage &&)msg); } }; }; // namespace nanohub }; // namespace android #endif