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