316 lines
9.3 KiB
C++
316 lines
9.3 KiB
C++
/*
|
|
* 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_SYSTEM_COMMS_H_
|
|
#define _NANOHUB_SYSTEM_COMMS_H_
|
|
|
|
#include <utils/Condition.h>
|
|
#include <utils/Mutex.h>
|
|
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include <hardware/context_hub.h>
|
|
#include "nanohubhal.h"
|
|
#include "message_buf.h"
|
|
|
|
//rx: return 0 if handled, > 0 if not handled, < 0 if error happened
|
|
|
|
#define MSG_HANDLED 0
|
|
|
|
//messages to the HostIf nanoapp & their replies (mesages and replies both begin with u8 message_type)
|
|
#define NANOHUB_EXT_APPS_ON 0 // () -> (char success)
|
|
#define NANOHUB_EXT_APPS_OFF 1 // () -> (char success)
|
|
#define NANOHUB_EXT_APP_DELETE 2 // (u64 name) -> (char success) //idempotent
|
|
#define NANOHUB_QUERY_MEMINFO 3 // () -> (mem_info)
|
|
#define NANOHUB_QUERY_APPS 4 // (u32 idxStart) -> (app_info[idxStart] OR EMPTY IF NO MORE)
|
|
#define NANOHUB_QUERY_RSA_KEYS 5 // (u32 byteOffset) -> (u8 data[1 or more bytes] OR EMPTY IF NO MORE)
|
|
#define NANOHUB_START_UPLOAD 6 // (char isOs, u32 totalLenToTx) -> (char success)
|
|
#define NANOHUB_CONT_UPLOAD 7 // (u32 offset, u8 data[]) -> (char success)
|
|
#define NANOHUB_FINISH_UPLOAD 8 // () -> (char success)
|
|
#define NANOHUB_REBOOT 9 // () -> (char success)
|
|
|
|
// Custom defined private messages
|
|
#define CONTEXT_HUB_LOAD_OS (CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE + 1)
|
|
|
|
|
|
#define NANOHUB_APP_NOT_LOADED (-1)
|
|
#define NANOHUB_APP_LOADED (0)
|
|
|
|
#define NANOHUB_UPLOAD_CHUNK_SZ_MAX 64
|
|
#define NANOHUB_MEM_SZ_UNKNOWN 0xFFFFFFFFUL
|
|
|
|
namespace android {
|
|
|
|
namespace nanohub {
|
|
|
|
int system_comms_handle_rx(const nano_message *msg);
|
|
int system_comms_handle_tx(const hub_message_t *outMsg);
|
|
|
|
struct NanohubAppInfo {
|
|
hub_app_name_t name;
|
|
uint32_t version, flashUse, ramUse;
|
|
} __attribute__((packed));
|
|
|
|
struct NanohubMemInfo {
|
|
//sizes
|
|
uint32_t flashSz, blSz, osSz, sharedSz, eeSz;
|
|
uint32_t ramSz;
|
|
|
|
//use
|
|
uint32_t blUse, osUse, sharedUse, eeUse;
|
|
uint32_t ramUse;
|
|
} __attribute__((packed));
|
|
|
|
struct NanohubRsp {
|
|
uint32_t cmd;
|
|
int32_t status;
|
|
NanohubRsp(MessageBuf &buf, bool no_status = false);
|
|
};
|
|
|
|
inline bool operator == (const hub_app_name_t &a, const hub_app_name_t &b) {
|
|
return a.id == b.id;
|
|
}
|
|
|
|
inline bool operator != (const hub_app_name_t &a, const hub_app_name_t &b) {
|
|
return !(a == b);
|
|
}
|
|
|
|
class SystemComm {
|
|
private:
|
|
|
|
/*
|
|
* Nanohub HAL sessions
|
|
*
|
|
* Session is an object that can group several message exchanges with FW,
|
|
* maintain state, and be waited for completion by someone else.
|
|
*
|
|
* As of this moment, since all sessions are triggered by client thread,
|
|
* and all the exchange is happening in local worker thread, it is only possible
|
|
* for client thread to wait on session completion.
|
|
* Allowing sessions to wait on each other will require a worker thread pool.
|
|
* It is now unnecessary, and not implemented.
|
|
*/
|
|
class ISession {
|
|
public:
|
|
virtual int setup(const hub_message_t *app_msg) = 0;
|
|
virtual int handleRx(MessageBuf &buf) = 0;
|
|
virtual int getState() const = 0; // FSM state
|
|
virtual int getStatus() const = 0; // execution status (result code)
|
|
virtual ~ISession() {}
|
|
};
|
|
|
|
class SessionManager;
|
|
|
|
class Session : public ISession {
|
|
friend class SessionManager;
|
|
|
|
mutable Mutex mDoneLock; // controls condition and state transitions
|
|
Condition mDoneWait;
|
|
volatile int mState;
|
|
|
|
protected:
|
|
mutable Mutex mLock; // serializes message handling
|
|
int32_t mStatus;
|
|
|
|
enum {
|
|
SESSION_INIT = 0,
|
|
SESSION_DONE = 1,
|
|
SESSION_USER = 2,
|
|
};
|
|
|
|
void complete() {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
if (mState != SESSION_DONE) {
|
|
mState = SESSION_DONE;
|
|
mDoneWait.broadcast();
|
|
}
|
|
}
|
|
void setState(int state) {
|
|
if (state == SESSION_DONE) {
|
|
complete();
|
|
} else {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
mState = state;
|
|
}
|
|
}
|
|
public:
|
|
Session() { mState = SESSION_INIT; mStatus = -1; }
|
|
int getStatus() const {
|
|
Mutex::Autolock _l(mLock);
|
|
return mStatus;
|
|
}
|
|
int wait() {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
while (mState != SESSION_DONE) {
|
|
mDoneWait.wait(mDoneLock);
|
|
}
|
|
return 0;
|
|
}
|
|
virtual int getState() const override {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
return mState;
|
|
}
|
|
virtual bool isDone() const {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
return mState == SESSION_DONE;
|
|
}
|
|
virtual bool isRunning() const {
|
|
Mutex::Autolock _l(mDoneLock);
|
|
return mState > SESSION_DONE;
|
|
}
|
|
};
|
|
|
|
class AppMgmtSession : public Session {
|
|
enum {
|
|
TRANSFER = SESSION_USER,
|
|
FINISH,
|
|
RELOAD,
|
|
REBOOT,
|
|
MGMT,
|
|
};
|
|
uint32_t mCmd; // UPLOAD_APP | UPPLOAD_OS
|
|
uint32_t mResult;
|
|
std::vector<uint8_t> mData;
|
|
uint32_t mLen;
|
|
uint32_t mPos;
|
|
|
|
int setupMgmt(const hub_message_t *appMsg, uint32_t cmd);
|
|
int handleTransfer(NanohubRsp &rsp);
|
|
int handleFinish(NanohubRsp &rsp);
|
|
int handleReload(NanohubRsp &rsp);
|
|
int handleReboot(NanohubRsp &rsp);
|
|
int handleMgmt(NanohubRsp &rsp);
|
|
public:
|
|
AppMgmtSession() {
|
|
mCmd = 0;
|
|
mResult = 0;
|
|
mPos = 0;
|
|
mLen = 0;
|
|
}
|
|
virtual int handleRx(MessageBuf &buf) override;
|
|
virtual int setup(const hub_message_t *app_msg) override;
|
|
};
|
|
|
|
class MemInfoSession : public Session {
|
|
public:
|
|
virtual int setup(const hub_message_t *app_msg) override;
|
|
virtual int handleRx(MessageBuf &buf) override;
|
|
};
|
|
|
|
class KeyInfoSession : public Session {
|
|
std::vector<uint8_t> mRsaKeyData;
|
|
int requestRsaKeys(void);
|
|
public:
|
|
virtual int setup(const hub_message_t *) override;
|
|
virtual int handleRx(MessageBuf &buf) override;
|
|
bool haveKeys() const {
|
|
Mutex::Autolock _l(mLock);
|
|
return mRsaKeyData.size() > 0 && !isRunning();
|
|
}
|
|
};
|
|
|
|
class AppInfoSession : public Session {
|
|
std::vector<hub_app_info> mAppInfo;
|
|
int requestNext();
|
|
public:
|
|
virtual int setup(const hub_message_t *) override;
|
|
virtual int handleRx(MessageBuf &buf) override;
|
|
};
|
|
|
|
class GlobalSession : public Session {
|
|
public:
|
|
virtual int setup(const hub_message_t *) override;
|
|
virtual int handleRx(MessageBuf &buf) override;
|
|
};
|
|
|
|
class SessionManager {
|
|
typedef std::map<int, Session* > SessionMap;
|
|
|
|
Mutex lock;
|
|
SessionMap sessions_;
|
|
GlobalSession mGlobal;
|
|
|
|
void next(SessionMap::iterator &pos)
|
|
{
|
|
Mutex::Autolock _l(lock);
|
|
pos->second->isDone() ? pos = sessions_.erase(pos) : ++pos;
|
|
}
|
|
|
|
public:
|
|
SessionManager() {
|
|
mGlobal.setup(nullptr);
|
|
}
|
|
int handleRx(MessageBuf &buf);
|
|
int setup_and_add(int id, Session *session, const hub_message_t *appMsg) {
|
|
Mutex::Autolock _l(lock);
|
|
if (sessions_.count(id) == 0 && !session->isRunning()) {
|
|
int ret = session->setup(appMsg);
|
|
if (ret < 0) {
|
|
session->complete();
|
|
} else {
|
|
sessions_[id] = session;
|
|
}
|
|
return ret;
|
|
}
|
|
return -EBUSY;
|
|
}
|
|
|
|
} mSessions;
|
|
|
|
const hub_app_name_t mHostIfAppName = {
|
|
.id = NANO_APP_ID(NANOAPP_VENDOR_GOOGLE, 0)
|
|
};
|
|
|
|
static SystemComm *getSystem() {
|
|
// this is thread-safe in c++11
|
|
static SystemComm theInstance;
|
|
return &theInstance;
|
|
}
|
|
|
|
SystemComm () = default;
|
|
~SystemComm() = default;
|
|
|
|
int doHandleTx(const hub_message_t *txMsg);
|
|
int doHandleRx(const nano_message *rxMsg);
|
|
|
|
static void sendToApp(uint32_t typ, const void *data, uint32_t len) {
|
|
if (NanoHub::messageTracingEnabled()) {
|
|
dumpBuffer("HAL -> APP", get_hub_info()->os_app_name, typ, data, len);
|
|
}
|
|
NanoHub::sendToApp(&get_hub_info()->os_app_name, typ, data, len);
|
|
}
|
|
static int sendToSystem(const void *data, size_t len);
|
|
|
|
KeyInfoSession mKeySession;
|
|
AppMgmtSession mAppMgmtSession;
|
|
AppInfoSession mAppInfoSession;
|
|
MemInfoSession mMemInfoSession;
|
|
|
|
public:
|
|
static int handleTx(const hub_message_t *txMsg) {
|
|
return getSystem()->doHandleTx(txMsg);
|
|
}
|
|
static int handleRx(const nano_message *rxMsg) {
|
|
return getSystem()->doHandleRx(rxMsg);
|
|
}
|
|
};
|
|
|
|
}; // namespace nanohub
|
|
|
|
}; // namespace android
|
|
|
|
#endif
|