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
23 #include "audio/Buffer.h"
24 #include "Log.h"
25 #include "audio/AudioProtocol.h"
26
27
sendCommand(AudioParam & param)28 bool AudioProtocol::sendCommand(AudioParam& param)
29 {
30 mBuffer[0] = htonl(mCommand);
31 mBuffer[1] = 0;
32 return sendData((char*)mBuffer, 8);
33 }
34
handleReply(const uint32_t * data,AudioParam * param)35 bool AudioProtocol::handleReply(const uint32_t* data, AudioParam* param)
36 {
37 if (!checkHeaderId(data, mCommand)) {
38 return false;
39 }
40 if (data[1] != 0) { // no endian change for 0
41 LOGE("error in reply %d", ntohl(data[1]));
42 return false;
43 }
44 if (data[2] != 0) {
45 LOGE("payload length %d not zero", ntohl(data[2]));
46 return false;
47 }
48 return true;
49 }
50
handleReplyHeader(ClientSocket & socket,uint32_t * data,CommandId & id)51 bool AudioProtocol::handleReplyHeader(ClientSocket& socket, uint32_t* data, CommandId& id)
52 {
53 if (!socket.readData((char*)data, REPLY_HEADER_SIZE)) {
54 LOGE("handleReplyHeader cannot read");
55 return false;
56 }
57 uint32_t command = ntohl(data[0]);
58 if ((command & 0xffff0000) != 0x43210000) {
59 LOGE("Wrong header %x %x", command, data[0]);
60 return false;
61 }
62 command = (command & 0xffff) | 0x12340000; // convert to id
63 if (command < ECmdStart) {
64 LOGE("Wrong header %x %x", command, data[0]);
65 return false;
66 }
67 if (command > (ECmdLast - 1)) {
68 LOGE("Wrong header %x %x", command, data[0]);
69 return false;
70 }
71 id = (CommandId)command;
72 LOGD("received reply with command %x", command);
73 return true;
74 }
75
checkHeaderId(const uint32_t * data,uint32_t command)76 bool AudioProtocol::checkHeaderId(const uint32_t* data, uint32_t command)
77 {
78 if (ntohl(data[0]) != ((command & 0xffff) | 0x43210000)) {
79 LOGE("wrong reply ID 0x%x", ntohl(data[0]));
80 return false;
81 }
82 return true;
83 }
84
85
86 /**
87 * param0 u32 data id
88 * param1 sp<Buffer>
89 */
sendCommand(AudioParam & param)90 bool CmdDownload::sendCommand(AudioParam& param)
91 {
92 mBuffer[0] = htonl(ECmdDownload);
93 mBuffer[1] = htonl(4 + param.mBuffer->getSize());
94 mBuffer[2] = htonl(param.mId);
95 if(!sendData((char*)mBuffer, 12)) {
96 return false;
97 }
98 return sendData(param.mBuffer->getData(), param.mBuffer->getSize());
99 }
100
101 /**
102 * param0 u32 data id
103 * param1 u32 sampling rate
104 * param2 u32 mono / stereo(MSB) | mode
105 * param3 u32 volume
106 * param4 u32 repeat
107 */
sendCommand(AudioParam & param)108 bool CmdStartPlayback::sendCommand(AudioParam& param)
109 {
110 mBuffer[0] = htonl(ECmdStartPlayback);
111 mBuffer[1] = htonl(20);
112 mBuffer[2] = htonl(param.mId);
113 mBuffer[3] = htonl(param.mSamplingF);
114 uint32_t mode = param.mStereo ? 0x80000000 : 0;
115 mode |= param.mMode;
116 mBuffer[4] = htonl(mode);
117 mBuffer[5] = htonl(param.mVolume);
118 mBuffer[6] = htonl(param.mNumberRepetition);
119
120 return sendData((char*)mBuffer, 28);
121 }
122
123
124 /**
125 * param0 u32 sampling rate
126 * param1 u32 mono / stereo(MSB) | mode
127 * param2 u32 volume
128 * param3 u32 samples
129 */
sendCommand(AudioParam & param)130 bool CmdStartRecording::sendCommand(AudioParam& param)
131 {
132 mBuffer[0] = htonl(ECmdStartRecording);
133 mBuffer[1] = htonl(16);
134 mBuffer[2] = htonl(param.mSamplingF);
135 uint32_t mode = param.mStereo ? 0x80000000 : 0;
136 mode |= param.mMode;
137 mBuffer[3] = htonl(mode);
138 mBuffer[4] = htonl(param.mVolume);
139 uint32_t samples = param.mBuffer->getSize() / (param.mStereo ? 4 : 2);
140 mBuffer[5] = htonl(samples);
141
142 return sendData((char*)mBuffer, 24);
143 }
144
145 /**
146 * param0 sp<Buffer>
147 */
handleReply(const uint32_t * data,AudioParam * param)148 bool CmdStartRecording::handleReply(const uint32_t* data, AudioParam* param)
149 {
150 if (!checkHeaderId(data, ECmdStartRecording)) {
151 return false;
152 }
153 if (data[1] != 0) { // no endian change for 0
154 LOGE("error in reply %d", ntohl(data[1]));
155 return false;
156 }
157 int len = ntohl(data[2]);
158 if (len > (int)param->mBuffer->getCapacity()) {
159 LOGE("received data %d exceeding buffer capacity %d", len, param->mBuffer->getCapacity());
160 // read and throw away
161 //Buffer tempBuffer(len);
162 //readData(tempBuffer.getData(), len);
163 return false;
164 }
165 if (!readData(param->mBuffer->getData(), len)) {
166 return false;
167 }
168 LOGI("received data %d from device", len);
169 param->mBuffer->setHandled(len);
170 param->mBuffer->setSize(len);
171 return true;
172 }
173
174
175
176
177