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 <UniquePtr.h>
22 #include <utils/StrongPointer.h>
23
24 #include "audio/Buffer.h"
25 #include "Log.h"
26 #include "audio/AudioProtocol.h"
27
28
sendCommand(AudioParam & param)29 bool AudioProtocol::sendCommand(AudioParam& param)
30 {
31 mBuffer[0] = htonl(mCommand);
32 mBuffer[1] = 0;
33 return sendData((char*)mBuffer, 8);
34 }
35
handleReply(const uint32_t * data,AudioParam * param)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
handleReplyHeader(ClientSocket & socket,uint32_t * data,CommandId & id)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
checkHeaderId(const uint32_t * data,uint32_t command)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 */
sendCommand(AudioParam & param)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 */
sendCommand(AudioParam & param)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 */
sendCommand(AudioParam & param)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 */
handleReply(const uint32_t * data,AudioParam * param)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
handleReply(const uint32_t * data,AudioParam * param)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