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