1b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh/* 2b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 3b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * BlueZ - Bluetooth protocol stack for Linux 4b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 5b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org> 69a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly * Copyright (C) 2009 The Android Open Source Project 7b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 8b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * This program is free software; you can redistribute it and/or modify 9b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * it under the terms of the GNU General Public License as published by 10b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * the Free Software Foundation; either version 2 of the License, or 11b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * (at your option) any later version. 12b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 13b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * This program is distributed in the hope that it will be useful, 14b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * but WITHOUT ANY WARRANTY; without even the implied warranty of 15b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * GNU General Public License for more details. 17b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 18b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * You should have received a copy of the GNU General Public License 19b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * along with this program; if not, write to the Free Software 20b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * 22b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh */ 23b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh 249a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <unistd.h> 259a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <errno.h> 269a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <sys/ioctl.h> 279a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <sys/types.h> 289a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <sys/socket.h> 299a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 30b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh#include <private/android_filesystem_config.h> 31b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh#include <sys/prctl.h> 32b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh#include <linux/capability.h> 33b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh 349a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <bluetooth/bluetooth.h> 359a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#include <bluetooth/hci.h> 369a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 37b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh/* Set UID to bluetooth w/ CAP_NET_RAW, CAP_NET_ADMIN and CAP_NET_BIND_SERVICE 38b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh * (Android's init.rc does not yet support applying linux capabilities) */ 39b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganeshvoid android_set_aid_and_cap() { 40b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 41b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh setuid(AID_BLUETOOTH); 42b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh 43b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh struct __user_cap_header_struct header; 44b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh struct __user_cap_data_struct cap; 45b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh header.version = _LINUX_CAPABILITY_VERSION; 46b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh header.pid = 0; 47b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh cap.effective = cap.permitted = 1 << CAP_NET_RAW | 48b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh 1 << CAP_NET_ADMIN | 49b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh 1 << CAP_NET_BIND_SERVICE; 50b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh cap.inheritable = 0; 51b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh capset(&header, &cap); 52b99eacf38b92b116f3dbd270af01f3e1e91bc72cJaikumar Ganesh} 539a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 54810bd7416134e721c6b951d489cf0689cf08c111Nick Pellystatic int write_flush_timeout(int fd, uint16_t handle, 55810bd7416134e721c6b951d489cf0689cf08c111Nick Pelly unsigned int timeout_ms) { 56810bd7416134e721c6b951d489cf0689cf08c111Nick Pelly uint16_t timeout = (timeout_ms * 1000) / 625; // timeout units of 0.625ms 5782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly unsigned char hci_write_flush_cmd[] = { 5882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 0x01, // HCI command packet 5982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 0x28, 0x0C, // HCI_Write_Automatic_Flush_Timeout 6082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 0x04, // Length 6182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 0x00, 0x00, // Handle 6282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 0x00, 0x00, // Timeout 6382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly }; 6482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 6582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly hci_write_flush_cmd[4] = (uint8_t)handle; 6682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly hci_write_flush_cmd[5] = (uint8_t)(handle >> 8); 6782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly hci_write_flush_cmd[6] = (uint8_t)timeout; 6882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly hci_write_flush_cmd[7] = (uint8_t)(timeout >> 8); 6982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 7082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly int ret = write(fd, hci_write_flush_cmd, sizeof(hci_write_flush_cmd)); 7182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly if (ret < 0) { 7282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly error("write(): %s (%d)]", strerror(errno), errno); 7382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly return -1; 7482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly } else if (ret != sizeof(hci_write_flush_cmd)) { 7582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly error("write(): unexpected length %d", ret); 7682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly return -1; 7782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly } 7882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly return 0; 7982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly} 8082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly 819a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#ifdef BOARD_HAVE_BLUETOOTH_BCM 829a8383ad9ee9516756abeeb5081de9651a6294edNick Pellystatic int vendor_high_priority(int fd, uint16_t handle) { 839a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly unsigned char hci_sleep_cmd[] = { 849a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 0x01, // HCI command packet 859a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 0x57, 0xfc, // HCI_Write_High_Priority_Connection 869a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 0x02, // Length 879a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 0x00, 0x00 // Handle 889a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly }; 899a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 909a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly hci_sleep_cmd[4] = (uint8_t)handle; 919a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly hci_sleep_cmd[5] = (uint8_t)(handle >> 8); 929a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 939a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int ret = write(fd, hci_sleep_cmd, sizeof(hci_sleep_cmd)); 949a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (ret < 0) { 959a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("write(): %s (%d)]", strerror(errno), errno); 969a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 979a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } else if (ret != sizeof(hci_sleep_cmd)) { 989a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("write(): unexpected length %d", ret); 999a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 1009a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1019a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return 0; 1029a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly} 1039a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1049a8383ad9ee9516756abeeb5081de9651a6294edNick Pellystatic int get_hci_sock() { 1059a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1069a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly struct sockaddr_hci addr; 1079a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int opt; 1089a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1099a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if(sock < 0) { 1109a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("Can't create raw HCI socket!"); 1119a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 1129a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1139a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1149a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly opt = 1; 1159a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (setsockopt(sock, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { 1169a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("Error setting data direction\n"); 1179a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 1189a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1199a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1209a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly /* Bind socket to the HCI device */ 1219a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly addr.hci_family = AF_BLUETOOTH; 1229a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly addr.hci_dev = 0; // hci0 1239a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if(bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1249a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("Can't attach to device hci0. %s(%d)\n", 1259a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly strerror(errno), 1269a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly errno); 1279a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 1289a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1299a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return sock; 1309a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly} 1319a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1329a8383ad9ee9516756abeeb5081de9651a6294edNick Pellystatic int get_acl_handle(int fd, bdaddr_t *bdaddr) { 1339a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int i; 1349a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int ret = -1; 1359a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly struct hci_conn_list_req *conn_list; 1369a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly struct hci_conn_info *conn_info; 1379a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int max_conn = 10; 1389a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1399a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly conn_list = malloc(max_conn * ( 1409a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly sizeof(struct hci_conn_list_req) + sizeof(struct hci_conn_info))); 1419a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (!conn_list) { 1429a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("Out of memory in %s\n", __FUNCTION__); 1439a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return -1; 1449a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1459a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1469a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly conn_list->dev_id = 0; /* hardcoded to HCI device 0 */ 1479a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly conn_list->conn_num = max_conn; 1489a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1499a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (ioctl(fd, HCIGETCONNLIST, (void *)conn_list)) { 1509a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly error("Failed to get connection list\n"); 1519a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly goto out; 1529a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1539a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1549a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly for (i=0; i < conn_list->conn_num; i++) { 1559a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly conn_info = &conn_list->conn_info[i]; 1569a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (conn_info->type == ACL_LINK && 1579a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly !memcmp((void *)&conn_info->bdaddr, (void *)bdaddr, 1589a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly sizeof(bdaddr_t))) { 1599a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly ret = conn_info->handle; 1609a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly goto out; 1619a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1629a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1639a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly ret = 0; 1649a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1659a8383ad9ee9516756abeeb5081de9651a6294edNick Pellyout: 1669a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly free(conn_list); 1679a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return ret; 1689a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly} 1699a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1709a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly/* Request that the ACL link to a given Bluetooth connection be high priority, 1719a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly * for improved coexistance support 1729a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly */ 1739a8383ad9ee9516756abeeb5081de9651a6294edNick Pellyint android_set_high_priority(bdaddr_t *ba) { 1749a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int ret; 1759a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int fd = get_hci_sock(); 1769a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly int acl_handle; 1779a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1789a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (fd < 0) 1799a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return fd; 1809a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1819a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly acl_handle = get_acl_handle(fd, ba); 1829a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly if (acl_handle < 0) { 1839a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly ret = acl_handle; 1849a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly goto out; 1859a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly } 1869a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1879a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly ret = vendor_high_priority(fd, acl_handle); 18882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly if (ret < 0) 18982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly goto out; 19027868bbc6230d357fda189a1c63cf6fcc59bb629Nick Pelly ret = write_flush_timeout(fd, acl_handle, 200); 1919a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1929a8383ad9ee9516756abeeb5081de9651a6294edNick Pellyout: 1939a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly close(fd); 1949a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1959a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return ret; 1969a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly} 1979a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 1989a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#else 1999a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 2009a8383ad9ee9516756abeeb5081de9651a6294edNick Pellyint android_set_high_priority(bdaddr_t *ba) { 2019a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly return 0; 2029a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly} 2039a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly 2049a8383ad9ee9516756abeeb5081de9651a6294edNick Pelly#endif 205