1 /* 2 * Copyright 2007, Intel Corporation 3 * 4 * This file is part of PowerTOP 5 * 6 * This program file is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program in a file named COPYING; if not, write to the 17 * Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301 USA 20 * 21 * Authors: 22 * Arjan van de Ven <arjan (at) linux.intel.com> 23 */ 24 25 #include <unistd.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <stdint.h> 30 #include <sys/types.h> 31 #include <dirent.h> 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <sys/ioctl.h> 35 #include <errno.h> 36 37 #include "powertop.h" 38 39 40 /* structure definitions copied from include/net/bluetooth/hci.h from the 2.6.20 kernel */ 41 #define HCIGETDEVINFO _IOR('H', 211, int) 42 #define BTPROTO_HCI 1 43 44 #define __u16 uint16_t 45 #define __u8 uint8_t 46 #define __u32 uint32_t 47 48 typedef struct { 49 __u8 b[6]; 50 } __attribute__((packed)) bdaddr_t; 51 52 struct hci_dev_stats { 53 __u32 err_rx; 54 __u32 err_tx; 55 __u32 cmd_tx; 56 __u32 evt_rx; 57 __u32 acl_tx; 58 __u32 acl_rx; 59 __u32 sco_tx; 60 __u32 sco_rx; 61 __u32 byte_rx; 62 __u32 byte_tx; 63 }; 64 65 66 struct hci_dev_info { 67 __u16 dev_id; 68 char name[8]; 69 70 bdaddr_t bdaddr; 71 72 __u32 flags; 73 __u8 type; 74 75 __u8 features[8]; 76 77 __u32 pkt_type; 78 __u32 link_policy; 79 __u32 link_mode; 80 81 __u16 acl_mtu; 82 __u16 acl_pkts; 83 __u16 sco_mtu; 84 __u16 sco_pkts; 85 86 struct hci_dev_stats stat; 87 }; 88 89 static int previous_bytes = -1; 90 91 void turn_bluetooth_off(void) 92 { 93 system("/usr/sbin/hciconfig hci0 down &> /dev/null"); 94 system("/sbin/rmmod hci_usb &> /dev/null"); 95 } 96 97 void suggest_bluetooth_off(void) 98 { 99 struct hci_dev_info devinfo; 100 FILE *file; 101 int fd; 102 int ret; 103 int thisbytes = 0; 104 105 /* first check if /sys/modules/bluetooth exists, if not, don't probe bluetooth because 106 it would trigger an autoload */ 107 108 if (access("/sys/module/bluetooth",F_OK)) 109 return; 110 111 fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 112 if (fd < 0) 113 return; 114 115 memset(&devinfo, 0, sizeof(devinfo)); 116 strcpy(devinfo.name, "hci0"); 117 ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo); 118 if (ret < 0) 119 goto out; 120 121 if ( (devinfo.flags & 1) == 0 && 122 access("/sys/module/hci_usb",F_OK)) /* interface down already */ 123 goto out; 124 125 thisbytes += devinfo.stat.byte_rx; 126 thisbytes += devinfo.stat.byte_tx; 127 128 if (thisbytes != previous_bytes) 129 goto out; 130 131 /* now, also check for active connections */ 132 file = popen("/usr/bin/hcitool con 2> /dev/null", "r"); 133 if (file) { 134 char line[2048]; 135 /* first line is standard header */ 136 fgets(line,2048,file); 137 memset(line, 0, 2048); 138 fgets(line, 2047, file); 139 pclose(file); 140 if (strlen(line)>0) 141 goto out; 142 } 143 144 add_suggestion( _("Suggestion: Disable the unused bluetooth interface with the following command:\n" 145 " hciconfig hci0 down ; rmmod hci_usb\n" 146 "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); 147 out: 148 previous_bytes = thisbytes; 149 close(fd); 150 return; 151 } 152