189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach/******************************************************************************
289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *
389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  Copyright (C) 2015 Google Inc.
489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *
589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  Licensed under the Apache License, Version 2.0 (the "License");
689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  you may not use this file except in compliance with the License.
789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  You may obtain a copy of the License at:
889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *
989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  http://www.apache.org/licenses/LICENSE-2.0
1089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *
1189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  Unless required by applicable law or agreed to in writing, software
1289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  distributed under the License is distributed on an "AS IS" BASIS,
1389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  See the License for the specific language governing permissions and
1589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *  limitations under the License.
1689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *
1789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach ******************************************************************************/
1889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
1989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include <stdio.h>
2089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include <string.h>
2189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include <time.h>
2289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
23873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach#include "btcore/include/bdaddr.h"
2489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "btif/include/btif_debug.h"
2589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "btif/include/btif_debug_conn.h"
2689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
2789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#define NUM_CONNECTION_EVENTS  16
28873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach#define TEMP_BUFFER_SIZE       30
2989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
3089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachtypedef struct conn_event_t {
3189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  uint64_t ts;
3289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  btif_debug_conn_state_t state;
3389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  bt_bdaddr_t bda;
3489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  tGATT_DISCONN_REASON disconnect_reason;
3589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} conn_event_t;
3689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
3789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstatic conn_event_t connection_events[NUM_CONNECTION_EVENTS];
3889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstatic uint8_t current_event = 0;
3989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
4089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstatic char *format_ts(const uint64_t ts, char *buffer, int len) {
4189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  const uint64_t ms = ts / 1000;
4289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  const time_t secs = ms / 1000;
4389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  struct tm *ptm = localtime(&secs);
4489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
45bd194901dbbd2abebfe2510a1e97bb8d3a75102bAjay Panicker  char tempbuff[20];
46bd194901dbbd2abebfe2510a1e97bb8d3a75102bAjay Panicker  strftime(tempbuff, sizeof(tempbuff), "%m-%d %H:%M:%S", ptm);
47bd194901dbbd2abebfe2510a1e97bb8d3a75102bAjay Panicker  snprintf(buffer, len, "%s.%03u", tempbuff, (uint16_t)(ms % 1000));
4889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
4989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  return buffer;
5089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}
5189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
5289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstatic char *format_state(const btif_debug_conn_state_t state) {
5389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  switch (state) {
5489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    case BTIF_DEBUG_CONNECTED:
5589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach      return "CONNECTED   ";
5689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    case BTIF_DEBUG_DISCONNECTED:
5789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach      return "DISCONNECTED";
5889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  }
5989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  return "UNKNOWN";
6089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}
6189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
6289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstatic void next_event() {
6389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  ++current_event;
6489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  if (current_event == NUM_CONNECTION_EVENTS)
6589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    current_event = 0;
6689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}
6789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
6889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachvoid btif_debug_conn_state(const bt_bdaddr_t bda, const btif_debug_conn_state_t state,
6989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    const tGATT_DISCONN_REASON disconnect_reason) {
7089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  next_event();
7189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
7289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  conn_event_t *evt = &connection_events[current_event];
7389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  evt->ts = btif_debug_ts();
7489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  evt->state = state;
7589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  evt->disconnect_reason = disconnect_reason;
7689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  memcpy(&evt->bda, &bda, sizeof(bt_bdaddr_t));
7789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}
7889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
7989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachvoid btif_debug_conn_dump(int fd) {
8089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  const uint8_t current_event_local = current_event; // Cache to avoid threading issues
8189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  uint8_t dump_event = current_event_local;
82873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach  char ts_buffer[TEMP_BUFFER_SIZE] = {0};
83873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach  char name_buffer[TEMP_BUFFER_SIZE] = {0};
8489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
8589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  dprintf(fd, "\nConnection Events:\n");
8689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  if (connection_events[dump_event].ts == 0)
8789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    dprintf(fd, "  None\n");
8889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
8989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  while (connection_events[dump_event].ts) {
9089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    conn_event_t *evt = &connection_events[dump_event];
91873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach    dprintf(fd, "  %s %s %s",
92873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach            format_ts(evt->ts, ts_buffer, sizeof(ts_buffer)),
9389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach            format_state(evt->state),
94873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach            bdaddr_to_string(&evt->bda, name_buffer, sizeof(name_buffer))
9589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach        );
96873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach    if (evt->state == BTIF_DEBUG_DISCONNECTED)
97873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach      dprintf(fd, " reason=%d", evt->disconnect_reason);
98873ca2f973321f67df845e8658ede02bf5d9ee0bAndre Eisenbach    dprintf(fd,"\n");
9989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
10089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    // Go to previous event; wrap if needed
10189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    if (dump_event > 0)
10289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach      --dump_event;
10389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    else
10489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach      dump_event = NUM_CONNECTION_EVENTS - 1;
10589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach
10689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    // Check if we dumped all events
10789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach    if (dump_event == current_event_local)
10889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach      break;
10989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach  }
11089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}
111