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 28 using std::vector; 29 30 namespace test_vendor_lib { 31 32 std::unique_ptr<CommandPacket> PacketStream::ReceiveCommand(int fd) const { 33 vector<uint8_t> header; 34 vector<uint8_t> params_size; 35 vector<uint8_t> payload; 36 37 if (!ReceiveAll(header, CommandPacket::kCommandHeaderSize, fd)) { 38 LOG_ERROR(LOG_TAG, "Error: receiving command header."); 39 return std::unique_ptr<CommandPacket>(nullptr); 40 } 41 42 if (!ReceiveAll(params_size, 1, fd)) { 43 LOG_ERROR(LOG_TAG, "Error: receiving params size."); 44 return std::unique_ptr<CommandPacket>(nullptr); 45 } 46 47 if (!ReceiveAll(payload, params_size[0], fd)) { 48 LOG_ERROR(LOG_TAG, "Error: receiving command payload."); 49 return std::unique_ptr<CommandPacket>(nullptr); 50 } 51 return std::unique_ptr<CommandPacket>(new CommandPacket(header, payload)); 52 } 53 54 serial_data_type_t PacketStream::ReceivePacketType(int fd) const { 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 73 bool PacketStream::SendEvent(std::unique_ptr<EventPacket> event, int fd) const { 74 if (event->GetPayload()[0] != event->GetPayloadSize() - 1) 75 LOG_WARN(LOG_TAG, "Malformed event: 0x%04X, payload size %zu, reported %u", 76 event->GetEventCode(), event->GetPacketSize(), 77 event->GetPayload()[0]); 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 96 bool PacketStream::ValidateTypeOctet(serial_data_type_t type) const { 97 // The only types of packets that should be received from the HCI are command 98 // packets and data packets. 99 return (type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO); 100 } 101 102 bool PacketStream::ReceiveAll(vector<uint8_t>& destination, 103 size_t num_octets_to_receive, int fd) const { 104 destination.resize(num_octets_to_receive); 105 size_t octets_remaining = num_octets_to_receive; 106 while (octets_remaining > 0) { 107 const int num_octets_received = 108 read(fd, &destination[num_octets_to_receive - octets_remaining], 109 octets_remaining); 110 if (num_octets_received < 0) return false; 111 octets_remaining -= num_octets_received; 112 } 113 return true; 114 } 115 116 bool PacketStream::SendAll(const vector<uint8_t>& source, 117 size_t num_octets_to_send, int fd) const { 118 CHECK(source.size() >= num_octets_to_send); 119 size_t octets_remaining = num_octets_to_send; 120 while (octets_remaining > 0) { 121 const int num_octets_sent = write( 122 fd, &source[num_octets_to_send - octets_remaining], octets_remaining); 123 if (num_octets_sent < 0) return false; 124 octets_remaining -= num_octets_sent; 125 } 126 return true; 127 } 128 129 } // namespace test_vendor_lib 130