15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
39891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson *  Copyright (C) 2014 Google, Inc.
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1949120dc867c7818511b5afec461dfc97d17eef58Marie Janssen#define LOG_TAG "bt_snoop"
2049120dc867c7818511b5afec461dfc97d17eef58Marie Janssen
213060ec68f6b0340d79e4712c17dd86141d68a5c1Pavlin Radoslavov#include <mutex>
223060ec68f6b0340d79e4712c17dd86141d68a5c1Pavlin Radoslavov
233e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6Etan Cohen#include <arpa/inet.h>
24a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <errno.h>
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <fcntl.h>
264394720415f45db5caea73e1a05351ff98601fe0Pavlin Radoslavov#include <inttypes.h>
27933926c92e1378cc76bc9c149107e670c4872d4eScott James Remnant#include <limits.h>
28933926c92e1378cc76bc9c149107e670c4872d4eScott James Remnant#include <netinet/in.h>
29611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <stdbool.h>
30a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <stdio.h>
31a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <stdlib.h>
323e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6Etan Cohen#include <string.h>
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/stat.h>
34a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <sys/time.h>
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <unistd.h>
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
37db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "bt_types.h"
3889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "hci/include/btsnoop.h"
3989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "hci/include/btsnoop_mem.h"
40fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include "hci_layer.h"
4144802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h"
4221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#include "osi/include/properties.h"
43071b507ad4278ae1ad24a188144d18cddf1b7137Jack He#include "osi/include/time.h"
449891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson#include "stack_config.h"
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker// The number of of packets per btsnoop file before we rotate to the next
4721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker// file. As of right now there are two snoop files that are rotated through.
4821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker// The size can be dynamically configured by seting the relevant system
4921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker// property
5021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#define DEFAULT_BTSNOOP_SIZE 0xffff
5121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
5221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#define BTSNOOP_ENABLE_PROPERTY "persist.bluetooth.btsnoopenable"
5321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#define BTSNOOP_PATH_PROPERTY "persist.bluetooth.btsnooppath"
5421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#define DEFAULT_BTSNOOP_PATH "/data/misc/bluetooth/logs/btsnoop_hci.log"
5521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker#define BTSNOOP_MAX_PACKETS_PROPERTY "persist.bluetooth.btsnoopsize"
5621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
57611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatitypedef enum {
58611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati  kCommandPacket = 1,
59611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati  kAclPacket = 2,
60611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati  kScoPacket = 3,
61611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati  kEventPacket = 4
62a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati} packet_type_t;
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
64a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati// Epoch in microseconds since 01/01/0000.
65a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavatistatic const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
679891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic int logfile_fd = INVALID_FD;
683060ec68f6b0340d79e4712c17dd86141d68a5c1Pavlin Radoslavovstatic std::mutex btsnoop_mutex;
699891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
7021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic int32_t packets_per_file;
7121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic int32_t packet_counter;
7221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
739891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// TODO(zachoverflow): merge btsnoop and btsnoop_net together
74a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_open();
75a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_close();
765ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonvoid btsnoop_net_write(const void* data, size_t length);
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic void delete_btsnoop_files();
7921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic bool is_btsnoop_enabled();
8021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic char* get_btsnoop_log_path(char* log_path);
8121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic char* get_btsnoop_last_log_path(char* last_log_path, char* log_path);
8221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic void open_next_snoop_file();
83796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
84071b507ad4278ae1ad24a188144d18cddf1b7137Jack He                                 bool is_received, uint64_t timestamp_us);
859891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
869891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Module lifecycle functions
879891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
885ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic future_t* start_up(void) {
8921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  std::lock_guard<std::mutex> lock(btsnoop_mutex);
9021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
9121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (!is_btsnoop_enabled()) {
9221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    delete_btsnoop_files();
9321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  } else {
9421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    open_next_snoop_file();
953f122786c51d318c8acb3e1759866846393ffbd2Jack He    packets_per_file = osi_property_get_int32(BTSNOOP_MAX_PACKETS_PROPERTY,
963f122786c51d318c8acb3e1759866846393ffbd2Jack He                                              DEFAULT_BTSNOOP_SIZE);
9721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    btsnoop_net_open();
9821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  }
999891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1009891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  return NULL;
1019891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson}
1029891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1035ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic future_t* shut_down(void) {
10421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  std::lock_guard<std::mutex> lock(btsnoop_mutex);
10521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
10621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (!is_btsnoop_enabled()) {
10721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    delete_btsnoop_files();
10821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  }
10921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
11021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (logfile_fd != INVALID_FD) close(logfile_fd);
11121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  logfile_fd = INVALID_FD;
11221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
11321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  btsnoop_net_close();
1149891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1159891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  return NULL;
1169891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson}
1179891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
118b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin RadoslavovEXPORT_SYMBOL extern const module_t btsnoop_module = {
1195ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .name = BTSNOOP_MODULE,
1205ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .init = NULL,
1215ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .start_up = start_up,
1225ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .shut_down = shut_down,
1235ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .clean_up = NULL,
1245ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    .dependencies = {STACK_CONFIG_MODULE, NULL}};
1259891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1269891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Interface functions
1275ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void capture(const BT_HDR* buffer, bool is_received) {
128796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset);
1299891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1303060ec68f6b0340d79e4712c17dd86141d68a5c1Pavlin Radoslavov  std::lock_guard<std::mutex> lock(btsnoop_mutex);
131071b507ad4278ae1ad24a188144d18cddf1b7137Jack He  uint64_t timestamp_us = time_gettimeofday_us();
132071b507ad4278ae1ad24a188144d18cddf1b7137Jack He  btsnoop_mem_capture(buffer, timestamp_us);
13389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
1345ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  if (logfile_fd == INVALID_FD) return;
1359891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1369891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  switch (buffer->event & MSG_EVT_MASK) {
1379891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_HC_TO_STACK_HCI_EVT:
138071b507ad4278ae1ad24a188144d18cddf1b7137Jack He      btsnoop_write_packet(kEventPacket, p, false, timestamp_us);
1399891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson      break;
1409891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_HC_TO_STACK_HCI_ACL:
1419891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_STACK_TO_HC_HCI_ACL:
142071b507ad4278ae1ad24a188144d18cddf1b7137Jack He      btsnoop_write_packet(kAclPacket, p, is_received, timestamp_us);
1439891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson      break;
1449891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_HC_TO_STACK_HCI_SCO:
1459891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_STACK_TO_HC_HCI_SCO:
146071b507ad4278ae1ad24a188144d18cddf1b7137Jack He      btsnoop_write_packet(kScoPacket, p, is_received, timestamp_us);
1479891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson      break;
1489891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    case MSG_STACK_TO_HC_HCI_CMD:
149071b507ad4278ae1ad24a188144d18cddf1b7137Jack He      btsnoop_write_packet(kCommandPacket, p, true, timestamp_us);
1509891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson      break;
1519891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  }
1529891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson}
1539891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
15421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic const btsnoop_t interface = {capture};
1559891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1565ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst btsnoop_t* btsnoop_get_interface() {
1579891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  return &interface;
1589891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson}
1599891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
1609891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Internal functions
16121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic void delete_btsnoop_files() {
16221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  LOG_VERBOSE(LOG_TAG, "Deleting snoop log if it exists");
16321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  char log_path[PROPERTY_VALUE_MAX];
16421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
16521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  get_btsnoop_log_path(log_path);
16621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  get_btsnoop_last_log_path(last_log_path, log_path);
16721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  remove(log_path);
16821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  remove(last_log_path);
16921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker}
1709891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
17121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic bool is_btsnoop_enabled() {
17221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  char btsnoop_enabled[PROPERTY_VALUE_MAX] = {0};
17321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  osi_property_get(BTSNOOP_ENABLE_PROPERTY, btsnoop_enabled, "false");
17421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  return strncmp(btsnoop_enabled, "true", 4) == 0;
17521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker}
17604bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson
17721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic char* get_btsnoop_log_path(char* btsnoop_path) {
17821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  osi_property_get(BTSNOOP_PATH_PROPERTY, btsnoop_path, DEFAULT_BTSNOOP_PATH);
17921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  return btsnoop_path;
18021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker}
1819891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
18221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic char* get_btsnoop_last_log_path(char* last_log_path,
18321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker                                       char* btsnoop_path) {
18421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  snprintf(last_log_path, PROPERTY_VALUE_MAX + sizeof(".last"), "%s.last",
18521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker           btsnoop_path);
18621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  return last_log_path;
18721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker}
1889891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
18921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panickerstatic void open_next_snoop_file() {
19021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  packet_counter = 0;
1919891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
19221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (logfile_fd != INVALID_FD) {
19321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    close(logfile_fd);
1949891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson    logfile_fd = INVALID_FD;
1959891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson  }
19621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
19721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  char log_path[PROPERTY_VALUE_MAX];
19821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
19921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  get_btsnoop_log_path(log_path);
20021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  get_btsnoop_last_log_path(last_log_path, log_path);
20121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
20221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (!rename(log_path, last_log_path) && errno != ENOENT)
20321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__,
20421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker              log_path, last_log_path, strerror(errno));
20521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
20621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  mode_t prevmask = umask(0);
20721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC,
20821ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker                    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
20921ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  umask(prevmask);
21021ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  if (logfile_fd == INVALID_FD) {
21121ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path,
21221ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker              strerror(errno));
21321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    return;
21421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  }
21521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
21621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker  write(logfile_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16);
2179891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson}
2189891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson
219796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachtypedef struct {
220796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t length_original;
221796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t length_captured;
222796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t flags;
223796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t dropped_packets;
224796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint64_t timestamp;
225796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint8_t type;
226796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach} __attribute__((__packed__)) btsnoop_header_t;
227796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach
228796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic uint64_t htonll(uint64_t ll) {
22916b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov  const uint32_t l = 1;
23016b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov  if (*(reinterpret_cast<const uint8_t*>(&l)) == 1)
23116b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov    return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 |
23216b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov           htonl(ll >> 32);
23316b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov
234796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  return ll;
235a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati}
236a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati
237796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
238071b507ad4278ae1ad24a188144d18cddf1b7137Jack He                                 bool is_received, uint64_t timestamp_us) {
239796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t length_he = 0;
240796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  uint32_t flags = 0;
241796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach
242a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati  switch (type) {
243a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati    case kCommandPacket:
244a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      length_he = packet[2] + 4;
245a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      flags = 2;
246a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      break;
247a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati    case kAclPacket:
248a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      length_he = (packet[3] << 8) + packet[2] + 5;
249a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      flags = is_received;
250a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      break;
251a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati    case kScoPacket:
252a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      length_he = packet[2] + 4;
253a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      flags = is_received;
254a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      break;
255a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati    case kEventPacket:
256a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      length_he = packet[1] + 3;
257a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      flags = 3;
258a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati      break;
259a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati  }
260a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati
261796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  btsnoop_header_t header;
262796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  header.length_original = htonl(length_he);
263796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  header.length_captured = header.length_original;
264796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  header.flags = htonl(flags);
265796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  header.dropped_packets = 0;
266071b507ad4278ae1ad24a188144d18cddf1b7137Jack He  header.timestamp = htonll(timestamp_us + BTSNOOP_EPOCH_DELTA);
267796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  header.type = type;
268796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach
269796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  btsnoop_net_write(&header, sizeof(btsnoop_header_t));
270796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  btsnoop_net_write(packet, length_he - 1);
271796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach
272796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  if (logfile_fd != INVALID_FD) {
27321ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    packet_counter++;
27421ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    if (packet_counter > packets_per_file) {
27521ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker      open_next_snoop_file();
27621ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker    }
27721ae30a6e5512cc454aec823efbf445ed5e1e238Ajay Panicker
278796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach    iovec iov[] = {{&header, sizeof(btsnoop_header_t)},
279796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach                   {reinterpret_cast<void*>(packet), length_he - 1}};
280796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach    TEMP_FAILURE_RETRY(writev(logfile_fd, iov, 2));
281796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach  }
282a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati}
283