summaryrefslogtreecommitdiffstats
path: root/src/tuning/bluetooth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tuning/bluetooth.cpp')
-rw-r--r--src/tuning/bluetooth.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/tuning/bluetooth.cpp b/src/tuning/bluetooth.cpp
new file mode 100644
index 0000000..2958849
--- /dev/null
+++ b/src/tuning/bluetooth.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "../lib.h"
+#include "bluetooth.h"
+
+bt_tunable::bt_tunable(void) : tunable("", 1.0, _("Good"), _("Bad"), _("Unknown"))
+{
+ sprintf(desc, _("Bluetooth device interface status"));
+ pt_strcpy(toggle_bad, "/usr/sbin/hciconfig hci0 up &> /dev/null &");
+ pt_strcpy(toggle_good, "/usr/sbin/hciconfig hci0 down &> /dev/null");
+}
+
+
+
+/* structure definitions copied from include/net/bluetooth/hci.h from the 2.6.20 kernel */
+#define HCIGETDEVINFO _IOR('H', 211, int)
+#define BTPROTO_HCI 1
+
+#define __u16 uint16_t
+#define __u8 uint8_t
+#define __u32 uint32_t
+
+typedef struct {
+ __u8 b[6];
+} __attribute__((packed)) bdaddr_t;
+
+struct hci_dev_stats {
+ __u32 err_rx;
+ __u32 err_tx;
+ __u32 cmd_tx;
+ __u32 evt_rx;
+ __u32 acl_tx;
+ __u32 acl_rx;
+ __u32 sco_tx;
+ __u32 sco_rx;
+ __u32 byte_rx;
+ __u32 byte_tx;
+};
+
+
+struct hci_dev_info {
+ __u16 dev_id;
+ char name[8];
+
+ bdaddr_t bdaddr;
+
+ __u32 flags;
+ __u8 type;
+
+ __u8 features[8];
+
+ __u32 pkt_type;
+ __u32 link_policy;
+ __u32 link_mode;
+
+ __u16 acl_mtu;
+ __u16 acl_pkts;
+ __u16 sco_mtu;
+ __u16 sco_pkts;
+
+ struct hci_dev_stats stat;
+};
+
+static int previous_bytes = -1;
+static time_t last_check_time = 0;
+static int last_check_result;
+
+int bt_tunable::good_bad(void)
+{
+ struct hci_dev_info devinfo;
+ FILE *file = 0;
+ int fd;
+ int thisbytes = 0;
+ int ret;
+ int result = TUNE_GOOD;
+
+ fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0)
+ return TUNE_GOOD;
+
+ memset(&devinfo, 0, sizeof(devinfo));
+ strcpy(devinfo.name, "hci0");
+ ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo);
+ if (ret < 0)
+ goto out;
+
+ if ( (devinfo.flags & 1) == 0 &&
+ access("/sys/module/hci_usb",F_OK)) /* interface down already */
+ goto out;
+
+ thisbytes += devinfo.stat.byte_rx;
+ thisbytes += devinfo.stat.byte_tx;
+
+ /* device is active... so we need to leave it on */
+ if (thisbytes != previous_bytes)
+ goto out;
+
+
+ /* this check is expensive.. only do it once per minute */
+ if (time(NULL) - last_check_time > 60) {
+ last_check_result = TUNE_BAD;
+ /* now, also check for active connections */
+ file = popen("/usr/bin/hcitool con 2> /dev/null", "r");
+ if (file) {
+ char line[2048];
+ /* first line is standard header */
+ if (fgets(line, 2047, file) == NULL)
+ goto out;
+ memset(line, 0, 2048);
+ if (fgets(line, 2047, file) == NULL) {
+ result = last_check_result = TUNE_GOOD;
+ goto out;
+ }
+
+ if (strlen(line) > 0) {
+ result = last_check_result = TUNE_GOOD;
+ goto out;
+ }
+ }
+ last_check_time = time(NULL);
+ };
+
+ result = last_check_result;
+
+out:
+ previous_bytes = thisbytes;
+ if (file)
+ pclose(file);
+ close(fd);
+ return result;
+}
+
+void bt_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ if(system("/usr/sbin/hciconfig hci0 up &> /dev/null &"))
+ printf("System is not available\n");
+ return;
+ }
+ if(system("/usr/sbin/hciconfig hci0 down &> /dev/null"))
+ printf("System is not available\n");
+}
+
+const char *bt_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+ return toggle_good;
+}
+
+
+void add_bt_tunable(void)
+{
+ struct hci_dev_info devinfo;
+ class bt_tunable *bt;
+ int fd;
+ int ret;
+
+ /* first check if /sys/modules/bluetooth exists, if not, don't probe bluetooth because
+ it would trigger an autoload */
+
+// if (access("/sys/module/bluetooth",F_OK))
+// return;
+
+
+ /* check if hci0 exists */
+ fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0)
+ return;
+
+ memset(&devinfo, 0, sizeof(devinfo));
+ strcpy(devinfo.name, "hci0");
+ ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo);
+ close(fd);
+ if (ret < 0)
+ return;
+
+
+ bt = new class bt_tunable();
+ all_tunables.push_back(bt);
+}