Home | History | Annotate | Download | only in contexthubhal
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef _NANOHUB_HAL_H_
     18 #define _NANOHUB_HAL_H_
     19 
     20 #include <mutex>
     21 #include <thread>
     22 #include <list>
     23 
     24 #include <hardware/context_hub.h>
     25 
     26 #include <nanohub/nanohub.h>
     27 
     28 //as per protocol
     29 #define MAX_RX_PACKET               128
     30 #define MAX_TX_PACKET               128
     31 #define APP_FROM_HOST_EVENT_ID      0x000000F8
     32 #define APP_FROM_HOST_CHRE_EVENT_ID 0x000000F9
     33 
     34 #define ENDPOINT_UNSPECIFIED        0xFFFE
     35 #define ENDPOINT_BROADCAST          0xFFFF
     36 
     37 namespace android {
     38 
     39 namespace nanohub {
     40 
     41 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);
     42 
     43 struct nano_message_chre {
     44     HostMsgHdrChre hdr;
     45     uint8_t data[MAX_RX_PACKET];
     46 } __attribute__((packed));
     47 
     48 struct nano_message_raw {
     49     HostMsgHdr hdr;
     50     uint8_t data[MAX_RX_PACKET];
     51 } __attribute__((packed));
     52 
     53 union nano_message {
     54     struct nano_message_chre chre;
     55     struct nano_message_raw raw;
     56 } __attribute__((packed));
     57 
     58 class HubMessage : public hub_message_t {
     59     std::unique_ptr<uint8_t> data_;
     60 public:
     61     uint32_t message_transaction_id;
     62     uint16_t message_endpoint;
     63     HubMessage(const HubMessage &other) = delete;
     64     HubMessage &operator = (const HubMessage &other) = delete;
     65 
     66     HubMessage(const hub_app_name_t *name, uint32_t typ, uint32_t transaction_id,
     67             uint16_t endpoint, const void *data, uint32_t len) {
     68         app_name = *name;
     69         message_type = typ;
     70         message_len = len;
     71         message = data;
     72         message_transaction_id = transaction_id;
     73         message_endpoint = endpoint;
     74         if (len > 0 && data != nullptr) {
     75             data_ = std::unique_ptr<uint8_t>(new uint8_t[len]);
     76             memcpy(data_.get(), data, len);
     77             message = data_.get();
     78         }
     79     }
     80 
     81     HubMessage(const hub_app_name_t *name, uint32_t typ, uint16_t endpoint, const void *data,
     82             uint32_t len) : HubMessage(name, typ, 0, endpoint, data, len) { }
     83 
     84     HubMessage(const hub_message_t *msg, uint32_t transaction_id, uint16_t endpoint) {
     85         app_name = msg->app_name;
     86         message_type = msg->message_type;
     87         message_len = msg->message_len;
     88         message = msg->message;
     89         message_transaction_id = transaction_id;
     90         message_endpoint = endpoint;
     91         if (msg->message_len > 0 && msg->message != nullptr) {
     92             data_ = std::unique_ptr<uint8_t>(new uint8_t[msg->message_len]);
     93             memcpy(data_.get(), msg->message, msg->message_len);
     94             message = data_.get();
     95         }
     96     }
     97 
     98     HubMessage(HubMessage &&other) {
     99         *this = (HubMessage &&)other;
    100     }
    101 
    102     HubMessage &operator = (HubMessage &&other) {
    103         *static_cast<hub_message_t *>(this) = static_cast<hub_message_t>(other);
    104         message_transaction_id = other.message_transaction_id;
    105         message_endpoint = other.message_endpoint;
    106         data_ = std::move(other.data_);
    107         other.message = nullptr;
    108         other.message_len = 0;
    109         return *this;
    110     }
    111 };
    112 
    113 typedef int Contexthub_callback(uint32_t hub_id, const HubMessage &rxed_msg, void *cookie);
    114 
    115 class NanoHub {
    116     std::mutex mLock;
    117     bool mAppQuit;
    118     std::mutex mAppTxLock;
    119     std::condition_variable mAppTxCond;
    120     std::list<HubMessage> mAppTxQueue;
    121     std::thread mPollThread;
    122     std::thread mAppThread;
    123     Contexthub_callback *mMsgCbkFunc;
    124     int mThreadClosingPipe[2];
    125     int mFd; // [0] is read end
    126     void * mMsgCbkData;
    127 
    128     NanoHub();
    129     ~NanoHub();
    130 
    131     void reset() {
    132         mThreadClosingPipe[0] = -1;
    133         mThreadClosingPipe[1] = -1;
    134         mFd = -1;
    135         mMsgCbkData = nullptr;
    136         mMsgCbkFunc = nullptr;
    137         mAppQuit = false;
    138     }
    139 
    140     void* runAppTx();
    141     void* runDeviceRx();
    142 
    143     int openHub();
    144     int closeHub();
    145 
    146     static NanoHub *hubInstance() {
    147         static NanoHub theHub;
    148         return &theHub;
    149     }
    150 
    151     int doSubscribeMessages(uint32_t hub_id, Contexthub_callback *cbk, void *cookie);
    152     int doSendToNanohub(uint32_t hub_id, const hub_message_t *msg,
    153             uint32_t transaction_id, uint16_t endpoint);
    154     int doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len,
    155             uint32_t messageType = 0, uint16_t endpoint = ENDPOINT_UNSPECIFIED);
    156     void doSendToApp(HubMessage &&msg);
    157     void doDumpAppInfo(std::string &result);
    158 
    159     static constexpr unsigned int FL_MESSAGE_TRACING = 1;
    160 
    161     unsigned int mFlags = 0;
    162 
    163 public:
    164 
    165     // debugging interface
    166 
    167     static bool messageTracingEnabled() {
    168         return hubInstance()->mFlags & FL_MESSAGE_TRACING;
    169     }
    170     static unsigned int getDebugFlags() {
    171         return hubInstance()->mFlags;
    172     }
    173     static void setDebugFlags(unsigned int flags) {
    174         hubInstance()->mFlags = flags;
    175     }
    176     static void dumpAppInfo(std::string &result) {
    177         hubInstance()->doDumpAppInfo(result);
    178     }
    179 
    180     // messaging interface
    181 
    182     // define callback to invoke for APP messages
    183     static int subscribeMessages(uint32_t hub_id, Contexthub_callback *cbk, void *cookie) {
    184         return hubInstance()->doSubscribeMessages(hub_id, cbk, cookie);
    185     }
    186     // all messages from APP go here
    187     static int sendToNanohub(uint32_t hub_id, const hub_message_t *msg,
    188             uint32_t transaction_id, uint16_t endpoint) {
    189         return hubInstance()->doSendToNanohub(hub_id, msg, transaction_id, endpoint);
    190     }
    191     // passes message to kernel driver directly
    192     static int sendToDevice(const hub_app_name_t *name, const void *data, uint32_t len,
    193             uint32_t transactionId) {
    194         return hubInstance()->doSendToDevice(*name, data, len, transactionId, ENDPOINT_UNSPECIFIED);
    195     }
    196     // passes message to APP via callback
    197     static void sendToApp(HubMessage &&msg) {
    198         hubInstance()->doSendToApp((HubMessage &&)msg);
    199     }
    200 };
    201 
    202 }; // namespace nanohub
    203 
    204 }; // namespace android
    205 
    206 #endif
    207