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 
ReceiveCommand(int fd) const32 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 
ReceivePacketType(int fd) const54 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 
SendEvent(std::unique_ptr<EventPacket> event,int fd) const73 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 
ValidateTypeOctet(serial_data_type_t type) const96 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 
ReceiveAll(vector<uint8_t> & destination,size_t num_octets_to_receive,int fd) const102 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 
SendAll(const vector<uint8_t> & source,size_t num_octets_to_send,int fd) const116 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