linuxOS_AP05/external/bluez-alsa/utils/hcitop.c

201 lines
4.6 KiB
C
Raw Normal View History

2025-06-02 05:59:07 +00:00
/*
* BlueALSA - hcitop.c
* Copyright (c) 2016-2018 Arkadiusz Bokowy
*
* This file is a part of bluez-alsa.
*
* This project is licensed under the terms of the MIT license.
*
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ncurses.h>
#include <bsd/stdlib.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
static const struct {
unsigned int bit;
char flag;
} hci_flags_map[] = {
{ HCI_UP, 'U' },
{ HCI_INIT, 'I' },
{ HCI_RUNNING, 'R' },
{ HCI_PSCAN, 'P' },
{ HCI_ISCAN, 'I' },
{ HCI_AUTH, 'A' },
{ HCI_ENCRYPT, 'E' },
{ HCI_INQUIRY, 'Q' },
{ HCI_RAW, 'X' },
};
static int get_devinfo(struct hci_dev_info di[HCI_MAX_DEV]) {
int i, num;
for (i = num = 0; i < HCI_MAX_DEV; i++)
if (hci_devinfo(i, &di[num]) == 0)
num++;
return num;
}
static unsigned int get_average_rate(unsigned int *array, size_t size) {
/* at least two points are required */
if (size < 2)
return 0;
unsigned int x = 0;
unsigned int y = 0;
size_t i;
size--;
i = size;
while (i--) {
int b = (array[i] - array[i + 1]) % size;
x += (array[i] - array[i + 1]) / size;
if (y >= size - b) {
y -= size - b;
x++;
}
else {
y += b;
}
}
return x + y / size;
}
static void sprint_hci_flags(char *str, unsigned int flags) {
size_t i;
for (i = 0; i < sizeof(hci_flags_map) / sizeof(*hci_flags_map); i++)
str[i] = hci_test_bit(hci_flags_map[i].bit, &flags) ? hci_flags_map[i].flag : ' ';
str[i] = '\0';
}
int main(int argc, char *argv[]) {
int opt;
const char *opts = "hVd:";
const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "delay", required_argument, NULL, 'd' },
{ 0, 0, 0, 0 },
};
int delay_sec = 1;
int delay_msec = 0;
while ((opt = getopt_long(argc, argv, opts, longopts, NULL)) != -1)
switch (opt) {
case 'h' /* --help */ :
printf("usage: %s [ -d sec ]\n"
" -h, --help\t\tprint this help and exit\n"
" -V, --version\t\tprint version and exit\n"
" -d, --delay=SEC\tdelay time interval\n",
argv[0]);
return EXIT_SUCCESS;
case 'V' /* --version */ :
printf("%s\n", PACKAGE_VERSION);
return EXIT_SUCCESS;
case 'd' /* --delay=SEC */ :
delay_sec = atoi(optarg);
delay_msec = (int)((atof(optarg) - delay_sec) * 10) * 100;
if (delay_sec < 0 || delay_msec < 0 || (delay_sec == 0 && delay_msec == 0)) {
fprintf(stderr, "%s: -d requires positive argument (max precision: 0.1)\n", argv[0]);
return EXIT_FAILURE;
}
break;
default:
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
return EXIT_FAILURE;
}
struct hci_dev_info devices[HCI_MAX_DEV];
unsigned int byte_rx[HCI_MAX_DEV][3];
unsigned int byte_tx[HCI_MAX_DEV][3];
size_t ii;
memset(byte_rx, 0, sizeof(byte_rx));
memset(byte_tx, 0, sizeof(byte_tx));
initscr();
cbreak();
noecho();
curs_set(0);
for (ii = 1;; ii++) {
const char *template_top = "%5s %9s %8s %8s %8s %8s";
const char *template_row = "%5s %9s %8s %8s %8s %8s";
int i, count;
attron(A_REVERSE);
mvprintw(0, 0, template_top, "HCI", "FLAGS", "RX", "TX", "RX/s", "TX/s");
attroff(A_REVERSE);
count = get_devinfo(devices);
for (i = 0; i < HCI_MAX_DEV; i++) {
/* shift historic data to the right by one sample */
memmove(&byte_rx[i][1], &byte_rx[i][0], sizeof(*byte_rx) - sizeof(**byte_rx));
memmove(&byte_tx[i][1], &byte_tx[i][0], sizeof(*byte_tx) - sizeof(**byte_tx));
if (i >= count)
continue;
char flags[sizeof(hci_flags_map) / sizeof(*hci_flags_map) + 1];
sprint_hci_flags(flags, devices[i].flags);
byte_rx[i][0] = devices[i].stat.byte_rx;
byte_tx[i][0] = devices[i].stat.byte_tx;
const size_t ii_max = sizeof(*byte_rx) / sizeof(**byte_rx);
const size_t samples = ii < ii_max ? ii : ii_max;
unsigned int rate_rx = get_average_rate(byte_rx[i], samples);
unsigned int rate_tx = get_average_rate(byte_tx[i], samples);
rate_rx = rate_rx * 10 / (delay_sec * 10 + delay_msec / 100);
rate_tx = rate_tx * 10 / (delay_sec * 10 + delay_msec / 100);
char rx[7], rx_rate[9];
char tx[7], tx_rate[9];
humanize_number(rx, sizeof(rx), byte_rx[i][0], "B", HN_AUTOSCALE, 0);
humanize_number(tx, sizeof(tx), byte_tx[i][0], "B", HN_AUTOSCALE, 0);
humanize_number(rx_rate, sizeof(rx_rate), rate_rx, "B", HN_AUTOSCALE, 0);
humanize_number(tx_rate, sizeof(tx_rate), rate_tx, "B", HN_AUTOSCALE, 0);
mvprintw(i + 1, 0, template_row, devices[i].name, flags, rx, tx, rx_rate, tx_rate);
}
timeout(delay_sec * 1000 + delay_msec);
if (getch() == 'q')
break;
}
endwin();
return EXIT_SUCCESS;
}