1611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// 2611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// Copyright (C) 2015 Google, Inc. 3611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// 4611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// Licensed under the Apache License, Version 2.0 (the "License"); 5611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// you may not use this file except in compliance with the License. 6611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// You may obtain a copy of the License at: 7611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// 8611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// http://www.apache.org/licenses/LICENSE-2.0 9611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// 10611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// Unless required by applicable law or agreed to in writing, software 11611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// distributed under the License is distributed on an "AS IS" BASIS, 12611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// See the License for the specific language governing permissions and 14611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// limitations under the License. 15611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// 16fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray 1749a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#define LOG_TAG "bt_bluetooth_host" 1849a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen 19e415c050edbb2710e8807dd2602c851412953268Scott James Remnant#include "service/ipc/linux_ipc_host.h" 20611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 21611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <errno.h> 22611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <stdio.h> 23611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <stdlib.h> 24611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/ioctl.h> 25611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/socket.h> 26611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/types.h> 27611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/un.h> 28611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <unistd.h> 29611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 30611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <algorithm> 31611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 32f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/base64.h> 33f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/strings/string_number_conversions.h> 34f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/strings/string_split.h> 35f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray 36611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include "osi/include/log.h" 37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "osi/include/osi.h" 38d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray#include "service/adapter.h" 39fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray 40d6a4b0c950f44d3eab34825880d26c19e362d22bArman Ugurayusing bluetooth::Adapter; 41fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Ugurayusing bluetooth::UUID; 42fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray 43fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Ugurayusing namespace bluetooth::gatt; 44611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 45611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgenamespace { 46611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 47611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// IPC API is according to: 48611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// https://docs.google.com/document/d/1eRnku-jAyVU1wGJsLT2CzWi0-8bs2g49s1b3FR_GApM 49611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetAdapterNameCommand[] = "set-device-name"; 50611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kCreateServiceCommand[] = "create-service"; 51611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kDestroyServiceCommand[] = "destroy-service"; 52611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kAddCharacteristicCommand[] = "add-characteristic"; 53611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetCharacteristicValueCommand[] = "set-characteristic-value"; 54611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetAdvertisementCommand[] = "set-advertisement"; 55611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetScanResponseCommand[] = "set-scan-response"; 56611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kStartServiceCommand[] = "start-service"; 57611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kStopServiceCommand[] = "stop-service"; 58611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kWriteCharacteristicCommand[] = "write-characteristic"; 59611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 60e415c050edbb2710e8807dd2602c851412953268Scott James Remnant// Useful values for indexing LinuxIPCHost::pfds_ 61611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// Not super general considering that we should be able to support 62e415c050edbb2710e8807dd2602c851412953268Scott James Remnant// many GATT FDs owned by one LinuxIPCHost. 63611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeenum { 64611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge kFdIpc = 0, 65611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge kFdGatt = 1, 66611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge kPossibleFds = 2, 67611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}; 68611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool TokenBool(const std::string& text) { return text == "true"; } 70611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 71611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} // namespace 72611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 73fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguraynamespace ipc { 74611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 75e415c050edbb2710e8807dd2602c851412953268Scott James RemnantLinuxIPCHost::LinuxIPCHost(int sockfd, Adapter* adapter) 76d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray : adapter_(adapter), pfds_(1, {sockfd, POLLIN, 0}) {} 77611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 78911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonLinuxIPCHost::~LinuxIPCHost() { close(pfds_[0].fd); } 79611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 80e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::EventLoop() { 81611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge while (true) { 82611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge int status = 83611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr)); 84611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (status < 1) { 85db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "ppoll error"); 86611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 87611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 88611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 89611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (pfds_[kFdIpc].revents && !OnMessage()) { 90611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 91611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 92611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (pfds_.size() == kPossibleFds && pfds_[kFdGatt].revents && 94611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge !OnGattWrite()) { 95611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 96611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 97611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 98611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 99611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 100611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 101e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetAdapterName(const std::string& name) { 102611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string decoded_data; 103611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge base::Base64Decode(name, &decoded_data); 104d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray return adapter_->SetName(decoded_data); 105611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 106611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 107e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnCreateService(const std::string& service_uuid) { 108fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray gatt_servers_[service_uuid] = std::unique_ptr<Server>(new Server); 109611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 110611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge int gattfd; 111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool status = 112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gatt_servers_[service_uuid]->Initialize(UUID(service_uuid), &gattfd); 113611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (!status) { 114db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Failed to initialize bluetooth"); 115611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 116611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 117611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge pfds_.resize(kPossibleFds); 118611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge pfds_[kFdGatt] = {gattfd, POLLIN, 0}; 119611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 120611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 121611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 122e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnDestroyService(const std::string& service_uuid) { 123611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge gatt_servers_.erase(service_uuid); 124611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge close(pfds_[1].fd); 125611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge pfds_.resize(1); 126611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 127611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 128611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 129e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnAddCharacteristic(const std::string& service_uuid, 130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& characteristic_uuid, 131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& control_uuid, 132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& options) { 13357d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko std::vector<std::string> option_tokens = base::SplitString( 13457d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko options, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 135611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 136611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge int properties_mask = 0; 137611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge int permissions_mask = 0; 138611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 139611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (std::find(option_tokens.begin(), option_tokens.end(), "notify") != 140611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge option_tokens.end()) { 141fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray permissions_mask |= kPermissionRead; 142fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray properties_mask |= kPropertyRead; 143fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray properties_mask |= kPropertyNotify; 144611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 145611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (std::find(option_tokens.begin(), option_tokens.end(), "read") != 146611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge option_tokens.end()) { 147fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray permissions_mask |= kPermissionRead; 148fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray properties_mask |= kPropertyRead; 149611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 150611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (std::find(option_tokens.begin(), option_tokens.end(), "write") != 151611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge option_tokens.end()) { 152fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray permissions_mask |= kPermissionWrite; 153fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray properties_mask |= kPropertyWrite; 154611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 155611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 156611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (control_uuid.empty()) { 157611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge gatt_servers_[service_uuid]->AddCharacteristic( 158fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray UUID(characteristic_uuid), properties_mask, permissions_mask); 159611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } else { 160fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray gatt_servers_[service_uuid]->AddBlob(UUID(characteristic_uuid), 161fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray UUID(control_uuid), properties_mask, 162611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge permissions_mask); 163611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 164611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 165611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 166611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool LinuxIPCHost::OnSetCharacteristicValue( 168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& service_uuid, const std::string& characteristic_uuid, 169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& value) { 170611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string decoded_data; 171611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge base::Base64Decode(value, &decoded_data); 172611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end()); 173fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray gatt_servers_[service_uuid]->SetCharacteristicValue(UUID(characteristic_uuid), 174611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge blob_data); 175611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 176611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 177611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 178e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetAdvertisement(const std::string& service_uuid, 179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& advertise_uuids, 180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& advertise_data, 181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& manufacturer_data, 182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& transmit_name) { 183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson LOG_INFO(LOG_TAG, "%s: service:%s uuids:%s data:%s", __func__, 184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson service_uuid.c_str(), advertise_uuids.c_str(), 185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson advertise_data.c_str()); 186611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 18757d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko std::vector<std::string> advertise_uuid_tokens = base::SplitString( 18857d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko advertise_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 189611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 190fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray // string -> vector<UUID> 191fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray std::vector<UUID> ids; 192611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge for (const auto& uuid_token : advertise_uuid_tokens) 193611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge ids.emplace_back(uuid_token); 194611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 195611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string decoded_data; 196611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge base::Base64Decode(advertise_data, &decoded_data); 197aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(), 198aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_data.end()); 199aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge 200aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge base::Base64Decode(manufacturer_data, &decoded_data); 201aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(), 202aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_data.end()); 203aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge 204aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge gatt_servers_[service_uuid]->SetAdvertisement(ids, decoded_advertise_data, 205aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_manufacturer_data, 206611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge TokenBool(transmit_name)); 207611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 208611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 209611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 210e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetScanResponse(const std::string& service_uuid, 211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& scan_response_uuids, 212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& scan_response_data, 213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& manufacturer_data, 214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const std::string& transmit_name) { 21557d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko std::vector<std::string> scan_response_uuid_tokens = base::SplitString( 21657d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko scan_response_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 217611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 218fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray // string -> vector<UUID> 219fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray std::vector<UUID> ids; 220611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge for (const auto& uuid_token : scan_response_uuid_tokens) 221611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge ids.emplace_back(uuid_token); 222611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 223611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string decoded_data; 224611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge base::Base64Decode(scan_response_data, &decoded_data); 225aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(), 226aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_data.end()); 227aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge 228aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge base::Base64Decode(manufacturer_data, &decoded_data); 229aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(), 230aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_data.end()); 231aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge 232aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge gatt_servers_[service_uuid]->SetScanResponse(ids, decoded_advertise_data, 233aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge decoded_manufacturer_data, 234611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge TokenBool(transmit_name)); 235611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 236611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 237611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 238e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnStartService(const std::string& service_uuid) { 239611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return gatt_servers_[service_uuid]->Start(); 240611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 241611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 242e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnStopService(const std::string& service_uuid) { 243611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return gatt_servers_[service_uuid]->Stop(); 244611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 245611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 246e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnMessage() { 247611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string ipc_msg; 248d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov ssize_t size; 249d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov 250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson OSI_NO_INTR(size = 251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC)); 252611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (-1 == size) { 253db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Error reading datagram size: %s", strerror(errno)); 254611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 255611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } else if (0 == size) { 256f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray LOG_INFO(LOG_TAG, "%s:%d: Connection closed", __func__, __LINE__); 257611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 258611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 259611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 260611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge ipc_msg.resize(size); 261d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size())); 262611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (-1 == size) { 263db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Error reading IPC: %s", strerror(errno)); 264611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 265611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } else if (0 == size) { 266f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray LOG_INFO(LOG_TAG, "%s:%d: Connection closed", __func__, __LINE__); 267611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 268611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 269611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 27057d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko std::vector<std::string> tokens = base::SplitString( 27157d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko ipc_msg, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 272611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge switch (tokens.size()) { 273611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge case 2: 274611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (tokens[0] == kSetAdapterNameCommand) 275611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return OnSetAdapterName(tokens[1]); 276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tokens[0] == kCreateServiceCommand) return OnCreateService(tokens[1]); 277611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (tokens[0] == kDestroyServiceCommand) 278611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return OnDestroyService(tokens[1]); 279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tokens[0] == kStartServiceCommand) return OnStartService(tokens[1]); 280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tokens[0] == kStopServiceCommand) return OnStopService(tokens[1]); 281611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge break; 282611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge case 4: 283611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (tokens[0] == kSetCharacteristicValueCommand) 284611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return OnSetCharacteristicValue(tokens[1], tokens[2], tokens[3]); 285611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge break; 286611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge case 5: 287611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (tokens[0] == kAddCharacteristicCommand) 288611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return OnAddCharacteristic(tokens[1], tokens[2], tokens[3], tokens[4]); 289611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge break; 290aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge case 6: 291aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge if (tokens[0] == kSetAdvertisementCommand) 292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4], 293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tokens[5]); 294aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge if (tokens[0] == kSetScanResponseCommand) 295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4], 296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tokens[5]); 297aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge break; 298611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge default: 299611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge break; 300611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 301611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 302db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Malformed IPC message: %s", ipc_msg.c_str()); 303611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 304611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 305611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 306e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnGattWrite() { 307fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray UUID::UUID128Bit id; 308d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov ssize_t r; 309d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov 310d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(r = read(pfds_[kFdGatt].fd, id.data(), id.size())); 311611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (r != id.size()) { 312db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Error reading GATT attribute ID"); 313611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 314611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 315611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 316611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::vector<uint8_t> value; 317611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge // TODO(icoolidge): Generalize this for multiple clients. 318611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge auto server = gatt_servers_.begin(); 319fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray server->second->GetCharacteristicValue(UUID(id), &value); 320611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge const std::string value_string(value.begin(), value.end()); 321611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string encoded_value; 322611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge base::Base64Encode(value_string, &encoded_value); 323611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 324611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge std::string transmit(kWriteCharacteristicCommand); 325611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge transmit += "|" + server->first; 326611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge transmit += "|" + base::HexEncode(id.data(), id.size()); 327611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge transmit += "|" + encoded_value; 328611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 329d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size())); 330611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge if (-1 == r) { 331db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "Error replying to IPC: %s", strerror(errno)); 332611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return false; 333611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge } 334611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 335611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge return true; 336611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge} 337611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge 338fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray} // namespace ipc 339