17a192d395ce5d7e5945afa684146d5b0abc53480mbligh/* 27a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Copyright 2007, Intel Corporation 37a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 47a192d395ce5d7e5945afa684146d5b0abc53480mbligh * This file is part of PowerTOP 57a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 67a192d395ce5d7e5945afa684146d5b0abc53480mbligh * This program file is free software; you can redistribute it and/or modify it 77a192d395ce5d7e5945afa684146d5b0abc53480mbligh * under the terms of the GNU General Public License as published by the 87a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Free Software Foundation; version 2 of the License. 97a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 107a192d395ce5d7e5945afa684146d5b0abc53480mbligh * This program is distributed in the hope that it will be useful, but WITHOUT 117a192d395ce5d7e5945afa684146d5b0abc53480mbligh * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 127a192d395ce5d7e5945afa684146d5b0abc53480mbligh * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 137a192d395ce5d7e5945afa684146d5b0abc53480mbligh * for more details. 147a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 157a192d395ce5d7e5945afa684146d5b0abc53480mbligh * You should have received a copy of the GNU General Public License 167a192d395ce5d7e5945afa684146d5b0abc53480mbligh * along with this program in a file named COPYING; if not, write to the 177a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Free Software Foundation, Inc., 187a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 51 Franklin Street, Fifth Floor, 197a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Boston, MA 02110-1301 USA 207a192d395ce5d7e5945afa684146d5b0abc53480mbligh * 217a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Authors: 227a192d395ce5d7e5945afa684146d5b0abc53480mbligh * Arjan van de Ven <arjan@linux.intel.com> 237a192d395ce5d7e5945afa684146d5b0abc53480mbligh */ 247a192d395ce5d7e5945afa684146d5b0abc53480mbligh 257a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <unistd.h> 267a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <stdio.h> 277a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <stdlib.h> 287a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <string.h> 297a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <stdint.h> 307a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <sys/types.h> 317a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <dirent.h> 327a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <sys/types.h> 337a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <sys/socket.h> 347a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <sys/ioctl.h> 357a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include <errno.h> 367a192d395ce5d7e5945afa684146d5b0abc53480mbligh 377a192d395ce5d7e5945afa684146d5b0abc53480mbligh#include "powertop.h" 387a192d395ce5d7e5945afa684146d5b0abc53480mbligh 397a192d395ce5d7e5945afa684146d5b0abc53480mbligh 407a192d395ce5d7e5945afa684146d5b0abc53480mbligh/* structure definitions copied from include/net/bluetooth/hci.h from the 2.6.20 kernel */ 417a192d395ce5d7e5945afa684146d5b0abc53480mbligh#define HCIGETDEVINFO _IOR('H', 211, int) 427a192d395ce5d7e5945afa684146d5b0abc53480mbligh#define BTPROTO_HCI 1 437a192d395ce5d7e5945afa684146d5b0abc53480mbligh 447a192d395ce5d7e5945afa684146d5b0abc53480mbligh#define __u16 uint16_t 457a192d395ce5d7e5945afa684146d5b0abc53480mbligh#define __u8 uint8_t 467a192d395ce5d7e5945afa684146d5b0abc53480mbligh#define __u32 uint32_t 477a192d395ce5d7e5945afa684146d5b0abc53480mbligh 487a192d395ce5d7e5945afa684146d5b0abc53480mblightypedef struct { 497a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u8 b[6]; 507a192d395ce5d7e5945afa684146d5b0abc53480mbligh} __attribute__((packed)) bdaddr_t; 517a192d395ce5d7e5945afa684146d5b0abc53480mbligh 527a192d395ce5d7e5945afa684146d5b0abc53480mblighstruct hci_dev_stats { 537a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 err_rx; 547a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 err_tx; 557a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 cmd_tx; 567a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 evt_rx; 577a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 acl_tx; 587a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 acl_rx; 597a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 sco_tx; 607a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 sco_rx; 617a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 byte_rx; 627a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 byte_tx; 637a192d395ce5d7e5945afa684146d5b0abc53480mbligh}; 647a192d395ce5d7e5945afa684146d5b0abc53480mbligh 657a192d395ce5d7e5945afa684146d5b0abc53480mbligh 667a192d395ce5d7e5945afa684146d5b0abc53480mblighstruct hci_dev_info { 677a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u16 dev_id; 687a192d395ce5d7e5945afa684146d5b0abc53480mbligh char name[8]; 697a192d395ce5d7e5945afa684146d5b0abc53480mbligh 707a192d395ce5d7e5945afa684146d5b0abc53480mbligh bdaddr_t bdaddr; 717a192d395ce5d7e5945afa684146d5b0abc53480mbligh 727a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 flags; 737a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u8 type; 747a192d395ce5d7e5945afa684146d5b0abc53480mbligh 757a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u8 features[8]; 767a192d395ce5d7e5945afa684146d5b0abc53480mbligh 777a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 pkt_type; 787a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 link_policy; 797a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u32 link_mode; 807a192d395ce5d7e5945afa684146d5b0abc53480mbligh 817a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u16 acl_mtu; 827a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u16 acl_pkts; 837a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u16 sco_mtu; 847a192d395ce5d7e5945afa684146d5b0abc53480mbligh __u16 sco_pkts; 857a192d395ce5d7e5945afa684146d5b0abc53480mbligh 867a192d395ce5d7e5945afa684146d5b0abc53480mbligh struct hci_dev_stats stat; 877a192d395ce5d7e5945afa684146d5b0abc53480mbligh}; 887a192d395ce5d7e5945afa684146d5b0abc53480mbligh 897a192d395ce5d7e5945afa684146d5b0abc53480mblighstatic int previous_bytes = -1; 907a192d395ce5d7e5945afa684146d5b0abc53480mbligh 917a192d395ce5d7e5945afa684146d5b0abc53480mblighvoid turn_bluetooth_off(void) 927a192d395ce5d7e5945afa684146d5b0abc53480mbligh{ 937a192d395ce5d7e5945afa684146d5b0abc53480mbligh system("/usr/sbin/hciconfig hci0 down &> /dev/null"); 947a192d395ce5d7e5945afa684146d5b0abc53480mbligh system("/sbin/rmmod hci_usb &> /dev/null"); 957a192d395ce5d7e5945afa684146d5b0abc53480mbligh} 967a192d395ce5d7e5945afa684146d5b0abc53480mbligh 977a192d395ce5d7e5945afa684146d5b0abc53480mblighvoid suggest_bluetooth_off(void) 987a192d395ce5d7e5945afa684146d5b0abc53480mbligh{ 997a192d395ce5d7e5945afa684146d5b0abc53480mbligh struct hci_dev_info devinfo; 1007a192d395ce5d7e5945afa684146d5b0abc53480mbligh FILE *file; 1017a192d395ce5d7e5945afa684146d5b0abc53480mbligh int fd; 1027a192d395ce5d7e5945afa684146d5b0abc53480mbligh int ret; 1037a192d395ce5d7e5945afa684146d5b0abc53480mbligh int thisbytes = 0; 1047a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1057a192d395ce5d7e5945afa684146d5b0abc53480mbligh /* first check if /sys/modules/bluetooth exists, if not, don't probe bluetooth because 1067a192d395ce5d7e5945afa684146d5b0abc53480mbligh it would trigger an autoload */ 1077a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1087a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (access("/sys/module/bluetooth",F_OK)) 1097a192d395ce5d7e5945afa684146d5b0abc53480mbligh return; 1107a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1117a192d395ce5d7e5945afa684146d5b0abc53480mbligh fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1127a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (fd < 0) 1137a192d395ce5d7e5945afa684146d5b0abc53480mbligh return; 1147a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1157a192d395ce5d7e5945afa684146d5b0abc53480mbligh memset(&devinfo, 0, sizeof(devinfo)); 1167a192d395ce5d7e5945afa684146d5b0abc53480mbligh strcpy(devinfo.name, "hci0"); 1177a192d395ce5d7e5945afa684146d5b0abc53480mbligh ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo); 1187a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (ret < 0) 1197a192d395ce5d7e5945afa684146d5b0abc53480mbligh goto out; 1207a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1217a192d395ce5d7e5945afa684146d5b0abc53480mbligh if ( (devinfo.flags & 1) == 0 && 1227a192d395ce5d7e5945afa684146d5b0abc53480mbligh access("/sys/module/hci_usb",F_OK)) /* interface down already */ 1237a192d395ce5d7e5945afa684146d5b0abc53480mbligh goto out; 1247a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1257a192d395ce5d7e5945afa684146d5b0abc53480mbligh thisbytes += devinfo.stat.byte_rx; 1267a192d395ce5d7e5945afa684146d5b0abc53480mbligh thisbytes += devinfo.stat.byte_tx; 1277a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1287a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (thisbytes != previous_bytes) 1297a192d395ce5d7e5945afa684146d5b0abc53480mbligh goto out; 1307a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1317a192d395ce5d7e5945afa684146d5b0abc53480mbligh /* now, also check for active connections */ 1327a192d395ce5d7e5945afa684146d5b0abc53480mbligh file = popen("/usr/bin/hcitool con 2> /dev/null", "r"); 1337a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (file) { 1347a192d395ce5d7e5945afa684146d5b0abc53480mbligh char line[2048]; 1357a192d395ce5d7e5945afa684146d5b0abc53480mbligh /* first line is standard header */ 1367a192d395ce5d7e5945afa684146d5b0abc53480mbligh fgets(line,2048,file); 1377a192d395ce5d7e5945afa684146d5b0abc53480mbligh memset(line, 0, 2048); 1387a192d395ce5d7e5945afa684146d5b0abc53480mbligh fgets(line, 2047, file); 1397a192d395ce5d7e5945afa684146d5b0abc53480mbligh pclose(file); 1407a192d395ce5d7e5945afa684146d5b0abc53480mbligh if (strlen(line)>0) 1417a192d395ce5d7e5945afa684146d5b0abc53480mbligh goto out; 1427a192d395ce5d7e5945afa684146d5b0abc53480mbligh } 1437a192d395ce5d7e5945afa684146d5b0abc53480mbligh 1447a192d395ce5d7e5945afa684146d5b0abc53480mbligh add_suggestion( _("Suggestion: Disable the unused bluetooth interface with the following command:\n" 1457a192d395ce5d7e5945afa684146d5b0abc53480mbligh " hciconfig hci0 down ; rmmod hci_usb\n" 1467a192d395ce5d7e5945afa684146d5b0abc53480mbligh "Bluetooth is a radio and consumes quite some power, and keeps USB busy as well.\n"), 40, 'B' , _(" B - Turn Bluetooth off "), turn_bluetooth_off); 1477a192d395ce5d7e5945afa684146d5b0abc53480mblighout: 1487a192d395ce5d7e5945afa684146d5b0abc53480mbligh previous_bytes = thisbytes; 1497a192d395ce5d7e5945afa684146d5b0abc53480mbligh close(fd); 1507a192d395ce5d7e5945afa684146d5b0abc53480mbligh return; 1517a192d395ce5d7e5945afa684146d5b0abc53480mbligh} 152