packet_stream.cc revision 265316f78ca1077216c9d87b2de096894fdd5ee5
1// 2// Copyright 2015 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of 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, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#define LOG_TAG "packet_stream" 18 19#include "packet_stream.h" 20 21#include "base/logging.h" 22 23#include <errno.h> 24#include <unistd.h> 25 26#include "osi/include/log.h" 27 28namespace test_vendor_lib { 29 30std::unique_ptr<CommandPacket> PacketStream::ReceiveCommand(int fd) const { 31 vector<uint8_t> header; 32 vector<uint8_t> params_size; 33 vector<uint8_t> payload; 34 35 if (!ReceiveAll(header, CommandPacket::kCommandHeaderSize, fd)) { 36 LOG_ERROR(LOG_TAG, "Error: receiving command header."); 37 return std::unique_ptr<CommandPacket>(nullptr); 38 } 39 40 if (!ReceiveAll(params_size, 1, fd)) { 41 LOG_ERROR(LOG_TAG, "Error: receiving params size."); 42 return std::unique_ptr<CommandPacket>(nullptr); 43 } 44 45 if (!ReceiveAll(payload, params_size[0], fd)) { 46 LOG_ERROR(LOG_TAG, "Error: receiving command payload."); 47 return std::unique_ptr<CommandPacket>(nullptr); 48 } 49 return std::unique_ptr<CommandPacket>(new CommandPacket(header, payload)); 50} 51 52serial_data_type_t PacketStream::ReceivePacketType(int fd) const { 53 LOG_INFO(LOG_TAG, "Receiving packet type."); 54 55 vector<uint8_t> raw_type_octet; 56 57 if (!ReceiveAll(raw_type_octet, 1, fd)) { 58 // TODO(dennischeng): Proper error handling. 59 LOG_ERROR(LOG_TAG, "Error: Could not receive packet type."); 60 } 61 62 // Check that the type octet received is in the valid range, i.e. the packet 63 // must be a command or data packet. 64 const serial_data_type_t type = 65 static_cast<serial_data_type_t>(raw_type_octet[0]); 66 if (!ValidateTypeOctet(type)) { 67 // TODO(dennischeng): Proper error handling. 68 LOG_ERROR(LOG_TAG, "Error: Received invalid packet type."); 69 } 70 return type; 71} 72 73bool PacketStream::SendEvent(const EventPacket& event, int fd) const { 74 LOG_INFO( 75 LOG_TAG, "Sending event with event code: 0x%04X", event.GetEventCode()); 76 LOG_INFO( 77 LOG_TAG, "Sending event with size: %zu octets", event.GetPacketSize()); 78 79 if (!SendAll({static_cast<uint8_t>(event.GetType())}, 1, fd)) { 80 LOG_ERROR(LOG_TAG, "Error: Could not send event type."); 81 return false; 82 } 83 84 if (!SendAll(event.GetHeader(), event.GetHeaderSize(), fd)) { 85 LOG_ERROR(LOG_TAG, "Error: Could not send event header."); 86 return false; 87 } 88 89 if (!SendAll(event.GetPayload(), event.GetPayloadSize(), fd)) { 90 LOG_ERROR(LOG_TAG, "Error: Could not send event payload."); 91 return false; 92 } 93 return true; 94} 95 96bool PacketStream::ValidateTypeOctet(serial_data_type_t type) const { 97 LOG_INFO(LOG_TAG, "Signal octet is 0x%02X.", type); 98 // The only types of packets that should be received from the HCI are command 99 // packets and data packets. 100 return (type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO); 101} 102 103bool PacketStream::ReceiveAll(vector<uint8_t>& destination, 104 size_t num_octets_to_receive, 105 int fd) const { 106 destination.resize(num_octets_to_receive); 107 size_t octets_remaining = num_octets_to_receive; 108 while (octets_remaining > 0) { 109 const int num_octets_received = 110 read(fd, 111 &destination[num_octets_to_receive - octets_remaining], 112 octets_remaining); 113 if (num_octets_received < 0) 114 return false; 115 octets_remaining -= num_octets_received; 116 } 117 return true; 118} 119 120bool PacketStream::SendAll(const vector<uint8_t>& source, 121 size_t num_octets_to_send, 122 int fd) const { 123 CHECK(source.size() >= num_octets_to_send); 124 size_t octets_remaining = num_octets_to_send; 125 while (octets_remaining > 0) { 126 const int num_octets_sent = write( 127 fd, &source[num_octets_to_send - octets_remaining], octets_remaining); 128 if (num_octets_sent < 0) 129 return false; 130 octets_remaining -= num_octets_sent; 131 } 132 return true; 133} 134 135} // namespace test_vendor_lib 136