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