Skip to content

Commit

Permalink
Add custom bluedroid
Browse files Browse the repository at this point in the history
  • Loading branch information
nopy committed Feb 5, 2012
1 parent 5e8b47f commit 2cea6b7
Show file tree
Hide file tree
Showing 2 changed files with 295 additions and 0 deletions.
2 changes: 2 additions & 0 deletions BoardConfig.mk
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ BOARD_USE_USB_MASS_STORAGE_SWITCH := true
# custom recovery ui
BOARD_CUSTOM_RECOVERY_KEYMAPPING := ../../device/toshiba/betelgeuse/recovery/recovery_ui.c

BOARD_CUSTOM_BLUEDROID := ../../../device/toshiba/betelgeuse/bluedroid/bluetooth.c

# Wifi related defines
#CONFIG_DRIVER_AR6000 := true
#BOARD_WPA_SUPPLICANT_DRIVER := AR6000
Expand Down
293 changes: 293 additions & 0 deletions bluedroid/bluetooth.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define LOG_TAG "bluedroid"

#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#include <cutils/log.h>
#include <cutils/properties.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#include <bluedroid/bluetooth.h>

#ifndef HCI_DEV_ID
#define HCI_DEV_ID 0
#endif

#define HCID_START_DELAY_SEC 3
#define HCID_STOP_DELAY_USEC 500000

#define MIN(x,y) (((x)<(y))?(x):(y))


static const char *sysrfkill = "/sys/class/rfkill";
static char *rfkill_state_path = NULL;


static int init_rfkill() {
char path[64];
char buf[16];
int fd;
int sz;
DIR *sysdir;
struct dirent *entry;

if ((sysdir = opendir(sysrfkill)) == NULL) {
LOGE("opendir failed: %s (%d)\n", strerror(errno), errno);
return -1;
}

while((entry = readdir(sysdir)) != NULL) {
if (!(strcmp(".", entry->d_name) && strcmp("..", entry->d_name)))
continue;
snprintf(path, sizeof(path), "%s/%s/type", sysrfkill, entry->d_name);
fd = open(path, O_RDONLY);
if (fd < 0) {
LOGW("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
continue;
}
sz = read(fd, &buf, sizeof(buf));
close(fd);
if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) {
char *sp;
if (asprintf(&sp, "/sys/class/rfkill/%s/state", entry->d_name) > 0) {
LOGI("found bluetooth at %s\n", path);
rfkill_state_path = sp;
break;
}
}
}

closedir(sysdir);
return rfkill_state_path ? 0 : -1;
}

static int check_bluetooth_power() {
int fd = -1;
int ret = -1;
char buffer;

if (rfkill_state_path == NULL) {
if (init_rfkill()) goto out;
}

fd = open(rfkill_state_path, O_RDONLY);
if (fd < 0) {
LOGE("open(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
errno);
goto out;
}
if (read(fd, &buffer, 1) != 1) {
LOGE("read(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
errno);
goto out;
}

switch (buffer) {
case '1':
ret = 1;
break;
case '0':
ret = 0;
break;
}

out:
if (fd >= 0) close(fd);
return ret;
}

static int set_bluetooth_power(int on) {
int fd = -1;
int ret = check_bluetooth_power();
const char buffer = (on ? '1' : '0');

if (ret < 0)
return ret;
else if (ret == on)
return 0;

fd = open(rfkill_state_path, O_WRONLY);
if (fd < 0) {
LOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
strerror(errno), errno);
goto out;
}
if (write(fd, &buffer, 1) != 1) {
LOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
errno);
goto out;
}
ret = 0;

out:
if (fd >= 0) close(fd);
return ret;
}

static int create_hci_sock() {
int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (sk < 0) {
LOGE("Failed to create bluetooth hci socket: %s (%d)",
strerror(errno), errno);
}
return sk;
}

int bt_enable() {
LOGV(__FUNCTION__);

int ret = -1;
int hci_sock = -1;
int attempt;

LOGI("Starting hciattach daemon");
if (property_set("ctl.start", "hciattach") < 0) {
LOGE("Failed to start hciattach");
set_bluetooth_power(0);
goto out;
}

// Try for 10 seconds, this can only succeed once hciattach has sent the
// firmware and then turned on hci device via HCIUARTSETPROTO ioctl
for (attempt = 10; attempt > 0; --attempt) {
int res = set_bluetooth_power(1);
sleep(1);
if (res < 0) {
bt_disable();
continue;
}
hci_sock = create_hci_sock();
if (hci_sock < 0) goto out;

if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID))
break;

LOGE("ioctl failed: %s (%d)", strerror(errno), errno);
close(hci_sock);
usleep(10000); // 10 ms retry delay
}
if (attempt == 0) {
LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
set_bluetooth_power(0);
goto out;
}

LOGI("Starting bluetoothd deamon");
if (property_set("ctl.start", "bluetoothd") < 0) {
LOGE("Failed to start bluetoothd");
set_bluetooth_power(0);
goto out;
}
sleep(HCID_START_DELAY_SEC);

ret = 0;

out:
if (hci_sock >= 0) close(hci_sock);
return ret;
}

int bt_disable() {
LOGV(__FUNCTION__);

int ret = -1;
int hci_sock = -1;

LOGI("Stopping bluetoothd deamon");
if (property_set("ctl.stop", "bluetoothd") < 0) {
LOGE("Error stopping bluetoothd");
goto out;
}
usleep(HCID_STOP_DELAY_USEC);

hci_sock = create_hci_sock();
if (hci_sock < 0) goto out;
ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID);

LOGI("Stopping hciattach deamon");
if (property_set("ctl.stop", "hciattach") < 0) {
LOGE("Error stopping hciattach");
goto out;
}

if (set_bluetooth_power(0) < 0) {
goto out;
}
ret = 0;

out:
free(rfkill_state_path);
rfkill_state_path = NULL;

if (hci_sock >= 0) close(hci_sock);
return ret;
}

int bt_is_enabled() {
LOGV(__FUNCTION__);

int hci_sock = -1;
int ret = -1;
struct hci_dev_info dev_info;


// Check power first
ret = check_bluetooth_power();
if (ret == -1 || ret == 0) goto out;

ret = -1;

// Power is on, now check if the HCI interface is up
hci_sock = create_hci_sock();
if (hci_sock < 0) goto out;

dev_info.dev_id = HCI_DEV_ID;
if (ioctl(hci_sock, HCIGETDEVINFO, (void *)&dev_info) < 0) {
ret = 0;
goto out;
}

ret = hci_test_bit(HCI_UP, &dev_info.flags);

out:
if (hci_sock >= 0) close(hci_sock);
return ret;
}

int ba2str(const bdaddr_t *ba, char *str) {
return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
}

int str2ba(const char *str, bdaddr_t *ba) {
int i;
for (i = 5; i >= 0; i--) {
ba->b[i] = (uint8_t) strtoul(str, &str, 16);
str++;
}
return 0;
}

0 comments on commit 2cea6b7

Please sign in to comment.