Home | History | Annotate | Download | only in audio
      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