一、蓝牙总体架构 

 

二、代码分布

1.应用

/packages/apps/Settings(原生的设置应用

/packages/apps/Bluetooth(原生的蓝牙应用

2.蓝牙java框架

/frameworks/base/core/java/android/bluetooth(蓝牙部分对应的应用程序api)

/frameworks/base/services/java/com/android/server/BluetoothManagerService.java(蓝牙相关的系统服务)

3.Bluedroid库

/external/bluetooth

4.适配层

/system/bluetooth

5.JNI部分

未知

6.蓝牙驱动

/driver/bluetooth

/driver/usb

/driver/serial

三、蓝牙各模块框架类图与设计模式

 

四、蓝牙启动过程

1.看下蓝牙框架层是怎么调用到BluetoothManagerService中去的

//SystemServer.java (frameworks\base\services\java\com\android\server) 

                if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
                Slog.i(TAG, "No Bluetooh Service (emulator)");
            } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
                Slog.i(TAG, "No Bluetooth Service (factory test)");
            } else {
                Slog.i(TAG, "Bluetooth Manager Service");
                bluetooth = new BluetoothManagerService(context);
                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
            }

如果采用的是模拟器内核,那么就不启动蓝牙服务,模拟器上不支持蓝牙

2.从BluetoothAdapter来看下应用是怎么调用蓝牙服务的

//BluetoothAdapter.java (\frameworks\base\core\java\android\bluetooth) 

 private final IBluetoothManager mManagerService;

    public boolean enable() {
        if (isEnabled() == true){
            if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
            return true;
        }
        try {
            return mManagerService.enable();
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

上面的mManagerService是在构造函数中传进来的,我们看下mManagerService的本质是什么:

 //BluetoothAdapter.java
    BluetoothAdapter(IBluetoothManager managerService) {

        if (managerService == null) {
            throw new IllegalArgumentException("bluetooth manager service is null");
        }
        try {
            mService = managerService.registerAdapter(mManagerCallback);
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        mManagerService = managerService;
        mServiceRecordHandler = null;
    }

IBluetoothManager是一个接口,所以实际上mManagerService是BluetoothManagerService的一个Proxy

其中class BluetoothManagerService extends IBluetoothManager.Stub {

为什么呢?我们从BluetoothAdapter在应用中的使用能够看出来:

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 

public static synchronized BluetoothAdapter getDefaultAdapter() {
        if (sAdapter == null) {
            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
            if (b != null) {
                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
                sAdapter = new BluetoothAdapter(managerService);
            } else {
                Log.e(TAG, "Bluetooth binder is null");
            }
        }
        return sAdapter;
    }

可以知道BluetoothAdapter(IBluetoothManager managerService)中的参数就是上面的

ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);

所以最后调用的是BluetoothManagerService.enable();

3. BluetoothManagerService.java (frameworks\base\services\java\com\android\server) 

public boolean enable() {
        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
            (!checkIfCallerIsForegroundUser())) {
            Log.w(TAG,"enable(): not allowed for non-active and non system user");
            return false;
        }

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH ADMIN permission");
        if (DBG) {
            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
                    " mBinding = " + mBinding);
        }

        synchronized(mReceiver) {
            mQuietEnableExternal = false;
            mEnableExternal = true;
            // waive WRITE_SECURE_SETTINGS permission check
            long callingIdentity = Binder.clearCallingIdentity();
            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
            Binder.restoreCallingIdentity(callingIdentity);
            sendEnableMsg(false);
        }
        return true;
    }

同样,BluetoothAdapter封装的一些接口最终都是调用到了BluetoothManagerSevice的函数实现。

五、应用层对框架层的调用

经过上面的一个垂直调用,我们再水平看下蓝牙框架层中的东西,打开/framework/base/core/java/android/bluetooth的源码,我们会发现其中都是一些java文件和aidl文件。

并且我们可以在编译代码后发现out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth

这个目录下有一系列的接口文件生成。

我们用类图来描述框架层中的东西:

 

在了解蓝牙框架的时候,我们先了解下应用对框架类的使用:

packages\apps\Settings

Settings这个应用中最后会调用到CachedBluetoothDevice.connectInt

  synchronized void connectInt(LocalBluetoothProfile profile) {
  Log.d(TAG,"duanliang,connectInt begin");
        if (!ensurePaired()) {
   Log.d(TAG,"duanliang,in connectInt,ensurePaired()==false return");
            return;
        }
  Log.d(TAG,"duanliang,before profile.connect(mDevice);");
        if (profile.connect(mDevice)) {
            if (Utils.D) {
                Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));
            }
            return;
        }
        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
    }

这个connect函数是有返回值得boolean型
profile.connect(mDevice))会调用到:

//BluetoothA2dp.java

这个问题是什么东西

 public boolean connect(BluetoothDevice device) {
        if (DBG) log("connect(" + device + ")");
        if (mService != null && isEnabled() &&
            isValidDevice(device)) {
            try {
    Log.d(TAG,"duanliang,in connect,mService="+mService);
                return mService.connect(device);
            } catch (RemoteException e) {
                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                return false;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
        return false;
    }

这里的mService打印出来的结果是:

D/BluetoothA2dp( 1086):mService=android.bluetooth.IBluetoothA2dp$Stub$Proxy@41ce2f20

结合:mService = IBluetoothA2dp.Stub.asInterface(service);

我们可以在/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth/IBluetoothA2dp.java中找到IBluetoothA2dp.Stub.asInterface();这个函数:


public static android.bluetooth.IBluetoothA2dp asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.bluetooth.IBluetoothA2dp))) {
return ((android.bluetooth.IBluetoothA2dp)iin);
}
return new android.bluetooth.IBluetoothA2dp.Stub.Proxy(obj);
}

这里返回的是service的一个实例

所以这个android.bluetooth.IBluetoothA2dp.Stub.Proxy(obj).connect()函数是:

A2dpService.connect()

//A2dpService.java

    public boolean connect(BluetoothDevice device) {
  Log.d(TAG,"duanliang,connect begin");
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                       "Need BLUETOOTH ADMIN permission");

        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
            return false;
        }

        int connectionState = mStateMachine.getConnectionState(device);
        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
            connectionState == BluetoothProfile.STATE_CONNECTING) {
            return false;
        }
  Log.d(TAG,"before sendMessage..");
        mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
        return true;
    }

然后是:mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);

因为final class A2dpStateMachine extends StateMachine ,sendMessage这个函数在StateMachine里面:

  
    public final void sendMessage(int what, Object obj) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(obtainMessage(what,obj));
    }

应该就是向设备发送了一个A2dpStateMachine.CONNECT消息。

然后由A2dpStateMachine相应状态的processMessage函数来处理,这里要是当前状态是Disconnected,则由此状态的processMessage来处理这个connect消息:

D/A2dpService( 1130): duanliang,connect begin
D/A2dpStateMachine( 1130): Disconnected process message: 1

 收到这个连接消息之后做了些什么呢?

//A2dpStateMachine.java

 case CONNECT:
     Log.d(TAG,"in Disconnect,duanliang,message.what=CONNECT");

                   //首先将设备类型转为BluetoothDevice
                    BluetoothDevice device = (BluetoothDevice) message.obj;

                  //广播连接状态的改变:未连接->正在连接
                    broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
                                   BluetoothProfile.STATE_DISCONNECTED);

                 //调用Native层进行连接

                    if (!connectA2dpNative(getByteAddress(device)) ) {

                //如果连接不成功,则将状态从正在连接改到未连接
                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
                                       BluetoothProfile.STATE_CONNECTING);
                        break;
                    }

                    synchronized (A2dpStateMachine.this) {
                        mTargetDevice = device;
                        transitionTo(mPending);
                    }
                    // TODO(BT) remove CONNECT_TIMEOUT when the stack
                    //          sends back events consistently
                    sendMessageDelayed(CONNECT_TIMEOUT, 30000);
                    break;

 

//A2dpStateMachine.java

 

    // This method does not check for error conditon (newState == prevState)
    private void broadcastConnectionState(BluetoothDevice device, int newState, int prevState) {

        int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, newState);

        mWakeLock.acquire();
        mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage(
                                                        MSG_CONNECTION_STATE_CHANGED,
                                                        prevState,
                                                        newState,
                                                        device),
                                                        delay);
    }

现在我们关注一下connectA2dpNative(getByteAddress(device)) ,这就通过jni调用到了native层

六、框架层对Native层的调用

框架层会通过jni调用本地方法到达Native层

//A2dpStateMachine.java

 private native boolean connectA2dpNative(byte[] address);

 packages/apps/bluetooth/jni下的文件有一系列的c++文件,最后编译成蓝牙的jni库

Install: out/target/product/nt72668_tcl/system/lib/libbluetooth_jni.so

 

//com_android_bluetooth_a2dp.cpp

static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
    jbyte *addr;
    bt_status_t status;
    jint a2dpRole = 0;

    ALOGI("%s: sBluetoothA2dpSourceInterface: %p sBluetoothA2dpSinkInterface: %p", __FUNCTION__,
          sBluetoothA2dpSourceInterface, sBluetoothA2dpSinkInterface);
    if (!(sBluetoothA2dpSourceInterface || sBluetoothA2dpSinkInterface)) return JNI_FALSE;

    addr = env->GetByteArrayElements(address, NULL);
    if (!addr) {
        jniThrowIOException(env, EINVAL);
        ALOGI("%s: addr null",__FUNCTION__);
        return JNI_FALSE;
    }

    a2dpRole = (jint) env->CallIntMethod(object, method_getA2dpProfileServiceUuid);
    ALOGI( "connectA2dpNative a2dp role 0x%x" ,a2dpRole);
    if ((sBluetoothA2dpSourceInterface)&& (a2dpRole == A2DP_SOURCE_SERVICE_UUID )) {
        ALOGI( "Attempting to connect a2dp source ");
        if ((status = sBluetoothA2dpSourceInterface->connect((bt_bdaddr_t *)addr)) !=
                                        BT_STATUS_SUCCESS) {
            ALOGE("Failed A2dp Source connection, status: %d", status);
        }
    }

    else if ((sBluetoothA2dpSinkInterface) && (a2dpRole == A2DP_SINK_SERVICE_UUID )) {
        ALOGI( "Attempting to connect a2dp sink ");
        if ((status = sBluetoothA2dpSinkInterface->connect((bt_bdaddr_t *)addr)) !=
                                        BT_STATUS_SUCCESS) {
            ALOGE("Failed A2dp Sink connection, status: %d", status);
        }
    }

    env->ReleaseByteArrayElements(address, addr, 0);
    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

这里会调用到:

I/BluetoothA2dpServiceJni( 1130): Attempting to connect a2dp source

然后调用到:

I/bt-btif ( 1130): connect
I/bt-btif ( 1130): connect

我们仔细分析下其中的:

 sBluetoothA2dpSourceInterface->connect((bt_bdaddr_t *)addr))

这个sBluetoothA2dpInterface结构体对象是在initNative(JNIEnv *env, jobjectobject)方法时得到的。

/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp中实现的是bluetooth的JNI代码,是上层Java与下层Bluedroid的接口

先看下结构体类型:

static const btav_interface_t  *sBluetoothA2dpSourceInterface = NULL;

再看下initNative:
    ALOGD("Attempting to acquire Bluetooth A2DP Source Interface");
    if ( (sBluetoothA2dpSourceInterface = (btav_interface_t *)
          btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) != NULL) {
        status = sBluetoothA2dpSourceInterface->init(&sBluetoothA2dpSourceCallbacks);
        if (status == BT_STATUS_SUCCESS) {
            mCallbacksObj = env->NewGlobalRef(object);
        }
        else {
            ALOGE("Failed to initialize Bluetooth A2DP source, status: %d", status);
            sBluetoothA2dpSourceInterface = NULL;
        }
    }
    else {
        ALOGW("Bluetooth A2DP Source Interface Unavailable");
    }

其中btInf = getBluetoothInterface()

//com_android_bluetooth_btservice_AdapterService.cpp

const bt_interface_t* getBluetoothInterface() {
    return sBluetoothInterface;
}

com_android_bluetooth_btservice_AdapterService.classInitNative中我们可以看到:

 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
            sBluetoothInterface = btStack->get_bluetooth_interface();

这里是获取一个蓝牙硬件抽象层的接口,就到达了硬件抽象层

七、Native层到HAL层(硬件抽象层)的调用

现在我们分析下蓝牙的硬件抽象层:

//Bluetooth.h

typedef struct {
    struct hw_device_t common;
    const bt_interface_t* (*get_bluetooth_interface)();
} bluetooth_device_t;

typedef bluetooth_device_t bluetooth_module_t;

可以看到继承了hw_device_t定义了硬件模块结构体结构体bluetooth_device_t;

此外还有硬件接口结构体:bt_interface_t

还可以找到抽象层硬件模块ID

 

#define BT_HARDWARE_MODULE_ID "bluetooth"
#define BT_STACK_MODULE_ID "bluetooth"
#define BT_STACK_TEST_MODULE_ID "bluetooth_test"

这样,Android硬件抽象层规范的要求的模块ID、模块结构体以及硬件接口结构体都具备了。

然后我们可以到

但是我们找不到Bluetooth.c这个实现文件,这是因为,硬件抽象层的实现是第三方实现的,并且封装成了so库提供给我们,/system/lib/hw下的bluetooth.default.so就是第三方给我们提供的蓝牙硬件抽象层的库,从名字可以判断下面两个是蓝牙耳机和音箱对应的硬件抽象层库:

audio.btmic.default.so
audio.a2dp.default.so

八、硬件抽象层到内核驱动层

 

--------------------------------------------------------------------------------------------------------------

以上是以蓝牙音箱的连接过程作为主线,现在看下蓝牙游戏手柄的连接

这里走的是hid设备

九、蓝牙手柄

在中我们知道会调用到profile.connect(mDevice));

因为蓝牙手柄时Hid设备,所以会调用到:

//HidProfile.java

    public boolean connect(BluetoothDevice device) {
  Log.d(TAG,"duanliang,connect begin");
        if (mService == null) return false;
        return mService.connect(device);
    }

然后调用到:

    public boolean connect(BluetoothDevice device) {
     Log.d(TAG,"duanliang,conect begin");
        if (DBG) log("connect(" + device + ")");
        if (mService != null && isEnabled() && isValidDevice(device)) {
            try {
    Log.d(TAG,"duanliang, before mService.connect(device);");
    Log.d(TAG,"duanliang,mService ="+mService);
                return mService.connect(device);
            } catch (RemoteException e) {
                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                return false;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
        return false;
    }

然后调用到HidService.java(不同于蓝牙音箱,上面蓝牙音箱的mService.connect(device)调用到的是A2dpService)

  boolean connect(BluetoothDevice device) {
  Log.d(TAG,"duanliang,connect begin");
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) {
            Log.e(TAG, "Hid Device not disconnected: " + device);
            return false;
        }
        if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
            Log.e(TAG, "Hid Device PRIORITY_OFF: " + device);
            return false;
        }

        Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device);
        mHandler.sendMessage(msg);
        return true;
    }

然后由HidService中的handle处理消息:

 case MESSAGE_CONNECT:
                {
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    if (!connectHidNative(Utils.getByteAddress(device)) ) {
                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
                        break;
                    }
                    mTargetDevice = device;
                }
                    break;

注意,这里还有一个mTargetDevice,应该是在连接之后需要使用的一个变量。这儿Native函数有一个返回值,所以应该是连接结果通过这个返回值来标识。

这里调用到Native层:

connectHidNative

//Com_android_bluetooth_hid.cpp

static jboolean connectHidNative(JNIEnv *env, jobject object, jbyteArray address) {
    bt_status_t status;
    jbyte *addr;
    jboolean ret = JNI_TRUE;
    if (!sBluetoothHidInterface) return JNI_FALSE;

    addr = env->GetByteArrayElements(address, NULL);
    if (!addr) {
        ALOGE("Bluetooth device address null");
        return JNI_FALSE;
    }

    if ((status = sBluetoothHidInterface->connect((bt_bdaddr_t *) addr)) !=
         BT_STATUS_SUCCESS) {
        ALOGE("Failed HID channel connection, status: %d", status);
        ret = JNI_FALSE;
    }
    env->ReleaseByteArrayElements(address, addr, 0);

    return ret;
}

这里调用status = sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))进行连接,

而这个sBluetoothHidInterface

static const bthh_interface_t *sBluetoothHidInterface = NULL;也是在initializeNative函数中初始化的

//Com_android_bluetooth_hid.cpp

static void initializeNative(JNIEnv *env, jobject object) {
    const bt_interface_t* btInf;
    bt_status_t status;

    if ( (btInf = getBluetoothInterface()) == NULL) {
        ALOGE("Bluetooth module is not loaded");
        return;
    }

    if (sBluetoothHidInterface !=NULL) {
        ALOGW("Cleaning up Bluetooth HID Interface before initializing...");
        sBluetoothHidInterface->cleanup();
        sBluetoothHidInterface = NULL;
    }

    if (mCallbacksObj != NULL) {
        ALOGW("Cleaning up Bluetooth GID callback object");
        env->DeleteGlobalRef(mCallbacksObj);
        mCallbacksObj = NULL;
    }


    if ( (sBluetoothHidInterface = (bthh_interface_t *)
          btInf->get_profile_interface(BT_PROFILE_HIDHOST_ID)) == NULL) {
        ALOGE("Failed to get Bluetooth HID Interface");
        return;
    }

    if ( (status = sBluetoothHidInterface->init(&sBluetoothHidCallbacks)) != BT_STATUS_SUCCESS) {
        ALOGE("Failed to initialize Bluetooth HID, status: %d", status);
        sBluetoothHidInterface = NULL;
        return;
    }

 

    mCallbacksObj = env->NewGlobalRef(object);
}

其中btInf = getBluetoothInterface()

//com_android_bluetooth_btservice_AdapterService.cpp

const bt_interface_t* getBluetoothInterface() {
    return sBluetoothInterface;
}

而这个sBluetoothInterface又是在

static void classInitNative(JNIEnv* env, jclass clazz) {
    int err;
    hw_module_t* module;

    jclass jniCallbackClass =
        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
        "Lcom/android/bluetooth/btservice/JniCallbacks;");

    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");

    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
                                                             "adapterPropertyChangedCallback",
                                                             "([I[[B)V");
    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                           "discoveryStateChangeCallback", "(I)V");

    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
                                                            "devicePropertyChangedCallback",
                                                            "([B[I[[B)V");
    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
                                                 "([B[BI)V");
    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
                                                 "([B[BIII)V");

    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                     "bondStateChangeCallback", "(I[BI)V");

    method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                    "aclStateChangeCallback", "(I[BI)V");
    char value[PROPERTY_VALUE_MAX];
    property_get("bluetooth.mock_stack", value, "");

    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);

    err = hw_get_module(id, (hw_module_t const**)&module);

    if (err == 0) {
        hw_device_t* abstraction;
        err = module->methods->open(module, id, &abstraction);
        if (err == 0) {
            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
            sBluetoothInterface = btStack->get_bluetooth_interface();
        } else {
           ALOGE("Error while opening Bluetooth library");
        }
    } else {
        ALOGE("No Bluetooth Library found");
    }
}

中被初始化的,所以,最后返回的是一个

btStack->get_bluetooth_interface();类型为bt_interface_t

然后强制转换成了bthh_interface_t类型

 

我们看一下:bt_interface_t

再看一下:bthh_interface_t

觉得这样强制转换有点奇怪

 

typedef struct {
    struct hw_device_t common;
    const bt_interface_t* (*get_bluetooth_interface)();
} bluetooth_device_t;

typedef bluetooth_device_t bluetooth_module_t;

也可以知道btStack的本质是一个bluetooth_device_t类型的结构体。

而这个结构体的来源从:

        hw_device_t* abstraction;
        err = module->methods->open(module, id, &abstraction);

知道,这个后续再深究

同样的,这里的get_bluetooth_interface的实现,也是被方案商封装起来的。


这个get_profile_interface就是硬件抽象层的实现:

./system/bluetooth/bluedroid/bluetooth.c

总结一下sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))的整个过程:

sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))=

(bthh_interface_t *)btInf->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=

(bthh_interface_t *)getBluetoothInterface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=

(bthh_interface_t *)sBluetoothInterface->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=

(bthh_interface_t *)btStack->get_bluetooth_interface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=

(bthh_interface_t *)(bluetooth_module_t *)abstraction->get_bluetooth_interface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=

可以知道:

1.调用bluetooth_module_t中的get_bluetooth_interface返回一个bt_interface_t

//Bluetooth.h

typedef struct {
    struct hw_device_t common;
    const bt_interface_t* (*get_bluetooth_interface)();
} bluetooth_device_t;

typedef bluetooth_device_t bluetooth_module_t;

2.调用bt_interface_t的get_profile_interface(BT_PROFILE_HIDHOST_ID)) 并将其转换成bthh_interface_t *类型

//bluetooth.h


typedef struct { 
    size_t size;
    int (*init)(bt_callbacks_t* callbacks );
    int (*enable)(void);
    int (*disable)(void);
    void (*cleanup)(void);
    int (*get_adapter_properties)(void);
    int (*get_adapter_property)(bt_property_type_t type);

    int (*set_adapter_property)(const bt_property_t *property);

    int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr);

    int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, bt_property_type_t type);

    int (*set_remote_device_property)(bt_bdaddr_t *remote_addr,const bt_property_t *property);

    int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid);

    int (*get_remote_services)(bt_bdaddr_t *remote_addr);

    int (*start_discovery)(void);
    int (*cancel_discovery)(void);
    int (*create_bond)(const bt_bdaddr_t *bd_addr);
    int (*remove_bond)(const bt_bdaddr_t *bd_addr);
    int (*cancel_bond)(const bt_bdaddr_t *bd_addr);
    int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept,
                     uint8_t pin_len, bt_pin_code_t *pin_code);
    int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
                     uint8_t accept, uint32_t passkey);
    const void* (*get_profile_interface) (const char *profile_id);
    int (*dut_mode_configure)(uint8_t enable);
    int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len);
    int (*enter_headless_mode)(void);
    int (*add_headless_mode_wakeup_device)(bt_bdaddr_t *remote_addr);
    int (*delete_headless_mode_wakeup_device)(bt_bdaddr_t *remote_addr);
} bt_interface_t;

3.调用bthh_interface_t里的connect函数进行连接:

typedef struct {

   
    size_t          size;

   
    bt_status_t (*init)( bthh_callbacks_t* callbacks );

   
    bt_status_t (*connect)( bt_bdaddr_t *bd_addr);

   
    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );

   
    bt_status_t (*virtual_unplug)(bt_bdaddr_t *bd_addr);

   
    bt_status_t (*set_info)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info );

   
    bt_status_t (*get_protocol) (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode);

   
    bt_status_t (*set_protocol)(bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode);

   
    bt_status_t (*get_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, uint8_t reportId, int bufferSize);

   
    bt_status_t (*set_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, char* report);

   
    bt_status_t (*send_data)(bt_bdaddr_t *bd_addr, char* data);

   
    bt_status_t (*ota_get_fwversion)(bt_bdaddr_t *bd_addr);

   
    bt_status_t (*ota_update_firmware)(bt_bdaddr_t *bd_addr, char* path);

   
    void  (*cleanup)( void );

} bthh_interface_t;

 现在我们要看一下bthh_interface_t的connect实现是在哪里。

我们调试的时候会发现看打印,其实已经掉到了蓝牙协议栈里:

I/bt-btif ( 1133): btif_hh_handle_evt: event=0
D/bt-btif ( 1133): btif_hh_connect: a=20:73:14:01:16:8b
I/bt-btif ( 1133): BTHH: btif_hh_connect
D/bt-btif ( 1133): btif_hh_find_dev_by_bda: a=20:73:14:01:16:8b
D/bt-btif ( 1133): btif_hh_find_dev_by_bda: not found
D/CachedBluetoothDevice( 1044): Command sent successfully:CONNECT Address:20:73:14:01:16:8B Profile:HID
D/bt-btif ( 1133): btif_hh_find_dev_available:
D/bt-btif ( 1133): btif_hh_find_dev_available: found 0
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
I/bt-l2cap( 1133): 02:09:35.340 L2CAP SENT Command.  Name: L2C Connection Request (0x02) ID 0x0a, len 4
I/bt-l2cap( 1133): 02:09:35.340                               Channel ID : 01
I/bt-l2cap( 1133): 02:09:35.340                                      PSM : 0x1
I/bt-l2cap( 1133): 02:09:35.340                               Source CID : 0x45
I/bt-l2cap( 1133): 02:09:35.340 --

 

 

查找 btif_hh_connect

chenglan@novatek:~/Android_NT667B/android$ grep -rn btif_hh_connect
Binary file .svn/pristine/d1/d110e9293da57287f57d20647f4180042c28578a.svn-base matches
.svn/pristine/c5/c5822f31e14e3040d6fddf1b557ba44308bb1ecd.svn-base:108:extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
.svn/pristine/c5/c5822f31e14e3040d6fddf1b557ba44308bb1ecd.svn-base:385:            status = btif_hh_connect(bd_addr);
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:559:** Function         btif_hh_connect
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:567:bt_status_t btif_hh_connect(bt_bdaddr_t *bd_addr)
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:1060:            ret = btif_hh_connect(bd_addr);
Binary file device/novatek/nt72668_tcl/bluetooth/bluetooth.default.so matches
external/bluetooth/bluedroid/btif/src/btif_dm.c:108:extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
external/bluetooth/bluedroid/btif/src/btif_dm.c:385:            status = btif_hh_connect(bd_addr);
external/bluetooth/bluedroid/btif/src/btif_hh.c:560:** Function         btif_hh_connect
external/bluetooth/bluedroid/btif/src/btif_hh.c:568:bt_status_t btif_hh_connect(bt_bdaddr_t *bd_addr)
external/bluetooth/bluedroid/btif/src/btif_hh.c:1061:            ret = btif_hh_connect(bd_addr);
Binary file out/target/product/nt72668_tcl/system.img matches
Binary file out/target/product/nt72668_tcl/system_ext4.img matches
Binary file out/target/product/nt72668_tcl/obj/PACKAGING/systemimage_intermediates/system.img matches
Binary file out/target/product/nt72668_tcl/system/lib/hw/bluetooth.default.so matches

而在btif_hh.c中由connect函数开始调,调到btif_hh_handle_evt再调到btif_hh_connect才有了上述打印,而这个connect函数的注册时在下面这个结构体中:上面的一大段分析,其实调到的就是这个bthh_interface_t类型的bthhInterface的connect函数。

static const bthh_interface_t bthhInterface = {
    sizeof(bt_interface_t),
    init,
    connect,
    disconnect,
    virtual_unplug,
    set_info,
    get_protocol,
    set_protocol,
//    get_idle_time,
//    set_idle_time,
    get_report,
    set_report,
    send_data,
    cleanup,
};

我们现在看下这个btif_hh.c中的connect:

static bt_status_t connect( bt_bdaddr_t *bd_addr)
{
    if(btif_hh_cb.status != BTIF_HH_DEV_CONNECTING)
    {
        btif_transfer_context(btif_hh_handle_evt, BTIF_HH_CONNECT_REQ_EVT,
                                 (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
        return BT_STATUS_SUCCESS;
    }
    else
        return BT_STATUS_BUSY;
}

这里我们跟踪下btif_transfer_context,看里面做了什么

 

 

bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback)
{
    tBTIF_CONTEXT_SWITCH_CBACK *p_msg;

    BTIF_TRACE_VERBOSE2("btif_transfer_context event %d, len %d", event, param_len);

   
    if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL)
    {
        p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT;
        p_msg->p_cb = p_cback;

        p_msg->event = event;                        

       
        if (p_copy_cback)
        {
            p_copy_cback(event, p_msg->p_param, p_params);
        }
        else if (p_params)
        {
            memcpy(p_msg->p_param, p_params, param_len); 
        }

        btif_sendmsg(p_msg);
        return BT_STATUS_SUCCESS;
    }
    else
    {
       
        return BT_STATUS_NOMEM;
    }
}

 

void btif_sendmsg(void *p_msg)
{

// Called by applications to send a buffer to a task
    GKI_send_msg(BTIF_TASK, BTU_BTIF_MBOX, p_msg);
}

不去发送这个消息之后是怎么处理的,但猜测应该是调用了btif_hh_handle_evt:

因为消息类型是BTIF_HH_CONNECT_REQ_EVT,所以执行的代码应该是:

 case BTIF_HH_CONNECT_REQ_EVT:
        {
            ret = btif_hh_connect(bd_addr);
            if(ret == BT_STATUS_SUCCESS)
            {
                HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_CONNECTING);
            }
            else
                HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_DISCONNECTED);
        }
        break;


 

这个函数会一直调用下去,调用到btif_hh_connect,在btif_hh_connect中又会调用到

btif_hh_find_dev_by_bda,这个函数的作用是:

Return the device pointer of the specified bt_bdaddr_t

在btif_hh_connect中调用玩btif_hh_find_dev_by_bda之后,又会调用HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr, BTHH_CONN_STATE_CONNECTING);

我们看下btif_hh_connect中连接相关的主要代码:

//这个added_dev类型是HAL层里定义好的

btif_hh_added_device_t *added_dev = NULL;

//for循环的作用是根据地址bd_addr得到匹配的设备

    for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
        if (memcmp(&(btif_hh_cb.added_devices[i].bd_addr), bd_addr, BD_ADDR_LEN) == 0) {
            added_dev = &btif_hh_cb.added_devices[i];
             BTIF_TRACE_WARNING3("%s: Device %s already added, attr_mask = 0x%x",
                 __FUNCTION__, bda_str, added_dev->attr_mask);
        }
    }

//如果设备存在,但不可用,则打印一个提示

    if (added_dev != NULL) {
        if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
            // No space for more HID device now.
            BTIF_TRACE_ERROR2("%s: Error, device %s added but addition failed", __FUNCTION__, bda_str);
            memset(&(added_dev->bd_addr), 0, 6);
            added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
            return BT_STATUS_FAIL;
        }
    }

//如果设备可连接
    if (added_dev == NULL ||
        (added_dev->attr_mask & HID_NORMALLY_CONNECTABLE) != 0 ||
        (added_dev->attr_mask & HID_RECONN_INIT) == 0)
    {
        tBTA_SEC sec_mask = BTUI_HH_SECURITY;
        btif_hh_cb.status = BTIF_HH_DEV_CONNECTING;
        BD_ADDR *bda = (BD_ADDR*)bd_addr;
        BTA_HhOpen(*bda, BTA_HH_PROTO_RPT_MODE, sec_mask);
    }

我们跟踪下这个BTA_HhOpen

bta/hh/bta_hh_api.c


void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
{
    tBTA_HH_API_CONN *p_buf;

    p_buf = (tBTA_HH_API_CONN *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_CONN));

    if (p_buf!= NULL)
    {
        memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));

        p_buf->hdr.event            = BTA_HH_API_OPEN_EVT;
        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
        p_buf->sec_mask             = sec_mask;
        p_buf->mode                 = mode;
        bdcpy(p_buf->bd_addr, dev_bda);

        bta_sys_sendmsg((void *)p_buf);
    }
    else
    {
        APPL_TRACE_ERROR0("No resource to send HID host Connect request.");
    }
}

这里调用到了:

void bta_sys_sendmsg(void *p_msg)
{
    GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
}

这个函数还是只用了一个地址

gki/common/gki_buffer.c


void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)
{
    BUFFER_HDR_T    *p_hdr;
    tGKI_COM_CB *p_cb = &gki_cb.com;

   
    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
    {
        GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
        GKI_freebuf (msg);
        return;
    }

#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    if (gki_chk_buf_damage(msg))
    {
        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
        return;
    }
#endif

    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);

    if (p_hdr->status != BUF_STATUS_UNLINKED)
    {
        GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
        return;
    }

    GKI_disable();

    if (p_cb->OSTaskQFirst[task_id][mbox])
        p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
    else
        p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;

    p_cb->OSTaskQLast[task_id][mbox] = p_hdr;

    p_hdr->p_next = NULL;
    p_hdr->status = BUF_STATUS_QUEUED;
    p_hdr->task_id = task_id;


    GKI_enable();

    GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));

    return;
}

gki/ulinux/gki_ulinux.c

 

UINT8 GKI_send_event (UINT8 task_id, UINT16 event)
{
    GKI_TRACE("GKI_send_event %d %x", task_id, event);

   
    if (task_id < GKI_MAX_TASKS)
    {
       
        pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[task_id]);

       
        gki_cb.com.OSWaitEvt[task_id] |= event;

        pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]);

        pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[task_id]);

        GKI_TRACE("GKI_send_event %d %x done", task_id, event);
        return ( GKI_SUCCESS );
    }
    GKI_TRACE("############## GKI_send_event FAILED!! ##################");
    return (GKI_FAILURE);
}

发送消息,不知道发送到哪里去了 = =

蓝牙打开关闭全过程跟踪:

 http://blog.csdn.net/yinlijun2004/article/details/9724347

分析了这么长,还是没有找到到底什么时候判定为连接上的,我们搜索BTHH_CONN_STATE_CONNECTED

发现

//---------------------------这里讨论callback来更新连接状态的过程

这个bt_hh_callbacks是在init函数中被初始化的:


static bt_status_t init( bthh_callbacks_t* callbacks )
{
    UINT32 i;
    BTIF_TRACE_EVENT1("%s", __FUNCTION__);

    bt_hh_callbacks = callbacks;
    memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
    for (i = 0; i < BTIF_HH_MAX_HID; i++){
        btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
    }
    btif_enable_service(BTA_HID_SERVICE_ID);
    return BT_STATUS_SUCCESS;
}

从Log

D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb

中分析,结合HAL_CBACK的定义,应该是调用到了bt_hh_callbacks->connection_state_cb

而这个bt_hh_callbacks类型是bthh_callbacks_t,其定义在include/hardware/bt_hh.h中


typedef struct {
    size_t      size;
    bthh_connection_state_callback  connection_state_cb;
    bthh_hid_info_callback          hid_info_cb;
    bthh_protocol_mode_callback     protocol_mode_cb;
    bthh_idle_time_callback         idle_time_cb;
    bthh_get_report_callback        get_report_cb;
    bthh_virtual_unplug_callback    virtual_unplug_cb;
    bthh_audio_state_callback       audio_state_cb;
    bthh_ota_version_callback       ota_version_cb;
    bthh_ota_update_callback        ota_update_cb;
    bthh_ota_updatedone_callback    ota_updatedone_cb;
} bthh_callbacks_t;

这里调用的是一个callback函数  bthh_connection_state_callback  connection_state_cb;
而这个connection_state_cb是在哪里指定的呢?

我们grep -rn bthh_callbacks_t可以发现:

com_android_bluetooth_hid.cpp:209:

static bthh_callbacks_t sBluetoothHidCallbacks = {
    sizeof(sBluetoothHidCallbacks),
    connection_state_callback,
    NULL,
    get_protocol_mode_callback,
    NULL,
    NULL,
    virtual_unplug_callback,
    audio_state_callback,
    ota_get_version_callback,
    ota_update_progress_callback,
    ota_update_done_callback
};

这个bthh_callbacks_t结构体里面的connection函数是connection_state_callback

所以,其实又调用到这里来了,而这个结构体的初始化是在com_android_bluetooth_hid.classInitNative()中讲其传进去进行初始化的。

status = sBluetoothHidInterface->init(&sBluetoothHidCallbacks)

所以现在回调就会调用到这里:


static void connection_state_callback(bt_bdaddr_t *bd_addr, bthh_connection_state_t state) {
    jbyteArray addr;

    CHECK_CALLBACK_ENV
    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (!addr) {
        ALOGE("Fail to new jbyteArray bd addr for HID channel state");
        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
        return;
    }
    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);

    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state);
    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
    sCallbackEnv->DeleteLocalRef(addr);
}

这个method_onConnectStateChanged类型是jmethodID,发现其实这里用到的是C++调用Android的机制。这里回调到了onConnectStateChanged函数,查找一下可以发现在HidService.java,PanService.java等文件中都有这个函数的定义。其实这些回调函数里只是发送了一个消息,然后HidService监听到之后做了处理,这里是发送了一个MESSAGE_CONNECT_STATE_CHANGED消息来更新连接状态:

D/HidService( 1133): MESSAGE_CONNECT_STATE_CHANGED newState:1, prevState:0

在Log中,我们发现btif之后是l2cap的log,那么我们现在要看下怎么调到l2cap中去的。

这个l2cap是一个协议栈,在目录external/bluetooth/bluedroid/stack/l2cap下:

 

//----------------------------------现在我们看下协议栈中队/uhid这个节点的操作情况--------------

在bluedroid/btif/co/bta_hh_co.c中有对这个设备节点的相应操作函数:

我们跟uhid_write这个函数被bta_hh_co_send_hid_info调用,被btif_hh_upstreams_evt调用(btif_hh.c)

收到 BTA_HH_GET_DSCP_EVT事件的时候会执行,

在btif_hh.c中有一个函数bte_hh_evt:

static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
{
    bt_status_t status;
    int param_len = 0;

    if (BTA_HH_ENABLE_EVT == event)
        param_len = sizeof(tBTA_HH_STATUS);
    else if (BTA_HH_OPEN_EVT == event)
        param_len = sizeof(tBTA_HH_CONN);
    else if (BTA_HH_DISABLE_EVT == event)
        param_len = sizeof(tBTA_HH_STATUS);
    else if (BTA_HH_CLOSE_EVT == event)
        param_len = sizeof(tBTA_HH_CBDATA);
    else if (BTA_HH_GET_DSCP_EVT == event)
        param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
    else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event)|| (BTA_HH_GET_IDLE_EVT == event))
        param_len = sizeof(tBTA_HH_HSDATA);
    else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) || (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
        param_len = sizeof(tBTA_HH_CBDATA);
    else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event) )
        param_len = sizeof(tBTA_HH_DEV_INFO);
    else if (BTA_HH_API_ERR_EVT == event)
        param_len = 0;
   
    status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);

   
    ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}

这个函数就是作event转换的

而调用这个函数的地方是在:



bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
{
     if (b_enable)
     {
         
          BTA_HhEnable(BTA_SEC_NONE, FALSE, bte_hh_evt);
     }
     else {
        
         BTA_HhDisable();
     }
     return BT_STATUS_SUCCESS;
}

BTA_HhEnable是在bta/hh/bta_hh_api.c中的,这个函数是注册hid host

 47
 60 void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
 61 {
 62     tBTA_HH_API_ENABLE *p_buf;
 63
 64    
 65     GKI_sched_lock();
 66     bta_sys_register(BTA_ID_HH, &bta_hh_reg);
 67     GKI_sched_unlock();
 68
 69     APPL_TRACE_ERROR0("Calling BTA_HhEnable");
 70     p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
 71
 72     if (p_buf != NULL)
 73     {
 74         memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
 75
 76         p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
 77         p_buf->p_cback = p_cback;
 78         p_buf->sec_mask = sec_mask;
 79
 80         bta_sys_sendmsg(p_buf);
 81     }
 82 }
 83

所以在注册hid host的时候,绑定了这个消息处理函数,因此后面收到消息的时候,会通过这个函数调用btif_hh_upstreams_evt来对设备节点进行操作,将相应的事件注入到设备节点,以与驱动进行事件交互。

而注册host的地方是在这里:btif_dm.c中

 

 

bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,
                                                BOOLEAN b_enable)
{
   
    switch (service_id)
    {
         case BTA_HFP_SERVICE_ID:
         case BTA_HSP_SERVICE_ID:
         {
              btif_hf_execute_service(b_enable);
         }break;
         case BTA_A2DP_SERVICE_ID:
         {
              btif_av_execute_service(b_enable);
         }break;
         case BTA_HID_SERVICE_ID:
         {
              btif_hh_execute_service(b_enable);
         }break;

         default:
              BTIF_TRACE_ERROR1("%s: Unknown service being enabled", __FUNCTION__);
              return BT_STATUS_FAIL;
    }
    return BT_STATUS_SUCCESS;
}

而btif_hh_execute_service是在btif_dm.c中执行的。

 

我们后续看下到底bta_hh_co.c中的函数对这个设备节点都做了哪些事情。

 先在的问题是,在HAL层,蓝牙协议栈是怎么使用的呢?

我们分析上面的过程:

 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
            sBluetoothInterface = btStack->get_bluetooth_interface();

为什么蓝牙协议栈是一个bluetooth_module_t的形式呢?

还有就是蓝牙协议层,是怎么和驱动层交流的

现在看下,蓝牙手柄上的按钮消息是怎么传到android系统的:

dumpsys可以知道:

  5: Broadcom Bluetooth HID

      Classes: 0x8000014b

      Path: /dev/input/event5

      Descriptor: 15d4b0db1b56c4af5d6eb4d517f062fed0422482

      Location: 

      UniqueId: 

      Identifier: bus=0x0005, vendor=0x1038, product=0x1412, version=0x001b

      KeyLayoutFile: /system/usr/keylayout/Generic.kl

      KeyCharacterMapFile: /system/usr/keychars/Generic.kcm

      ConfigurationFile: 

      HaveKeyboardLayoutOverlay: false

我们操纵蓝牙手柄的时候发现这样的信息:

[ 5600.559211] input: Broadcom Bluetooth HID as /devices/virtual/misc/uhid/input6

[ 5600.569201] hid-generic 0005:1038:1412.0003: input,hidraw1: BLUETOOTH HID v0.1b Mouse [Broadcom Bluetooth HID] on 

Hid设备的注册:


 http://blog.csdn.net/tankai19880619/article/details/11639185


http://blog.sina.com.cn/s/blog_6695f9eb0101dpzn.html


http://blog.csdn.net/tankai19880619/article/details/17447791

//-------------------------------------Android HAL层------------------------------------------------

百度文库,对android蓝牙连接流程的介绍:

http://wenku.baidu.com/link?url=Wli_9D7k5bPU7Q-Rh1WtuLL2AhE8szYEcXrOyilR6E_0EqCGJb6wJlN-LCKkSeFUeN9t70hsfP3uMQ2_XihHrH-xnq9Mmn9VznODqxU6Dou


这里有对Android HAL层的讲解:

http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html


/hardware/libhardware/modules  目录下定义了很多硬件模块

/hardware/msm7k  /hardware/qcom  /hardware/ti  /device/Samsung 

/device/moto            各个厂商平台相关的hal

这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录

1.在Bluetooth.h中定义了蓝牙模块的ID

#define BT_STACK_MODULE_ID "bluetooth"

2.com_android_bluetooth_btservice_AdapterService.cpp中根据这个ID获取蓝牙模块,参数module是硬件模块地址(相当于是一个指针)

err = hw_get_module(id, (hw_module_t const**)&module);

3.获得模块之后,打开这个硬件设备

 hw_device_t* abstraction;

        err = module->methods->open(module, id, &abstraction);

上述的module->methods->open这个open函数就是HAL提供的接口,其函数原型在hardware.h头文件中有定义,只能返回struct hw_device_t类型的指针,而在JNI方法中,我们关心的是struct hello_device_t,只有通过struct hello_device_t,我们才能获取其所有的成员函数(接HAL提供的接口函数),由于struct hello_device_t的第一个成员就是struct hw_device_t类型的数据,因此在这里可以将获取的struct hw_device_t强制转化为struct hello_device_t来用。

具体参看:

http://www.open-open.com/lib/view/open1325474434250.html


针对

        hw_device_t* abstraction;

        err = module->methods->open(module, id, &abstraction);

        if (err == 0) {

            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;

            sBluetoothInterface = btStack->get_bluetooth_interface();

我们看下abstraction的来源:


 err = hw_get_module(id, (hw_module_t const**)&module);

//Hardware.c

int hw_get_module_by_class(const char *class_id, const char *inst,

                           const struct hw_module_t **module)

{

    int status;

    int i;

    const struct hw_module_t *hmi = NULL;

    char prop[PATH_MAX];

    char path[PATH_MAX];

    char name[PATH_MAX];


    if (inst)

        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);

    else

        strlcpy(name, class_id, PATH_MAX);

    for (i=0 ; i

        if (i < HAL_VARIANT_KEYS_COUNT) {

            if (property_get(variant_keys[i], prop, NULL) == 0) {

                continue;

            }

            snprintf(path, sizeof(path), "%s/%s.%s.so",

                     HAL_LIBRARY_PATH2, name, prop);

            if (access(path, R_OK) == 0) break;


            snprintf(path, sizeof(path), "%s/%s.%s.so",

                     HAL_LIBRARY_PATH1, name, prop);

            if (access(path, R_OK) == 0) break;

        } else {

            snprintf(path, sizeof(path), "%s/%s.default.so",

                     HAL_LIBRARY_PATH1, name);

            if (access(path, R_OK) == 0) break;

        }

    }

    status = -ENOENT;

    if (i < HAL_VARIANT_KEYS_COUNT+1) {

        status = load(class_id, path, module);

    }

    return status;

}

 

cat /proc/bus/input/devices得到:

I: Bus=0005 Vendor=1038 Product=1412 Version=001b
N: Name="Broadcom Bluetooth HID"
P: Phys=
S: Sysfs=/devices/virtual/misc/uhid/input5
U: Uniq=
H: Handlers=sysrq kbd mouse4 event5
B: PROP=0
B: EV=12001f
B: KEY=110 4000 0 0 0 6 fc810 2050000 0 ffff0000 70000 fc2124a8 20f ff9f30fa c14057ff febeffdf ffefffff ffefffff fffffffe
B: REL=103
B: ABS=100 30027
B: MSC=10
B: LED=1f
这就是这个博通蓝牙HID的信息

系统调用和驱动的关系:

http://blog.sina.com.cn/s/blog_6405313801012p9r.html

HAL层框架的搭建:

http://www.2cto.com/kf/201205/132683.html

Bluedroid架构:

http://blog.csdn.net/xiaojsj111/article/details/12647923

 bluetooth services和bluetooth JNI编译出来的结果就是bluetooth.apk, bluetooth services透过bluetooth JNI,bluetooth JNI透过硬件抽象层,直接调用到bluedroid的核心协议栈,而核心协议栈通过uart driver,rfkill driver,UHID,TUN等vfs文件接口直接调用到内核空间的驱动。

Android蓝牙下层驱动

/dev/input # ls
event0  event1  event2  event3  event4  mice    mouse0  mouse1  mouse2  mouse3
/dev/input # [ 8075.222116] input: Broadcom Bluetooth HID as /devices/virtual/misc/uhid/input5
[ 8075.232058] hid-generic 0005:1038:1412.0002: input,hidraw1: BLUETOOTH HID v0.1b Mouse [Broadcom Bluetooth HID] on

/dev/input #
/dev/input #
/dev/input # ls
event0  event2  event4  mice    mouse1  mouse3
event1  event3  event5  mouse0  mouse2  mouse4

从上面的打印可以知道,在/dev/input目录下生产了一个event5的节点

 /dev/input目录下的事件都是在驱动中调用input_register_device(struct input_dev *dev)产生的。

与event对应的相关设备信息位于/proc/bus/input/devices

cat devices可以找到这个设备的信息:
I: Bus=0005 Vendor=1038 Product=1412 Version=001b
N: Name="Broadcom Bluetooth HID"
P: Phys=
S: Sysfs=/devices/virtual/misc/uhid/input5
U: Uniq=
H: Handlers=sysrq kbd mouse4 event5
B: PROP=0
B: EV=12001f
B: KEY=110 4000 0 0 0 6 fc810 2050000 0 ffff0000 70000 fc2124a8 20f ff9f30fa c14057ff febeffdf ffefffff ffefffff fffffffe
B: REL=103
B: ABS=100 30027
B: MSC=10
B: LED=1f

知道还有一个目录,是:

./sys/devices/virtual/misc/uhid/input5

这个设备节点应该是uhid驱动注册的

 

更多相关文章

  1. C语言函数以及函数的使用
  2. android 调用draw(canvas) 函数自动退出
  3. Xposed框架之函数Hook学习
  4. android 蓝牙driver的启动流程
  5. android中去掉空格--trim函数
  6. Android 蓝牙自动连接实现
  7. Android三角函数
  8. ISurfaceComposer接口有13个成员函数
  9. Android jni系统变量、函数、接口定义汇总

随机推荐

  1. 分享Android(安卓)KTX + Kotlin协程 组合
  2. android ndk 开发
  3. Unity和Android通信系列文章1——总览
  4. Android百度地图(二):百度地图sdk显示位
  5. Android(安卓)系统菜单与自定义菜单
  6. 2021年Android高级面试题,终局之战
  7. Android:Kotlin详细入门学习指南-类和对象
  8. android 安装 出现Android(安卓)Native D
  9. 2021最新Android中高级开发必知必会面试
  10. WebView中的视频播放