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 APP_FROM_HOST_EVENT_ID      0x000000F8
31 #define APP_FROM_HOST_CHRE_EVENT_ID 0x000000F9
32 
33 namespace android {
34 
35 namespace nanohub {
36 
37 void dumpBuffer(const char *pfx, const hub_app_name_t &appId, uint32_t evtId, const void *data, size_t len, int status = 0);
38 
39 struct nano_message_chre {
40     HostMsgHdrChre hdr;
41     uint8_t data[MAX_RX_PACKET];
42 } __attribute__((packed));
43 
44 struct nano_message {
45     HostMsgHdr hdr;
46     uint8_t data[MAX_RX_PACKET];
47 } __attribute__((packed));
48 
49 class HubMessage : public hub_message_t {
50     std::unique_ptr<uint8_t> data_;
51 public:
52     HubMessage(const HubMessage &other) = delete;
53     HubMessage &operator = (const HubMessage &other) = delete;
54 
HubMessage(const hub_app_name_t * name,uint32_t typ,const void * data,uint32_t len)55     HubMessage(const hub_app_name_t *name, uint32_t typ, const void *data, uint32_t len) {
56         app_name = *name;
57         message_type = typ;
58         message_len = len;
59         message = data;
60         if (len > 0 && data != nullptr) {
61             data_ = std::unique_ptr<uint8_t>(new uint8_t[len]);
62             memcpy(data_.get(), data, len);
63             message = data_.get();
64         }
65     }
66 
HubMessage(HubMessage && other)67     HubMessage(HubMessage &&other) {
68         *this = (HubMessage &&)other;
69     }
70 
71     HubMessage &operator = (HubMessage &&other) {
72         *static_cast<hub_message_t *>(this) = static_cast<hub_message_t>(other);
73         data_ = std::move(other.data_);
74         other.message = nullptr;
75         other.message_len = 0;
76         return *this;
77     }
78 };
79 
80 class NanoHub {
81     std::mutex mLock;
82     bool mAppQuit;
83     std::mutex mAppTxLock;
84     std::condition_variable mAppTxCond;
85     std::list<HubMessage> mAppTxQueue;
86     std::thread mPollThread;
87     std::thread mAppThread;
88     context_hub_callback *mMsgCbkFunc;
89     int mThreadClosingPipe[2];
90     int mFd; // [0] is read end
91     void * mMsgCbkData;
92 
93     NanoHub();
94     ~NanoHub();
95 
reset()96     void reset() {
97         mThreadClosingPipe[0] = -1;
98         mThreadClosingPipe[1] = -1;
99         mFd = -1;
100         mMsgCbkData = nullptr;
101         mMsgCbkFunc = nullptr;
102         mAppQuit = false;
103     }
104 
105     void* runAppTx();
106     void* runDeviceRx();
107 
108     int openHub();
109     int closeHub();
110 
hubInstance()111     static NanoHub *hubInstance() {
112         static NanoHub theHub;
113         return &theHub;
114     }
115 
116     int doSubscribeMessages(uint32_t hub_id, context_hub_callback *cbk, void *cookie);
117     int doSendToNanohub(uint32_t hub_id, const hub_message_t *msg);
118     int doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len, uint32_t messageType);
119     void doSendToApp(HubMessage &&msg);
120 
121     static constexpr unsigned int FL_MESSAGE_TRACING = 1;
122 
123     unsigned int mFlags = 0;
124 
125 public:
126 
127     // debugging interface
128 
messageTracingEnabled()129     static bool messageTracingEnabled() {
130         return hubInstance()->mFlags & FL_MESSAGE_TRACING;
131     }
getDebugFlags()132     static unsigned int getDebugFlags() {
133         return hubInstance()->mFlags;
134     }
setDebugFlags(unsigned int flags)135     static void setDebugFlags(unsigned int flags) {
136         hubInstance()->mFlags = flags;
137     }
138 
139     // messaging interface
140 
141     // define callback to invoke for APP messages
subscribeMessages(uint32_t hub_id,context_hub_callback * cbk,void * cookie)142     static int subscribeMessages(uint32_t hub_id, context_hub_callback *cbk, void *cookie) {
143         return hubInstance()->doSubscribeMessages(hub_id, cbk, cookie);
144     }
145     // all messages from APP go here
sendToNanohub(uint32_t hub_id,const hub_message_t * msg)146     static int sendToNanohub(uint32_t hub_id, const hub_message_t *msg) {
147         return hubInstance()->doSendToNanohub(hub_id, msg);
148     }
149     // passes message to kernel driver directly
sendToDevice(const hub_app_name_t * name,const void * data,uint32_t len)150     static int sendToDevice(const hub_app_name_t *name, const void *data, uint32_t len) {
151         return hubInstance()->doSendToDevice(*name, data, len, 0);
152     }
153     // passes message to APP via callback
sendToApp(HubMessage && msg)154     static void sendToApp(HubMessage &&msg) {
155         hubInstance()->doSendToApp((HubMessage &&)msg);
156     }
157 };
158 
159 }; // namespace nanohub
160 
161 }; // namespace android
162 
163 #endif
164