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