2019独角兽企业重金招聘Python工程师标准>>>
http://www.oschina.net/question/158589_55569
以下是我自己关于这个问题的详细分析过程:
问题:bluetooth必须在wifi开启后才能正常开启。
目标:bluetooth的开启不受wifi影响。
现象:
先打开wifi,再打开bluetooth。
I/wpa_supplicant( 2748): CTRL-EVENT-STATE-CHANGE id=-1 state=1
V/WifiMonitor( 2359): Event [CTRL-EVENT-STATE-CHANGE id=-1 state=1]
V/WifiStateTracker( 2359): Changing supplicant state: INACTIVE ==> INACTIVE
D/BluetoothService( 2359): Bluetooth state 10 -> 11
V/BluetoothEventRedirector( 2533): Received android.bluetooth.adapter.action.STATE_CHANGED
init: no such service 'hciattach'
I/bluedroid( 2359): Starting hciattach daemon
I/bluedroid( 2359): Starting bluetoothd deamon
E/BluetoothEventLoop.cpp( 2359): event_filter: Received signal org.freedesktop.DBus:NameAcquired from /org/freedesktop/DBus
D/BluetoothService( 2359): found 1 bonded devices
I/BluetoothDeviceProfileState( 2359): Entering ACL Connected state with: -1
D/BluetoothService( 2359): Bluetooth state 11 -> 12
V/BluetoothEventRedirector( 2533): Received android.bluetooth.adapter.action.STATE_CHANGED
D/BluetoothService( 2359): updateDeviceServiceChannelCache(E4:B0:21:58:18:53)
I/bluetooth_ScoSocket.cpp( 2439): Listening SCO socket...
D/BluetoothService( 2359): uuid(system): 00001105-0000-1000-8000-00805f9b34fb 3
I/BtOppRfcommListener( 2571): Accept thread started on channel 12
D/BluetoothService( 2359): Registering hfag record
打开bluetooth,不打开wifi
D/BluetoothService( 2359): Bluetooth state 10 -> 11
V/BluetoothEventRedirector( 2533): Received android.bluetooth.adapter.action.STATE_CHANGED
init: no such service 'hciattach'
I/bluedroid( 2359): Starting hciattach daemon
D/dalvikvm( 2571): GC_EXPLICIT freed 194K, 49% free 2802K/5447K, external 716K/1038K, paused 104ms
打开bluetooth,然后打开wifi
D/BluetoothService( 2359): Bluetooth state 10 -> 11
V/BluetoothEventRedirector( 2533): Received android.bluetooth.adapter.action.STATE_CHANGED
init: no such service 'hciattach'
I/bluedroid( 2359): Starting hciattach daemon
D/dalvikvm( 2571): GC_EXPLICIT freed 120K, 49% free 2782K/5447K, external 716K/1038K, paused 89ms
WLAN FW already running! Skip FW download
WLAN FW is active
I/bluedroid( 2359): Starting bluetoothd deamon
W/Netd ( 2215): action=1, iface=mlan0
D/Tethering( 2359): mlan0 is not a tetherable iface, ignoring
D/NetdConnector( 2359): RCV <- {600 Iface added mlan0}
W/Netd ( 2215): action=5, iface=mlan0
D/Tethering( 2359): interfaceLinkStatusChanged mlan0, false
D/NetdConnector( 2359): RCV <- {600 Iface linkstate mlan0 down}
W/Netd ( 2215): action=1, iface=uap0
D/Tethering( 2359): uap0 is not a tetherable iface, ignoring
W/Netd ( 2215): action=5, iface=uap0
D/Tethering( 2359): interfaceLinkStatusChanged uap0, false
D/NetdConnector( 2359): RCV <- {600 Iface added uap0}
D/NetdConnector( 2359): RCV <- {600 Iface linkstate uap0 down}
I/BluetoothEventLoop.cpp( 2359): agent_event_filter: Received method org.bluez.Agent:Release
D/BluetoothService( 2359): found 1 bonded devices
D/BluetoothService( 2359): Bluetooth state 11 -> 12
V/BluetoothEventRedirector( 2533): Received android.bluetooth.adapter.action.STATE_CHANGED
I/bluetooth_ScoSocket.cpp( 2439): Listening SCO socket...
分析:
定位关键代码
if (set_bluetooth_power(1) < 0) goto out;
LOGI("Starting hciattach daemon");
if (property_set("ctl.start", "hciattach") < 0) {
LOGE("Failed to start hciattach");
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 = 1000; attempt > 0; attempt--) {
hci_sock = create_hci_sock();
if (hci_sock < 0) goto out;
if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)) {
break;
}
close(hci_sock);
usleep(10000); // 10 ms retry delay
}
if (attempt == 0) {
LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
goto out;
}
LOGI("Starting bluetoothd deamon");
if (property_set("ctl.start", "bluetoothd") < 0) {
LOGE("Failed to start bluetoothd");
goto out;
}
在标红的代码两端添加打印,看是否是该段代码阻塞了蓝牙的打开。
I/bluedroid( 2385): Starting hciattach daemon
I/bluedroid( 2385): <
D/dalvikvm( 2583): GC_EXPLICIT freed 170K, 49% free 2800K/5447K, external 716K/1038K, paused 89ms
D/dalvikvm( 2385): GC_EXPLICIT freed 434K, 38% free 4808K/7751K, external 1867K/3065
并没有LOGI("<
=》可能是卡死在for循环了。
=》可能是直接走out了。
需要进行确认。
在for循环中添加打印:
LOGI("<
for (attempt = 1000; attempt > 0; attempt--) {
hci_sock = create_hci_sock();
LOGI("<
if (hci_sock < 0) goto out;
if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)) {
break;
}
close(hci_sock);
usleep(10000); // 10 ms retry delay
}
LOGI("<
if (attempt == 0) {
LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
goto out;
}
一直在循环。
通过for循环前的注释,初步定位为hciattach服务的问题。Grep关键词,主要是在以下文件中:
./device/fsl/imx51_3stack/mxc_bt.sh:/system/bin/hciattach -n -s 921600 /dev/ttymxc1 bcsp 921600;
./device/fsl/imx51_3stack/init.rc:service hciattach /system/bin/logwrapper /system/bin/sh /system/etc/bluez/mxc_bt.sh
经确认,不是这个原因,因为fsl目录下的东西没有被执行。
HCI device无法通过ioctl打开
=》ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)失败了
=》查看hci socket的ioctl
static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
case HCIDEVUP:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
return hci_dev_open(arg);
}
其实就是权限检查+设备打开。
增加打印
case HCIDEVUP:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
printk("<
ret = hci_dev_open(arg);
printk("<
return ret;
目标:通过打印看是权限不对还是打开hci设备出错。
<
<
I/bluedroid( 2386): <
#define ETIMEDOUT 110 /* Connection timed out */
于是问题就定位为HCI device做request时产生了timeout的错误。
int hci_dev_open(__u16 dev)
{
ret = __hci_request(hdev, hci_init_req, 0,
msecs_to_jiffies(HCI_INIT_TIMEOUT));//10s timeout
}
执行hci_init_req(hdev, 0)产生了超时
=》对hci device进行考察,找出超时原因。(android hci; Linux hci; hci device;)
=》wifi开启时,哪些东西会影响hci device?
猜想:有可能是固件加载的问题。打开蓝牙时没有对固件进行加载。
已经排除此可能。
猜想:是不是nh387还没有上电?
Nh387已经成功初始化。
猜想:HCI daemon没有启动,或者确实文件。
方法:了解HCI通信机制及其需要的文件。
在bt_main.c中有如下函数:
/**
* @brief This function send module cfg cmd to firmware
*
* Command format:
* +--------+--------+--------+--------+--------+--------+--------+
* | OCF OGF | Length | Data |
* +--------+--------+--------+--------+--------+--------+--------+
* | 2-byte | 1-byte | 4-byte |
* +--------+--------+--------+--------+--------+--------+--------+
*
* @param priv A pointer to bt_private structure
* @param subcmd sub command
* @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE
*/
int
bt_send_module_cfg_cmd(bt_private * priv, int subcmd)
它在执行如下语句时失败了
ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
if (ret < 0) {
PRINTM(FATAL, "Module cfg command send failed!\n");
goto err_init_fw;
}
这就很有可能是问题所在。提高PRINTM打印级别,看bt模块是否正确的初始化其firmware。
Firmware初始化正常了,但是bringup module这个request却执行失败。
bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);这句话会如何执行?
用旧的驱动和firmware:
加载蓝牙驱动时,没有timeout的错误,也就是说module_bringup_req执行成功了。但是,依然是不能打开蓝牙,现象和新的蓝牙驱动一样。
另外,使用旧的wifi驱动,系统启动后,”setting” -> “open wifi”会导致down机。
还原SDIO驱动
ok。。。。。。。。我擦!