btsnoop.cc revision 16b3e929c25490ec05d7935f18962720ec7c96a4
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 213e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6Etan Cohen#include <arpa/inet.h> 22a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <errno.h> 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <fcntl.h> 244394720415f45db5caea73e1a05351ff98601fe0Pavlin Radoslavov#include <inttypes.h> 25933926c92e1378cc76bc9c149107e670c4872d4eScott James Remnant#include <limits.h> 26933926c92e1378cc76bc9c149107e670c4872d4eScott James Remnant#include <netinet/in.h> 27611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <stdbool.h> 28a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <stdio.h> 29a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <stdlib.h> 303e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6Etan Cohen#include <string.h> 315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/stat.h> 32a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati#include <sys/time.h> 335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <unistd.h> 345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 35db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "bt_types.h" 3689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "hci/include/btsnoop.h" 3789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "hci/include/btsnoop_mem.h" 38fbbd42b1fc1aae7a106f46275ab1fd86452cce78Zach Johnson#include "hci_layer.h" 3944802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 409891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson#include "stack_config.h" 415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 42611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatitypedef enum { 43611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati kCommandPacket = 1, 44611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati kAclPacket = 2, 45611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati kScoPacket = 3, 46611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati kEventPacket = 4 47a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati} packet_type_t; 485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 49a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati// Epoch in microseconds since 01/01/0000. 50a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavatistatic const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL; 515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 525ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic const stack_config_t* stack_config; 53f1d68e95f34921361dced60b1b53e3fef8401f03Kim Schulz 549891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic int logfile_fd = INVALID_FD; 559891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic bool module_started; 569891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic bool is_logging; 579891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic bool logging_enabled_via_api; 589891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 599891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// TODO(zachoverflow): merge btsnoop and btsnoop_net together 60a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_open(); 61a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_close(); 625ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonvoid btsnoop_net_write(const void* data, size_t length); 635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 64796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic void btsnoop_write_packet(packet_type_t type, uint8_t* packet, 655ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bool is_received); 669891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic void update_logging(); 679891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 689891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Module lifecycle functions 699891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 705ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic future_t* start_up(void) { 719891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson module_started = true; 729891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson update_logging(); 739891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 749891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return NULL; 759891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 769891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 775ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic future_t* shut_down(void) { 789891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson module_started = false; 799891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson update_logging(); 809891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 819891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return NULL; 829891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 839891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 84b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin RadoslavovEXPORT_SYMBOL extern const module_t btsnoop_module = { 855ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .name = BTSNOOP_MODULE, 865ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .init = NULL, 875ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .start_up = start_up, 885ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .shut_down = shut_down, 895ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .clean_up = NULL, 905ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson .dependencies = {STACK_CONFIG_MODULE, NULL}}; 919891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 929891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Interface functions 939891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 949891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic void set_api_wants_to_log(bool value) { 959891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson logging_enabled_via_api = value; 969891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson update_logging(); 979891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 989891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 995ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void capture(const BT_HDR* buffer, bool is_received) { 100796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset); 1019891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 10289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach btsnoop_mem_capture(buffer); 10389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 1045ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (logfile_fd == INVALID_FD) return; 1059891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1069891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson switch (buffer->event & MSG_EVT_MASK) { 1079891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_HC_TO_STACK_HCI_EVT: 1089891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson btsnoop_write_packet(kEventPacket, p, false); 1099891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson break; 1109891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_HC_TO_STACK_HCI_ACL: 1119891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_STACK_TO_HC_HCI_ACL: 1129891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson btsnoop_write_packet(kAclPacket, p, is_received); 1139891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson break; 1149891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_HC_TO_STACK_HCI_SCO: 1159891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_STACK_TO_HC_HCI_SCO: 1169891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson btsnoop_write_packet(kScoPacket, p, is_received); 1179891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson break; 1189891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson case MSG_STACK_TO_HC_HCI_CMD: 1199891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson btsnoop_write_packet(kCommandPacket, p, true); 1209891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson break; 1219891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson } 1229891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 1239891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1245ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic const btsnoop_t interface = {set_api_wants_to_log, capture}; 1259891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1265ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst btsnoop_t* btsnoop_get_interface() { 1279891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson stack_config = stack_config_get_interface(); 1289891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return &interface; 1299891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 1309891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1319891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson// Internal functions 1329891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1331192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestrostatic uint64_t btsnoop_timestamp(void) { 1341192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro struct timeval tv; 1351192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro gettimeofday(&tv, NULL); 1361192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro 1371192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro // Timestamp is in microseconds. 1387dc4051b584bb056940afebda9d8ad3a48c046c3Ben YoungTae Kim uint64_t timestamp = tv.tv_sec; 1397dc4051b584bb056940afebda9d8ad3a48c046c3Ben YoungTae Kim timestamp *= (uint64_t)1000000ULL; 1401192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro timestamp += tv.tv_usec; 1411192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro timestamp += BTSNOOP_EPOCH_DELTA; 1421192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro return timestamp; 1431192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro} 1441192df9f7e709b9d9508ac86cbf5099a3a7ffa0eTucker Sylvestro 1459891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonstatic void update_logging() { 1465ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bool should_log = module_started && (logging_enabled_via_api || 1475ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson stack_config->get_btsnoop_turned_on()); 1489891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1495ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (should_log == is_logging) return; 1509891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1519891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson is_logging = should_log; 1529891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson if (should_log) { 1535ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson const char* log_path = stack_config->get_btsnoop_log_path(); 15404bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson 15504bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson // Save the old log if configured to do so 15604bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson if (stack_config->get_btsnoop_should_save_last()) { 15704bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson char last_log_path[PATH_MAX]; 1584394720415f45db5caea73e1a05351ff98601fe0Pavlin Radoslavov snprintf(last_log_path, PATH_MAX, "%s.%" PRIu64, log_path, 1594394720415f45db5caea73e1a05351ff98601fe0Pavlin Radoslavov btsnoop_timestamp()); 16004bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson if (!rename(log_path, last_log_path) && errno != ENOENT) 1615ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__, 1625ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson log_path, last_log_path, strerror(errno)); 16304bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson } 1649891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 16512aeda148b39f82d07733ad5c3eafcc9264707a1Ajay Panicker mode_t prevmask = umask(0); 1665ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC, 1675ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 1689891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson if (logfile_fd == INVALID_FD) { 1695ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path, 1705ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 17104bb236d873005ccb5950cb8e8f1f348499e032eZach Johnson is_logging = false; 17212aeda148b39f82d07733ad5c3eafcc9264707a1Ajay Panicker umask(prevmask); 1739891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return; 1749891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson } 17512aeda148b39f82d07733ad5c3eafcc9264707a1Ajay Panicker umask(prevmask); 1769891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1779891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson write(logfile_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16); 17895b9bc0e533545a14cf12877c72e0d96ab4370fdSrinu Jella btsnoop_net_open(); 1799891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson } else { 1805ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (logfile_fd != INVALID_FD) close(logfile_fd); 1819891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 1829891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson logfile_fd = INVALID_FD; 1839891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson btsnoop_net_close(); 1849891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson } 1859891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson} 1869891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 187796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachtypedef struct { 188796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t length_original; 189796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t length_captured; 190796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t flags; 191796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t dropped_packets; 192796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint64_t timestamp; 193796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint8_t type; 194796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach} __attribute__((__packed__)) btsnoop_header_t; 195796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach 196796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic uint64_t htonll(uint64_t ll) { 19716b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov const uint32_t l = 1; 19816b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov if (*(reinterpret_cast<const uint8_t*>(&l)) == 1) 19916b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 | 20016b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov htonl(ll >> 32); 20116b3e929c25490ec05d7935f18962720ec7c96a4Pavlin Radoslavov 202796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach return ll; 203a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati} 204a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati 205796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbachstatic void btsnoop_write_packet(packet_type_t type, uint8_t* packet, 2065ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bool is_received) { 207796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t length_he = 0; 208796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach uint32_t flags = 0; 209796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach 210a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati switch (type) { 211a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati case kCommandPacket: 212a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati length_he = packet[2] + 4; 213a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati flags = 2; 214a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati break; 215a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati case kAclPacket: 216a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati length_he = (packet[3] << 8) + packet[2] + 5; 217a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati flags = is_received; 218a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati break; 219a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati case kScoPacket: 220a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati length_he = packet[2] + 4; 221a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati flags = is_received; 222a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati break; 223a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati case kEventPacket: 224a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati length_he = packet[1] + 3; 225a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati flags = 3; 226a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati break; 227a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati } 228a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati 229796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach btsnoop_header_t header; 230796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.length_original = htonl(length_he); 231796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.length_captured = header.length_original; 232796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.flags = htonl(flags); 233796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.dropped_packets = 0; 234796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.timestamp = htonll(btsnoop_timestamp()); 235796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach header.type = type; 236796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach 237796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach btsnoop_net_write(&header, sizeof(btsnoop_header_t)); 238796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach btsnoop_net_write(packet, length_he - 1); 239796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach 240796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach if (logfile_fd != INVALID_FD) { 241796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach iovec iov[] = {{&header, sizeof(btsnoop_header_t)}, 242796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach {reinterpret_cast<void*>(packet), length_he - 1}}; 243796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach TEMP_FAILURE_RETRY(writev(logfile_fd, iov, 2)); 244796523d32d5478b63d9a545ec6a4e26207742b0cAndre Eisenbach } 245a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati} 246