1fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema/* 2e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * Copyright (C) 2016 The Android Open Source Project 3fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema * 4e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * Licensed under the Apache License, Version 2.0 (the "License"); 5e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * you may not use this file except in compliance with the License. 6e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * You may obtain a copy of the License at 7fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema * 8e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * http://www.apache.org/licenses/LICENSE-2.0 9e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * 10e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * Unless required by applicable law or agreed to in writing, software 11e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * distributed under the License is distributed on an "AS IS" BASIS, 12e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * See the License for the specific language governing permissions and 14e96ece71fbd610603074755303e1d6cc3e505b00Zhengyin Qian * limitations under the License. 15fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema */ 16fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 17fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#define LOG_TAG "NanohubHAL" 1896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 1996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <fcntl.h> 2096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <poll.h> 2196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <unistd.h> 2296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <sys/inotify.h> 2396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <sys/types.h> 2496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <sys/stat.h> 2596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 26fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#include <hardware/context_hub.h> 27fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#include <hardware/hardware.h> 2896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 2996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <utils/Log.h> 3070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov#include <cutils/properties.h> 3196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 32c8e09a8dc0eecf2e0fb473ff8d8c0574f7fbfa9cAlexey Polyudov#include <nanohub/nanohub.h> 33c8e09a8dc0eecf2e0fb473ff8d8c0574f7fbfa9cAlexey Polyudov 3496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov#include <cinttypes> 3570ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov#include <iomanip> 3670ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov#include <sstream> 3796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 38fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#include "nanohub_perdevice.h" 39fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#include "system_comms.h" 40fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema#include "nanohubhal.h" 4183110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 423716b181acd60279ba61a0db235ca7267462567cPeng Xu#define NANOHUB_LOCK_DIR "/data/vendor/sensor/nanohub_lock" 4383110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie#define NANOHUB_LOCK_FILE NANOHUB_LOCK_DIR "/lock" 4483110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie#define NANOHUB_LOCK_DIR_PERMS (S_IRUSR | S_IWUSR | S_IXUSR) 45fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 4696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovnamespace android { 4796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 4896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovnamespace nanohub { 49fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 5070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudovinline std::ostream &operator << (std::ostream &os, const hub_app_name_t &appId) 5170ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov{ 5270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov char vendor[6]; 5370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov __be64 beAppId = htobe64(appId.id); 5470ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov uint32_t seqId = appId.id & NANOAPP_VENDOR_ALL_APPS; 5570ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov 5670ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov std::ios::fmtflags f(os.flags()); 5770ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov memcpy(vendor, (void*)&beAppId, sizeof(vendor) - 1); 5870ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov vendor[sizeof(vendor) - 1] = 0; 5970ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (strlen(vendor) == 5) 6070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << vendor << ", " << std::hex << std::setw(6) << seqId; 6170ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov else 6270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << "#" << std::hex << appId.id; 6370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os.flags(f); 6470ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov 6570ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov return os; 6670ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov} 6770ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov 6870ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudovvoid dumpBuffer(const char *pfx, const hub_app_name_t &appId, uint32_t evtId, const void *data, size_t len, int status) 6970ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov{ 7070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov std::ostringstream os; 7170ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov const uint8_t *p = static_cast<const uint8_t *>(data); 7270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << pfx << ": [ID=" << appId << "; SZ=" << std::dec << len; 7370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (evtId) 7470ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << "; EVT=" << std::hex << evtId; 7570ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << "]:" << std::hex; 7670ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov for (size_t i = 0; i < len; ++i) { 7717e6eabfe6229c7b42d078a89c4119fea7108788Alexey Polyudov os << " " << std::setfill('0') << std::setw(2) << (unsigned int)p[i]; 7870ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov } 7970ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (status) { 8070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov os << "; status=" << status << " [" << std::setfill('0') << std::setw(8) << status << "]"; 8170ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov } 8270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov ALOGI("%s", os.str().c_str()); 8370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov} 8470ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov 85fe2188fa871f1d4470378c004ad44d4216202641Ben Fennemastatic int rwrite(int fd, const void *buf, int len) 86fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 87fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema int ret; 88fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 89fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema do { 90fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = write(fd, buf, len); 91fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } while (ret < 0 && errno == EINTR); 92fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 9396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (ret != len) { 94fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return errno ? -errno : -EIO; 9596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 96fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 97fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return 0; 98fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 99fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 100fe2188fa871f1d4470378c004ad44d4216202641Ben Fennemastatic int rread(int fd, void *buf, int len) 101fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 102fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema int ret; 103fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 104fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema do { 105fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = read(fd, buf, len); 106fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } while (ret < 0 && errno == EINTR); 107fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 108fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return ret; 109fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 110fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 11196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovstatic bool init_inotify(pollfd *pfd) { 11283110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie bool success = false; 11383110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 11483110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie mkdir(NANOHUB_LOCK_DIR, NANOHUB_LOCK_DIR_PERMS); 11583110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie pfd->fd = inotify_init1(IN_NONBLOCK); 11683110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie if (pfd->fd < 0) { 11783110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie ALOGE("Couldn't initialize inotify: %s", strerror(errno)); 1189bbfdff8a9baa3e2c9b258f326777d8234af7c44Brian Duddie } else if (inotify_add_watch(pfd->fd, NANOHUB_LOCK_DIR, IN_CREATE | IN_DELETE) < 0) { 11983110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie ALOGE("Couldn't add inotify watch: %s", strerror(errno)); 12083110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie close(pfd->fd); 12183110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } else { 12283110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie pfd->events = POLLIN; 12383110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie success = true; 12483110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } 12583110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 12683110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie return success; 12783110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie} 12883110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 12996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovstatic void discard_inotify_evt(pollfd &pfd) { 13096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if ((pfd.revents & POLLIN)) { 13196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov char buf[sizeof(inotify_event) + NAME_MAX + 1]; 13296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov int ret = read(pfd.fd, buf, sizeof(buf)); 13396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ALOGD("Discarded %d bytes of inotify data", ret); 13496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 13583110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie} 13683110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 13796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovstatic void wait_on_dev_lock(pollfd &pfd) { 13883110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie // While the lock file exists, poll on the inotify fd (with timeout) 13996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov discard_inotify_evt(pfd); 14083110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie while (access(NANOHUB_LOCK_FILE, F_OK) == 0) { 14183110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie ALOGW("Nanohub is locked; blocking read thread"); 14296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov int ret = poll(&pfd, 1, 5000); 14396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (ret > 0) { 14496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov discard_inotify_evt(pfd); 14583110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } 14683110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } 14783110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie} 14883110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 149679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian DuddieNanoHub::NanoHub() { 150679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie reset(); 151679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie} 152679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie 153679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian DuddieNanoHub::~NanoHub() { 154679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie if (mMsgCbkFunc) { 155679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie ALOGD("Shutting down"); 156679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie closeHub(); 157679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie } 158679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie} 159679ee8dd0d6f535da9062ddef53cf9b8b00bc3c2Brian Duddie 160672acdeb3c63987a9a778dbcc84fe74e0fb4a5dbStephen Hinesint NanoHub::doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len, uint32_t messageType) 161fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 162672acdeb3c63987a9a778dbcc84fe74e0fb4a5dbStephen Hines if (len > MAX_RX_PACKET) { 163fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov return -EINVAL; 16496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 165fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov 1660ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov // transmit message to FW in CHRE format 1670ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov nano_message_chre msg = { 168fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov .hdr = { 1690ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov .eventId = APP_FROM_HOST_CHRE_EVENT_ID, 170672acdeb3c63987a9a778dbcc84fe74e0fb4a5dbStephen Hines .appId = name.id, 17196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov .len = static_cast<uint8_t>(len), 1720ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov .appEventId = messageType, 17396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov }, 174fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov }; 175fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 176fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov memcpy(&msg.data[0], data, len); 177fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 178fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov return rwrite(mFd, &msg, len + sizeof(msg.hdr)); 179fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 180fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 18153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudovvoid NanoHub::doSendToApp(HubMessage &&msg) 182fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 18353d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov std::unique_lock<std::mutex> lk(mAppTxLock); 18453d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppTxQueue.push_back((HubMessage &&)msg); 18553d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov lk.unlock(); 18653d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppTxCond.notify_all(); 18753d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov} 188fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 18953d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudovvoid* NanoHub::runAppTx() 19053d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov{ 19153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov std::unique_lock<std::mutex> lk(mAppTxLock); 19253d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov while(true) { 19353d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppTxCond.wait(lk, [this] { return !mAppTxQueue.empty() || mAppQuit; }); 19453d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov if (mAppQuit) { 19553d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov break; 19653d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov } 19753d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov HubMessage &m = mAppTxQueue.front(); 19853d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov lk.unlock(); 19953d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mMsgCbkFunc(0, &m, mMsgCbkData); 20053d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov lk.lock(); 20153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppTxQueue.pop_front(); 20253d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov }; 20353d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov return NULL; 204fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 205fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 20653d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudovvoid* NanoHub::runDeviceRx() 20796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov{ 20896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov enum { 20996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov IDX_NANOHUB, 21096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov IDX_CLOSE_PIPE, 21196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov IDX_INOTIFY 21296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov }; 21396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov pollfd myFds[3] = { 21496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov [IDX_NANOHUB] = { .fd = mFd, .events = POLLIN, }, 21596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov [IDX_CLOSE_PIPE] = { .fd = mThreadClosingPipe[0], .events = POLLIN, }, 21683110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie }; 21796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov pollfd &inotifyFd = myFds[IDX_INOTIFY]; 21896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov bool hasInotify = false; 21983110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie int numPollFds = 2; 220fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 22196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (init_inotify(&inotifyFd)) { 22296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov numPollFds++; 22396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov hasInotify = true; 22483110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } 22583110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 22670ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov setDebugFlags(property_get_int32("persist.nanohub.debug", 0)); 22770ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov 228fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema while (1) { 22996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov int ret = poll(myFds, numPollFds, -1); 230fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (ret <= 0) { 231710367565483bf7e01d5a2c7ab51d931f082bab8Andrew Rossignol ALOGD("poll returned with an error: %s", strerror(errno)); 232fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema continue; 233fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 234fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 23596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (hasInotify) { 23696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov wait_on_dev_lock(inotifyFd); 23783110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie } 23883110051b77fe8a6c4c31ef115ad745cea4d79a6Brian Duddie 23996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (myFds[IDX_NANOHUB].revents & POLLIN) { // we have data 240fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 24196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov nano_message msg; 242fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 243fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov ret = rread(mFd, &msg, sizeof(msg)); 244fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (ret <= 0) { 245b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser ALOGE("read failed with %d", ret); 246fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema break; 247fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 248fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov if (ret < (int)sizeof(msg.hdr)) { 249b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser ALOGE("Only read %d bytes", ret); 250b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser break; 251b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser } 252b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser 25396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov uint32_t len = msg.hdr.len; 254fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 255fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov if (len > sizeof(msg.data)) { 256b143f602214a5b711b5c9b1c3a11c8bd49f84764Greg Kaiser ALOGE("malformed packet with len %" PRIu32, len); 257fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema break; 258fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 259fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 2600ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov // receive message from FW in legacy format 261fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov if (ret != (int)(sizeof(msg.hdr) + len)) { 26296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ALOGE("Expected %zu bytes, read %d bytes", sizeof(msg.hdr) + len, ret); 263fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema break; 264fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 265fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 26696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ret = SystemComm::handleRx(&msg); 26796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (ret < 0) { 26896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ALOGE("SystemComm::handleRx() returned %d", ret); 26996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else if (ret) { 270b78969e7bce5b6d57a3e6b99315f44fe77b5d2b6Alexey Polyudov hub_app_name_t app_name = { .id = msg.hdr.appId }; 27170ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (messageTracingEnabled()) { 272b78969e7bce5b6d57a3e6b99315f44fe77b5d2b6Alexey Polyudov dumpBuffer("DEV -> APP", app_name, msg.hdr.eventId, &msg.data[0], msg.hdr.len); 27370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov } 27453d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov doSendToApp(HubMessage(&app_name, msg.hdr.eventId, &msg.data[0], msg.hdr.len)); 27596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 276fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 277fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 27896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (myFds[IDX_CLOSE_PIPE].revents & POLLIN) { // we have been asked to die 279fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGD("thread exiting"); 280fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema break; 281fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 282fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 283fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 284fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema close(mFd); 285fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return NULL; 286fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 287fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 28896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovint NanoHub::openHub() 289fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 290fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema int ret = 0; 291fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 292fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema mFd = open(get_devnode_path(), O_RDWR); 293fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (mFd < 0) { 294fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGE("cannot find hub devnode '%s'", get_devnode_path()); 295fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = -errno; 296fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema goto fail_open; 297fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 298fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 299fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (pipe(mThreadClosingPipe)) { 300fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGE("failed to create signal pipe"); 301fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = -errno; 302fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema goto fail_pipe; 303fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 304fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 30553d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mPollThread = std::thread([this] { runDeviceRx(); }); 30653d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppThread = std::thread([this] { runAppTx(); }); 307fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return 0; 308fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 309fe2188fa871f1d4470378c004ad44d4216202641Ben Fennemafail_pipe: 310fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema close(mFd); 311fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 312fe2188fa871f1d4470378c004ad44d4216202641Ben Fennemafail_open: 313fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return ret; 314fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 315fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 31696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovint NanoHub::closeHub(void) 317fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 318fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema char zero = 0; 319fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 32053d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov // stop mPollThread 32153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov while(write(mThreadClosingPipe[1], &zero, 1) != 1) { 32253d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov continue; 32353d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov } 32453d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov 32553d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov // stop mAppThread 32653d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov { 32753d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov std::unique_lock<std::mutex> lk(mAppTxLock); 32853d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppQuit = true; 32953d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov lk.unlock(); 33053d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppTxCond.notify_all(); 33153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov } 332fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 333fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema //wait 3347adb1a0b7ba0f6c2ef0c3e44979a382314f0ab0cAlexey Polyudov if (mPollThread.joinable()) { 3357adb1a0b7ba0f6c2ef0c3e44979a382314f0ab0cAlexey Polyudov mPollThread.join(); 3367adb1a0b7ba0f6c2ef0c3e44979a382314f0ab0cAlexey Polyudov } 337fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 33853d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov //wait 33953d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov if (mAppThread.joinable()) { 34053d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov mAppThread.join(); 34153d7164c9e25b417d597c102d92bae3050c149aeAlexey Polyudov } 342fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema //cleanup 34396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ::close(mThreadClosingPipe[0]); 34496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ::close(mThreadClosingPipe[1]); 3455db89a8cfee5a45e9fb8185d4c08d0f7c9d2c9a2Alexey Polyudov ::close(mFd); 34696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 34796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov reset(); 348fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 349fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return 0; 350fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 351fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 35296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovint NanoHub::doSubscribeMessages(uint32_t hub_id, context_hub_callback *cbk, void *cookie) 353fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 35496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (hub_id) { 355fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return -ENODEV; 35696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 35796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 3587adb1a0b7ba0f6c2ef0c3e44979a382314f0ab0cAlexey Polyudov std::lock_guard<std::mutex> _l(mLock); 35996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov int ret = 0; 360fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 361fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (!mMsgCbkFunc && !cbk) { //we're off and staying off - do nothing 362fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 363fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGD("staying off"); 36496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else if (cbk && mMsgCbkFunc) { //new callback but staying on 365fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 366fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGD("staying on"); 36796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else if (mMsgCbkFunc) { //we were on but turning off 368fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 369fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGD("turning off"); 370fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 37196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ret = closeHub(); 37296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else if (cbk) { //we're turning on 373fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 374fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGD("turning on"); 37596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ret = openHub(); 376fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 377fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 378fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema mMsgCbkFunc = cbk; 379fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema mMsgCbkData = cookie; 380fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 381fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return ret; 382fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 383fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 38496177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovint NanoHub::doSendToNanohub(uint32_t hub_id, const hub_message_t *msg) 385fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 38696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov if (hub_id) { 387fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return -ENODEV; 38896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } 389fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 39096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov int ret = 0; 3917adb1a0b7ba0f6c2ef0c3e44979a382314f0ab0cAlexey Polyudov std::lock_guard<std::mutex> _l(mLock); 392fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 393fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema if (!mMsgCbkFunc) { 394fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGW("refusing to send a message when nobody around to get a reply!"); 395fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = -EIO; 39696177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else { 397fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov if (!msg || !msg->message) { 398fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGW("not sending invalid message 1"); 399fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = -EINVAL; 40096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else if (get_hub_info()->os_app_name == msg->app_name) { 401fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov //messages to the "system" app are special - hal handles them 40270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (messageTracingEnabled()) { 40370ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov dumpBuffer("APP -> HAL", msg->app_name, msg->message_type, msg->message, msg->message_len); 40470ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov } 40596177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov ret = SystemComm::handleTx(msg); 4060ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov } else if (msg->message_len > MAX_RX_PACKET) { 407fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ALOGW("not sending invalid message 2"); 408fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema ret = -EINVAL; 40996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov } else { 41070ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov if (messageTracingEnabled()) { 4110ce3d053b7c75d4759e047653868cb1079e32252Alexey Polyudov dumpBuffer("APP -> DEV", msg->app_name, msg->message_type, msg->message, msg->message_len); 41270ab6271e35d78b86a68b00b663c177230697fb5Alexey Polyudov } 413672acdeb3c63987a9a778dbcc84fe74e0fb4a5dbStephen Hines ret = doSendToDevice(msg->app_name, msg->message, msg->message_len, msg->message_type); 414fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 415fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema } 416fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 417fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return ret; 418fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 419fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 42096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovstatic int hal_get_hubs(context_hub_module_t*, const context_hub_t ** list) 421fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema{ 422fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema *list = get_hub_info(); 423fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 424fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema return 1; /* we have one hub */ 425fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema} 426fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 42796177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov}; // namespace nanohub 42896177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 42996177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov}; // namespace android 43096177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov 43196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudovcontext_hub_module_t HAL_MODULE_INFO_SYM = { 432fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .common = { 433fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .tag = HARDWARE_MODULE_TAG, 434fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .module_api_version = CONTEXT_HUB_DEVICE_API_VERSION_1_0, 435fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .hal_api_version = HARDWARE_HAL_API_VERSION, 436fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .id = CONTEXT_HUB_MODULE_ID, 437fd9c05e653cf9de55c72afb85af849f5d932e1a1Alexey Polyudov .name = "Nanohub HAL", 438fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema .author = "Google", 439fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema }, 440fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema 44196177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov .get_hubs = android::nanohub::hal_get_hubs, 44296177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov .subscribe_messages = android::nanohub::NanoHub::subscribeMessages, 44396177b03ab7915a8abce9fcb14f61be2edab918fAlexey Polyudov .send_message = android::nanohub::NanoHub::sendToNanohub, 444fe2188fa871f1d4470378c004ad44d4216202641Ben Fennema}; 445