1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright (C) 2016 Steven Toth <stoth@kernellabs.com> 4bf215546Sopenharmony_ci * Copyright (C) 2016 Zodiac Inflight Innovations 5bf215546Sopenharmony_ci * All Rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci * the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci * of the Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci * 27bf215546Sopenharmony_ci **************************************************************************/ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#ifdef HAVE_GALLIUM_EXTRA_HUD 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci/* Purpose: Reading network interface RX/TX throughput per second, 32bf215546Sopenharmony_ci * displaying on the HUD. 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "hud/hud_private.h" 36bf215546Sopenharmony_ci#include "util/list.h" 37bf215546Sopenharmony_ci#include "util/os_time.h" 38bf215546Sopenharmony_ci#include "os/os_thread.h" 39bf215546Sopenharmony_ci#include "util/u_memory.h" 40bf215546Sopenharmony_ci#include "util/u_string.h" 41bf215546Sopenharmony_ci#include <stdio.h> 42bf215546Sopenharmony_ci#include <unistd.h> 43bf215546Sopenharmony_ci#include <dirent.h> 44bf215546Sopenharmony_ci#include <stdlib.h> 45bf215546Sopenharmony_ci#include <unistd.h> 46bf215546Sopenharmony_ci#include <inttypes.h> 47bf215546Sopenharmony_ci#include <sys/types.h> 48bf215546Sopenharmony_ci#include <sys/stat.h> 49bf215546Sopenharmony_ci#include <sys/socket.h> 50bf215546Sopenharmony_ci#include <sys/ioctl.h> 51bf215546Sopenharmony_ci#include <linux/wireless.h> 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistruct nic_info 54bf215546Sopenharmony_ci{ 55bf215546Sopenharmony_ci struct list_head list; 56bf215546Sopenharmony_ci int mode; 57bf215546Sopenharmony_ci char name[64]; 58bf215546Sopenharmony_ci uint64_t speedMbps; 59bf215546Sopenharmony_ci int is_wireless; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci char throughput_filename[128]; 62bf215546Sopenharmony_ci uint64_t last_time; 63bf215546Sopenharmony_ci uint64_t last_nic_bytes; 64bf215546Sopenharmony_ci}; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci/* TODO: We don't handle dynamic NIC arrival or removal. 67bf215546Sopenharmony_ci * Static globals specific to this HUD category. 68bf215546Sopenharmony_ci */ 69bf215546Sopenharmony_cistatic int gnic_count = 0; 70bf215546Sopenharmony_cistatic struct list_head gnic_list; 71bf215546Sopenharmony_cistatic mtx_t gnic_mutex = _MTX_INITIALIZER_NP; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic struct nic_info * 74bf215546Sopenharmony_cifind_nic_by_name(const char *n, int mode) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci list_for_each_entry(struct nic_info, nic, &gnic_list, list) { 77bf215546Sopenharmony_ci if (nic->mode != mode) 78bf215546Sopenharmony_ci continue; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci if (strcasecmp(nic->name, n) == 0) 81bf215546Sopenharmony_ci return nic; 82bf215546Sopenharmony_ci } 83bf215546Sopenharmony_ci return 0; 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistatic int 87bf215546Sopenharmony_ciget_file_value(const char *fname, uint64_t *value) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci FILE *fh = fopen(fname, "r"); 90bf215546Sopenharmony_ci if (!fh) 91bf215546Sopenharmony_ci return -1; 92bf215546Sopenharmony_ci if (fscanf(fh, "%" PRIu64 "", value) != 0) { 93bf215546Sopenharmony_ci /* Error */ 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci fclose(fh); 96bf215546Sopenharmony_ci return 0; 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic boolean 100bf215546Sopenharmony_ciget_nic_bytes(const char *fn, uint64_t *bytes) 101bf215546Sopenharmony_ci{ 102bf215546Sopenharmony_ci if (get_file_value(fn, bytes) < 0) 103bf215546Sopenharmony_ci return FALSE; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci return TRUE; 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic void 109bf215546Sopenharmony_ciquery_wifi_bitrate(const struct nic_info *nic, uint64_t *bitrate) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci int sockfd; 112bf215546Sopenharmony_ci struct iw_statistics stats; 113bf215546Sopenharmony_ci struct iwreq req; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci memset(&stats, 0, sizeof(stats)); 116bf215546Sopenharmony_ci memset(&req, 0, sizeof(req)); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci snprintf(req.ifr_name, sizeof(req.ifr_name), "%s", nic->name); 119bf215546Sopenharmony_ci req.u.data.pointer = &stats; 120bf215546Sopenharmony_ci req.u.data.flags = 1; 121bf215546Sopenharmony_ci req.u.data.length = sizeof(struct iw_statistics); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci /* Any old socket will do, and a datagram socket is pretty cheap */ 124bf215546Sopenharmony_ci if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 125bf215546Sopenharmony_ci fprintf(stderr, "Unable to create socket for %s\n", nic->name); 126bf215546Sopenharmony_ci return; 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (ioctl(sockfd, SIOCGIWRATE, &req) == -1) { 130bf215546Sopenharmony_ci fprintf(stderr, "Error performing SIOCGIWSTATS on %s\n", nic->name); 131bf215546Sopenharmony_ci close(sockfd); 132bf215546Sopenharmony_ci return; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci *bitrate = req.u.bitrate.value; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci close(sockfd); 137bf215546Sopenharmony_ci} 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_cistatic void 140bf215546Sopenharmony_ciquery_nic_rssi(const struct nic_info *nic, uint64_t *leveldBm) 141bf215546Sopenharmony_ci{ 142bf215546Sopenharmony_ci int sockfd; 143bf215546Sopenharmony_ci struct iw_statistics stats; 144bf215546Sopenharmony_ci struct iwreq req; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci memset(&stats, 0, sizeof(stats)); 147bf215546Sopenharmony_ci memset(&req, 0, sizeof(req)); 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci snprintf(req.ifr_name, sizeof(req.ifr_name), "%s", nic->name); 150bf215546Sopenharmony_ci req.u.data.pointer = &stats; 151bf215546Sopenharmony_ci req.u.data.flags = 1; 152bf215546Sopenharmony_ci req.u.data.length = sizeof(struct iw_statistics); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci if (nic->mode != NIC_RSSI_DBM) 155bf215546Sopenharmony_ci return; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci /* Any old socket will do, and a datagram socket is pretty cheap */ 158bf215546Sopenharmony_ci if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 159bf215546Sopenharmony_ci fprintf(stderr, "Unable to create socket for %s\n", nic->name); 160bf215546Sopenharmony_ci return; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci /* Perform the ioctl */ 164bf215546Sopenharmony_ci if (ioctl(sockfd, SIOCGIWSTATS, &req) == -1) { 165bf215546Sopenharmony_ci fprintf(stderr, "Error performing SIOCGIWSTATS on %s\n", nic->name); 166bf215546Sopenharmony_ci close(sockfd); 167bf215546Sopenharmony_ci return; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci *leveldBm = ((char) stats.qual.level * -1); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci close(sockfd); 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_cistatic void 175bf215546Sopenharmony_ciquery_nic_load(struct hud_graph *gr, struct pipe_context *pipe) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci /* The framework calls us at a regular but indefined period, 178bf215546Sopenharmony_ci * not once per second, compensate the statistics accordingly. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci struct nic_info *nic = gr->query_data; 182bf215546Sopenharmony_ci uint64_t now = os_time_get(); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci if (nic->last_time) { 185bf215546Sopenharmony_ci if (nic->last_time + gr->pane->period <= now) { 186bf215546Sopenharmony_ci switch (nic->mode) { 187bf215546Sopenharmony_ci case NIC_DIRECTION_RX: 188bf215546Sopenharmony_ci case NIC_DIRECTION_TX: 189bf215546Sopenharmony_ci { 190bf215546Sopenharmony_ci uint64_t bytes; 191bf215546Sopenharmony_ci get_nic_bytes(nic->throughput_filename, &bytes); 192bf215546Sopenharmony_ci uint64_t nic_mbps = 193bf215546Sopenharmony_ci ((bytes - nic->last_nic_bytes) / 1000000) * 8; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci float speedMbps = nic->speedMbps; 196bf215546Sopenharmony_ci float periodMs = gr->pane->period / 1000.0; 197bf215546Sopenharmony_ci float bits = nic_mbps; 198bf215546Sopenharmony_ci float period_factor = periodMs / 1000; 199bf215546Sopenharmony_ci float period_speed = speedMbps * period_factor; 200bf215546Sopenharmony_ci float pct = (bits / period_speed) * 100; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci /* Scaling bps with a narrow time period into a second, 203bf215546Sopenharmony_ci * potentially suffers from rounding errors at higher 204bf215546Sopenharmony_ci * periods. Eg 104%. Compensate. 205bf215546Sopenharmony_ci */ 206bf215546Sopenharmony_ci if (pct > 100) 207bf215546Sopenharmony_ci pct = 100; 208bf215546Sopenharmony_ci hud_graph_add_value(gr, (uint64_t) pct); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci nic->last_nic_bytes = bytes; 211bf215546Sopenharmony_ci } 212bf215546Sopenharmony_ci break; 213bf215546Sopenharmony_ci case NIC_RSSI_DBM: 214bf215546Sopenharmony_ci { 215bf215546Sopenharmony_ci uint64_t leveldBm = 0; 216bf215546Sopenharmony_ci query_nic_rssi(nic, &leveldBm); 217bf215546Sopenharmony_ci hud_graph_add_value(gr, leveldBm); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci break; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci nic->last_time = now; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci else { 226bf215546Sopenharmony_ci /* initialize */ 227bf215546Sopenharmony_ci switch (nic->mode) { 228bf215546Sopenharmony_ci case NIC_DIRECTION_RX: 229bf215546Sopenharmony_ci case NIC_DIRECTION_TX: 230bf215546Sopenharmony_ci get_nic_bytes(nic->throughput_filename, &nic->last_nic_bytes); 231bf215546Sopenharmony_ci break; 232bf215546Sopenharmony_ci case NIC_RSSI_DBM: 233bf215546Sopenharmony_ci break; 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci nic->last_time = now; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci} 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci/** 241bf215546Sopenharmony_ci * Create and initialize a new object for a specific network interface dev. 242bf215546Sopenharmony_ci * \param pane parent context. 243bf215546Sopenharmony_ci * \param nic_name logical block device name, EG. eth0. 244bf215546Sopenharmony_ci * \param mode query type (NIC_DIRECTION_RX/WR/RSSI) statistics. 245bf215546Sopenharmony_ci */ 246bf215546Sopenharmony_civoid 247bf215546Sopenharmony_cihud_nic_graph_install(struct hud_pane *pane, const char *nic_name, 248bf215546Sopenharmony_ci unsigned int mode) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci struct hud_graph *gr; 251bf215546Sopenharmony_ci struct nic_info *nic; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci int num_nics = hud_get_num_nics(0); 254bf215546Sopenharmony_ci if (num_nics <= 0) 255bf215546Sopenharmony_ci return; 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci nic = find_nic_by_name(nic_name, mode); 258bf215546Sopenharmony_ci if (!nic) 259bf215546Sopenharmony_ci return; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci gr = CALLOC_STRUCT(hud_graph); 262bf215546Sopenharmony_ci if (!gr) 263bf215546Sopenharmony_ci return; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci nic->mode = mode; 266bf215546Sopenharmony_ci if (nic->mode == NIC_DIRECTION_RX) { 267bf215546Sopenharmony_ci snprintf(gr->name, sizeof(gr->name), "%s-rx-%"PRId64"Mbps", nic->name, 268bf215546Sopenharmony_ci nic->speedMbps); 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci else if (nic->mode == NIC_DIRECTION_TX) { 271bf215546Sopenharmony_ci snprintf(gr->name, sizeof(gr->name), "%s-tx-%"PRId64"Mbps", nic->name, 272bf215546Sopenharmony_ci nic->speedMbps); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci else if (nic->mode == NIC_RSSI_DBM) 275bf215546Sopenharmony_ci snprintf(gr->name, sizeof(gr->name), "%s-rssi", nic->name); 276bf215546Sopenharmony_ci else { 277bf215546Sopenharmony_ci free(gr); 278bf215546Sopenharmony_ci return; 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci gr->query_data = nic; 282bf215546Sopenharmony_ci gr->query_new_value = query_nic_load; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci hud_pane_add_graph(pane, gr); 285bf215546Sopenharmony_ci hud_pane_set_max_value(pane, 100); 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cistatic int 289bf215546Sopenharmony_ciis_wireless_nic(const char *dirbase) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci struct stat stat_buf; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci /* Check if its a wireless card */ 294bf215546Sopenharmony_ci char fn[256]; 295bf215546Sopenharmony_ci snprintf(fn, sizeof(fn), "%s/wireless", dirbase); 296bf215546Sopenharmony_ci if (stat(fn, &stat_buf) == 0) 297bf215546Sopenharmony_ci return 1; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci return 0; 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic void 303bf215546Sopenharmony_ciquery_nic_bitrate(struct nic_info *nic, const char *dirbase) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci struct stat stat_buf; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci /* Check if its a wireless card */ 308bf215546Sopenharmony_ci char fn[256]; 309bf215546Sopenharmony_ci snprintf(fn, sizeof(fn), "%s/wireless", dirbase); 310bf215546Sopenharmony_ci if (stat(fn, &stat_buf) == 0) { 311bf215546Sopenharmony_ci /* we're a wireless nic */ 312bf215546Sopenharmony_ci query_wifi_bitrate(nic, &nic->speedMbps); 313bf215546Sopenharmony_ci nic->speedMbps /= 1000000; 314bf215546Sopenharmony_ci } 315bf215546Sopenharmony_ci else { 316bf215546Sopenharmony_ci /* Must be a wired nic */ 317bf215546Sopenharmony_ci snprintf(fn, sizeof(fn), "%s/speed", dirbase); 318bf215546Sopenharmony_ci get_file_value(fn, &nic->speedMbps); 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci} 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci/** 323bf215546Sopenharmony_ci * Initialize internal object arrays and display NIC HUD help. 324bf215546Sopenharmony_ci * \param displayhelp true if the list of detected devices should be 325bf215546Sopenharmony_ci displayed on the console. 326bf215546Sopenharmony_ci * \return number of detected network interface devices. 327bf215546Sopenharmony_ci */ 328bf215546Sopenharmony_ciint 329bf215546Sopenharmony_cihud_get_num_nics(bool displayhelp) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci struct dirent *dp; 332bf215546Sopenharmony_ci struct stat stat_buf; 333bf215546Sopenharmony_ci struct nic_info *nic; 334bf215546Sopenharmony_ci char name[64]; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci /* Return the number if network interfaces. */ 337bf215546Sopenharmony_ci mtx_lock(&gnic_mutex); 338bf215546Sopenharmony_ci if (gnic_count) { 339bf215546Sopenharmony_ci mtx_unlock(&gnic_mutex); 340bf215546Sopenharmony_ci return gnic_count; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci /* Scan /sys/block, for every object type we support, create and 344bf215546Sopenharmony_ci * persist an object to represent its different statistics. 345bf215546Sopenharmony_ci */ 346bf215546Sopenharmony_ci list_inithead(&gnic_list); 347bf215546Sopenharmony_ci DIR *dir = opendir("/sys/class/net/"); 348bf215546Sopenharmony_ci if (!dir) { 349bf215546Sopenharmony_ci mtx_unlock(&gnic_mutex); 350bf215546Sopenharmony_ci return 0; 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci while ((dp = readdir(dir)) != NULL) { 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci /* Avoid 'lo' and '..' and '.' */ 356bf215546Sopenharmony_ci if (strlen(dp->d_name) <= 2) 357bf215546Sopenharmony_ci continue; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci char basename[256]; 360bf215546Sopenharmony_ci snprintf(basename, sizeof(basename), "/sys/class/net/%s", dp->d_name); 361bf215546Sopenharmony_ci snprintf(name, sizeof(name), "%s/statistics/rx_bytes", basename); 362bf215546Sopenharmony_ci if (stat(name, &stat_buf) < 0) 363bf215546Sopenharmony_ci continue; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (!S_ISREG(stat_buf.st_mode)) 366bf215546Sopenharmony_ci continue; /* Not a regular file */ 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci int is_wireless = is_wireless_nic(basename); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* Add the RX object */ 371bf215546Sopenharmony_ci nic = CALLOC_STRUCT(nic_info); 372bf215546Sopenharmony_ci strcpy(nic->name, dp->d_name); 373bf215546Sopenharmony_ci snprintf(nic->throughput_filename, sizeof(nic->throughput_filename), 374bf215546Sopenharmony_ci "%s/statistics/rx_bytes", basename); 375bf215546Sopenharmony_ci nic->mode = NIC_DIRECTION_RX; 376bf215546Sopenharmony_ci nic->is_wireless = is_wireless; 377bf215546Sopenharmony_ci query_nic_bitrate(nic, basename); 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci list_addtail(&nic->list, &gnic_list); 380bf215546Sopenharmony_ci gnic_count++; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci /* Add the TX object */ 383bf215546Sopenharmony_ci nic = CALLOC_STRUCT(nic_info); 384bf215546Sopenharmony_ci strcpy(nic->name, dp->d_name); 385bf215546Sopenharmony_ci snprintf(nic->throughput_filename, 386bf215546Sopenharmony_ci sizeof(nic->throughput_filename), 387bf215546Sopenharmony_ci "/sys/class/net/%s/statistics/tx_bytes", dp->d_name); 388bf215546Sopenharmony_ci nic->mode = NIC_DIRECTION_TX; 389bf215546Sopenharmony_ci nic->is_wireless = is_wireless; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci query_nic_bitrate(nic, basename); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci list_addtail(&nic->list, &gnic_list); 394bf215546Sopenharmony_ci gnic_count++; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (nic->is_wireless) { 397bf215546Sopenharmony_ci /* RSSI Support */ 398bf215546Sopenharmony_ci nic = CALLOC_STRUCT(nic_info); 399bf215546Sopenharmony_ci strcpy(nic->name, dp->d_name); 400bf215546Sopenharmony_ci snprintf(nic->throughput_filename, 401bf215546Sopenharmony_ci sizeof(nic->throughput_filename), 402bf215546Sopenharmony_ci "/sys/class/net/%s/statistics/tx_bytes", dp->d_name); 403bf215546Sopenharmony_ci nic->mode = NIC_RSSI_DBM; 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci query_nic_bitrate(nic, basename); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci list_addtail(&nic->list, &gnic_list); 408bf215546Sopenharmony_ci gnic_count++; 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci closedir(dir); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci list_for_each_entry(struct nic_info, nic, &gnic_list, list) { 415bf215546Sopenharmony_ci char line[64]; 416bf215546Sopenharmony_ci snprintf(line, sizeof(line), " nic-%s-%s", 417bf215546Sopenharmony_ci nic->mode == NIC_DIRECTION_RX ? "rx" : 418bf215546Sopenharmony_ci nic->mode == NIC_DIRECTION_TX ? "tx" : 419bf215546Sopenharmony_ci nic->mode == NIC_RSSI_DBM ? "rssi" : "undefined", nic->name); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci puts(line); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci mtx_unlock(&gnic_mutex); 426bf215546Sopenharmony_ci return gnic_count; 427bf215546Sopenharmony_ci} 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci#endif /* HAVE_GALLIUM_EXTRA_HUD */ 430