1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 #include <stdint.h> 17 #include <arpa/inet.h> 18 #include <sys/types.h> 19 #include <sys/socket.h> 20 21 #include <utils/StrongPointer.h> 22 #include <utils/UniquePtr.h> 23 24 #include "audio/Buffer.h" 25 #include "Log.h" 26 #include "audio/AudioProtocol.h" 27 28 29 bool AudioProtocol::sendCommand(AudioParam& param) 30 { 31 mBuffer[0] = htonl(mCommand); 32 mBuffer[1] = 0; 33 return sendData((char*)mBuffer, 8); 34 } 35 36 bool AudioProtocol::handleReply(const uint32_t* data, AudioParam* param) 37 { 38 if (!checkHeaderId(data, mCommand)) { 39 return false; 40 } 41 if (data[1] != 0) { // no endian change for 0 42 LOGE("error in reply %d", ntohl(data[1])); 43 return false; 44 } 45 if (data[2] != 0) { 46 LOGE("payload length %d not zero", ntohl(data[2])); 47 return false; 48 } 49 return true; 50 } 51 52 bool AudioProtocol::handleReplyHeader(ClientSocket& socket, uint32_t* data, CommandId& id) 53 { 54 if (!socket.readData((char*)data, REPLY_HEADER_SIZE)) { 55 LOGE("handleReplyHeader cannot read"); 56 return false; 57 } 58 uint32_t command = ntohl(data[0]); 59 if ((command & 0xffff0000) != 0x43210000) { 60 LOGE("Wrong header %x %x", command, data[0]); 61 return false; 62 } 63 command = (command & 0xffff) | 0x12340000; // convert to id 64 if (command < ECmdStart) { 65 LOGE("Wrong header %x %x", command, data[0]); 66 return false; 67 } 68 if (command > (ECmdLast - 1)) { 69 LOGE("Wrong header %x %x", command, data[0]); 70 return false; 71 } 72 id = (CommandId)command; 73 LOGD("received reply with command %x", command); 74 return true; 75 } 76 77 bool AudioProtocol::checkHeaderId(const uint32_t* data, uint32_t command) 78 { 79 if (ntohl(data[0]) != ((command & 0xffff) | 0x43210000)) { 80 LOGE("wrong reply ID 0x%x", ntohl(data[0])); 81 return false; 82 } 83 return true; 84 } 85 86 87 /** 88 * param0 u32 data id 89 * param1 sp<Buffer> 90 */ 91 bool CmdDownload::sendCommand(AudioParam& param) 92 { 93 mBuffer[0] = htonl(ECmdDownload); 94 mBuffer[1] = htonl(4 + param.mBuffer->getSize()); 95 mBuffer[2] = htonl(param.mId); 96 if(!sendData((char*)mBuffer, 12)) { 97 return false; 98 } 99 return sendData(param.mBuffer->getData(), param.mBuffer->getSize()); 100 } 101 102 /** 103 * param0 u32 data id 104 * param1 u32 sampling rate 105 * param2 u32 mono / stereo(MSB) | mode 106 * param3 u32 volume 107 * param4 u32 repeat 108 */ 109 bool CmdStartPlayback::sendCommand(AudioParam& param) 110 { 111 mBuffer[0] = htonl(ECmdStartPlayback); 112 mBuffer[1] = htonl(20); 113 mBuffer[2] = htonl(param.mId); 114 mBuffer[3] = htonl(param.mSamplingF); 115 uint32_t mode = param.mStereo ? 0x80000000 : 0; 116 mode |= param.mMode; 117 mBuffer[4] = htonl(mode); 118 mBuffer[5] = htonl(param.mVolume); 119 mBuffer[6] = htonl(param.mNumberRepetition); 120 121 return sendData((char*)mBuffer, 28); 122 } 123 124 125 /** 126 * param0 u32 sampling rate 127 * param1 u32 mono / stereo(MSB) | mode 128 * param2 u32 volume 129 * param3 u32 samples 130 */ 131 bool CmdStartRecording::sendCommand(AudioParam& param) 132 { 133 mBuffer[0] = htonl(ECmdStartRecording); 134 mBuffer[1] = htonl(16); 135 mBuffer[2] = htonl(param.mSamplingF); 136 uint32_t mode = param.mStereo ? 0x80000000 : 0; 137 mode |= param.mMode; 138 mBuffer[3] = htonl(mode); 139 mBuffer[4] = htonl(param.mVolume); 140 uint32_t samples = param.mBuffer->getSize() / (param.mStereo ? 4 : 2); 141 mBuffer[5] = htonl(samples); 142 143 return sendData((char*)mBuffer, 24); 144 } 145 146 /** 147 * param0 sp<Buffer> 148 */ 149 bool CmdStartRecording::handleReply(const uint32_t* data, AudioParam* param) 150 { 151 if (!checkHeaderId(data, ECmdStartRecording)) { 152 return false; 153 } 154 if (data[1] != 0) { // no endian change for 0 155 LOGE("error in reply %d", ntohl(data[1])); 156 return false; 157 } 158 int len = ntohl(data[2]); 159 if (len > (int)param->mBuffer->getCapacity()) { 160 LOGE("received data %d exceeding buffer capacity %d", len, param->mBuffer->getCapacity()); 161 // read and throw away 162 //Buffer tempBuffer(len); 163 //readData(tempBuffer.getData(), len); 164 return false; 165 } 166 if (!readData(param->mBuffer->getData(), len)) { 167 return false; 168 } 169 LOGI("received data %d from device", len); 170 param->mBuffer->setHandled(len); 171 param->mBuffer->setSize(len); 172 return true; 173 } 174 175 bool CmdGetDeviceInfo::handleReply(const uint32_t* data, AudioParam* param) 176 { 177 if (!checkHeaderId(data, ECmdGetDeviceInfo)) { 178 return false; 179 } 180 if (data[1] != 0) { // no endian change for 0 181 LOGE("error in reply %d", ntohl(data[1])); 182 return false; 183 } 184 int len = ntohl(data[2]); 185 186 UniquePtr<char, DefaultDelete<char[]> > infoString(new char[len + 1]); 187 if (!readData(infoString.get(), len)) { 188 return false; 189 } 190 (infoString.get())[len] = 0; 191 LOGI("received data %s from device", infoString.get()); 192 android::String8* string = reinterpret_cast<android::String8*>(param->mExtra); 193 string->setTo(infoString.get(), len); 194 return true; 195 } 196 197 198