win7 修改MAC 地址无效的解决办法(含补充)

今天在win7下尝试修改网卡的MAC地址时,发现不生效的问题,很是费解.网上查了一些资料,发现以下文章:

<win7 修改MAC 地址无效的解决办法>

内容如下(黄色部分,此内容从以下网址复制,图片未复制 http://blog.csdn.net/xpb1980/article/details/18016865):

1.修改网卡的MAC 地址
     计算机——属性——设备管理器——网络设备器——网卡——属性

 然后点击 高级——本地管理MAC地址右边的值修改,网卡的MAC地址修改完成

2 如果用户发现没有管理本地MAC地址怎么办?

可以通过修改注册表来添加这个MAC地址键值

下面以我的笔记本位列,简述MAC地址的修改步骤:
1. 在运行中输入:regedit命令,进入注册表。
在注册表中找到下面位置:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
2. 通过查找诸如0000,0001分支中的DriverDesc的键值来查看现有网卡是在哪个分支下。(我的是在0014下)
3. 在0014子键下添加一个字符串,命名为“NetworkAddress”,键值为修改后的MAC地址,要求为连续的12个16进制数。
4. 然后在“0014”子键下的NDI\params中新建一项名为NetworkAddress的子键,在该子键下添加名为“default”的字符串,键值为修改后的MAC地址。
5. 在NetworkAddress的子键下继续建立名为“ParamDesc”的字符串,其作用为指定NetworkAddress的描述,其值可为 “MAC Address”。这样以后打开网络邻居的“属性”,双击相应的网卡就会发现有一个“高级”设置,其下存在MAC Address的选项,它就是你在注册表中加入的新项NetworkAddress,以后只要在此修改MAC地址就可以了
 3 好了按照以上方式 顺利的话你会修改成功你的MAC 地址,在WINDOWS控制台  CMD命令,IPCONFIG -all  发现你的MAC 地址修改完成 那么恭喜你 你已经修改了你的MAC 地址,但是有时候你会发现修改无效

 

以上在WINDOWS XP 下面修改 完全是没有问题的

在WINDOW7 下面MAC 地址不能随机生成MAC 地址,修改时要注意如下规则:

从左往右第二个字符必须2,6,A,E其中之一,

列如:

02:00:00:00:00:00 —有效

 06:00:00:00:00:00 —有效

 0A:00:00:00:00:00 —有效

 0E:00:00:00:00:00 —有效

 不知道是不是WIN7 的一个BUG 还是什么

文章的最后,提到,第一个字节必须为02,06,0a,0e,按照这个规则改下来,好像也确实是那么一回事.

这里不得不感叹一下,真的是天下文章一大抄啊,同样的文字,在N个网站上被找到.

这个就不吐槽了,因为我也抄了上面的文字,真是难为情.

来研究一下最后的结论,”不知道是不是WIN7的一个BUG”,直觉告诉我,这肯定不是bug,做windows的人,肯定有他的想法.

直觉告诉我,得去查一下MAC地址的每一位定义.

发现,最高字节的最低一位,是用来表示单播和多播的,笔记本的地址,按照理解应该算单播吧,所以这个是0应该不过分;最高字节的倒数第二低位是表示universally administered address 和locally administered address的,如果是修改的地址,那么按照规则来说,应该定义为locally address,因此这一位肯定得是1啊.

所以按照上面的理解,最高字节应该是0bxxxxxx10才对,符合上述规则的,而参考文章的02,06,0a,0e的最低两位不都是10么?

所以,这肯定不是win7的bug了,而是我们想的不够多.

最后,又做了一些额外的测试,将第一个字节改为0x16,0xa6测试,发现修改也是生效的,所以,并不是之前文章所说的02,06,0a,0e才行.

这也符合了我之前的猜想,最高字节必须符合0bxxxxxx10这个规则.

至于最高字节其他值,如0x22,0xFE等等,有兴趣的朋友也可以去测试一下.

“Beyond Compare 许可证密钥被撤销” 的解决办法(转)

解决方法:

删除相应目录

根据系统进入相应文件夹,删除所有文件。

WinXP   C:\Documents and Settings\[Your User Name]\Application Data\Scooter Software\Beyond Compare 3\
Win7    C:\Users\[Your User Name]\AppData\Roaming\Scooter Software\Beyond Compare 3\

重新安装

重新打开 Beyond Compare,提示需要安装,重新安装,输入秘钥,问题解决。

以上内容转自:http://blog.csdn.net/loosen17/article/details/63784913

我再补充一下:

实际测试下来,不需要重新安装,只需要删除对应文件,然后再打开compare软件,会提示你激活,再一次输入秘钥即可.

[转]蓝牙配对过程分析(经典蓝牙)

打开手机/手表的蓝牙,就能在列表中看到扫描到的蓝牙,点击就可以实现配对功能。目前手表支持与所有设备的配对,但是仅支持与耳机类型的设备进行连接

安全简易配对SSP(Secure simple pairing),蓝牙2.0之后配对方式,简易安全配对一共有四种,其中Out of Band很少使用到,具体如下: 
Numeric Comparison 
配对双方都显示一个6位的数字,由用户来核对数字是否一致,并输入Yes/No,两端Yes表示一致即可配对,可以防止中间人攻击。 
使用场景:两端设备可以弹出6位十进制数,并且有yes和no按钮。

Passkey Entry 
配对目标输入一个在本地设备上显示的6位数字,输入正确即可配对,并可以防止中间人攻击。 
使用场景:一端设备可以显示,另一端设备可以输入。

Just Works 
不会进行鉴权,不能防止中间人攻击用于配对没有显示没有输入的设备,主动发起连接即可配对,用户看不到配对过程,不可以防止中间人攻击,例如连接蓝牙耳机。 
使用场景:用于即不能显示6位随机数,也不能输入的设备。

Out of Band 
两设备的通过别的途径交换配对信息,例如一些NFC蓝牙音箱。

一、原生应用设置界面的packages\Settings

目录:android\packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothDevicePreference.java

void onClicked() { int bondState = mCachedDevice.getBondState(); if (mCachedDevice.isConnected()) {
        askDisconnect();//断开连接 } else if (bondState == BluetoothDevice.BOND_BONDED) {
        mCachedDevice.connect(true);//已经配对了就连接 } else if (bondState == BluetoothDevice.BOND_NONE) {
        pair();//没有配对的话就去配对 }
}
private void pair() { if (!mCachedDevice.startPairing()) { Utils.showError(getContext(), mCachedDevice.getName(), R.string.bluetooth_pairing_error_message);
    } else {
        final Context context = getContext(); SearchIndexableRaw data = new SearchIndexableRaw(context); data.className = BluetoothSettings.class.getName(); data.title = mCachedDevice.getName(); data.screenTitle = context.getResources().getString(R.string.bluetooth_settings); data.iconResId = R.drawable.ic_settings_bluetooth; data.enabled = true; Index.getInstance(context).updateFromSearchIndexableData(data); }
}

Y:\HLOS\frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java

public boolean startPairing() { // Pairing is unreliable while scanning, so cancel discovery if (mLocalAdapter.isDiscovering()) {
            mLocalAdapter.cancelDiscovery();//如果设备正在搜索,就取消搜索 } if (!mDevice.createBond()) {//配对 return false;
        }

        mConnectAfterPairing = true; // auto-connect after pairing return true;
    }

二、framework层配对逻辑

Y:\HLOS\frameworks\base\core\java\android\bluetooth\BluetoothDevice.java

public boolean createBond() { if (sService == null) {
            Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); return false;
        } try {
            Log.i(TAG, "createBond() for device " + getAddress() + " called by pid: " + Process.myPid() + " tid: " + Process.myTid()); return sService.createBond(this, TRANSPORT_AUTO);//跨进程调用到AdapterService中的方法 } catch (RemoteException e) {Log.e(TAG, "", e);} return false;
    }

三、frameworks的aidl文件

private static IBluetooth sService;

HLOS\frameworks\base\core\java\android\bluetooth\IBluetooth.aidl 
boolean createBond(in BluetoothDevice device); 
这个是属于跨进程通信的方法,通过IBluetooth.aidl文件,调用到AdapterService.java中的createBond方法

四、从framework跨进程调到packages\Bluetooth

Y:\HLOS\packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java

public boolean createBond(BluetoothDevice device, int transport) { if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                Log.w(TAG, "createBond() - Not allowed for non-active user"); return false;
            }

            AdapterService service = getService(); if (service == null) return false; return service.createBond(device, transport, null);//调用本服务的createBond }

同在AdapterService文件下

boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { return false;
        } // Multicast: Do not allow bonding while multcast A2dpService a2dpService = A2dpService.getA2dpService(); if (a2dpService != null &&
            a2dpService.isMulticastFeatureEnabled() &&
            a2dpService.isMulticastOngoing(null)) {
            Log.i(TAG,"A2dp Multicast is ongoing, ignore bonding"); return false;
        } // Pairing is unreliable while scanning, so cancel discovery // Note, remove this when native stack improves cancelDiscoveryNative();//配对过程,取消扫描 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
        msg.obj = device;
        msg.arg1 = transport; if (oobData != null) {
            Bundle oobDataBundle = new Bundle();
            oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
            msg.setData(oobDataBundle);
        }
        mBondStateMachine.sendMessage(msg);//给配对的状态机发消息,创建创建了BondStateMachine.CREATE_BOND return true;
    }

在Y:\HLOS\packages\apps\Bluetooth\src\com\android\bluetooth\btservice\BondStateMachine.java 
处理服务发送过来的消息

@Override public boolean processMessage(Message msg) {

            BluetoothDevice dev = (BluetoothDevice)msg.obj;
            DeviceProperties devProp = mRemoteDevices.getDeviceProperties(dev); boolean result = false; if (mDevices.contains(dev) && msg.what != CANCEL_BOND &&
                   msg.what != BONDING_STATE_CHANGE && msg.what != SSP_REQUEST &&
                   msg.what != PIN_REQUEST) {
                 deferMessage(msg); return true;
             }

            Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); switch (msg.what) { case CREATE_BOND:
                    OobData oobData = null; if (msg.getData() != null)
                        oobData = msg.getData().getParcelable(OOBDATA);

                    result = createBond(dev, msg.arg1, oobData, false); break;
                    、、、
                    }
            }
private boolean createBond(BluetoothDevice dev, int transport, OobData oobData, boolean transition) { if(mAdapterService == null) return false; if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
            infoLog("Bond address is:" + dev); byte[] addr = Utils.getBytesFromAddress(dev.getAddress()); boolean result; if (oobData != null) {//判读是否借助其他硬件进行无绑定配对 result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
            } else {
                result = mAdapterService.createBondNative(addr, transport);//调用到JNI层,进行配对 } if (!result) {
                sendIntent(dev, BluetoothDevice.BOND_NONE,
                           BluetoothDevice.UNBOND_REASON_REMOVED); return false;
            } else if (transition) {
                transitionTo(mPendingCommandState);
            } return true;
        } return false;
    } 

五、packages\Bluetooth的java层调到jini层的cpp文件

Y:\HLOS\packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr;
    jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL); if (addr == NULL) {
        jniThrowIOException(env, EINVAL); return result;
    } int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);//该接口调用到hal层的配对函数 env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return result;
} 

六、hal层createBond的调用

Y:\HLOS\system\bt\btif\src\bluetooth.c

static int create_bond(const bt_bdaddr_t *bd_addr, int transport)
{ /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_dm_create_bond(bd_addr, transport);
}

Y:\HLOS\system\bt\btif\src\btif_dm.c

bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr, int transport)
{
    btif_dm_create_bond_cb_t create_bond_cb;
    create_bond_cb.transport = transport;
    bdcpy(create_bond_cb.bdaddr.address, bd_addr->address);

    bdstr_t bdstr;
    BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport); if (pairing_cb.state != BT_BOND_STATE_NONE) return BT_STATUS_BUSY;

    btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CREATE_BOND, pairing_cb.state);//添加了绑定事件 btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND,
                          (char *)&create_bond_cb, sizeof(btif_dm_create_bond_cb_t), NULL);//cotext是开辟了上下文的意思,这里create_bond_cb已经包含了要绑定的蓝牙地址,会分别发送给底层两部分,最后会调用btif_dm_generic_evt return BT_STATUS_SUCCESS;
}

Y:\HLOS\system\bt\btif\src\btif_dm.c

static void btif_dm_generic_evt(UINT16 event, char* p_param)
{
    BTIF_TRACE_EVENT("%s: event=%d", __FUNCTION__, event); switch(event)
    { case BTIF_DM_CB_DISCOVERY_STARTED:
        {
            HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STARTED);
        } break; case BTIF_DM_CB_CREATE_BOND://走这一路去配对 {
            pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
            btif_dm_create_bond_cb_t *create_bond_cb = (btif_dm_create_bond_cb_t*)p_param;
            btif_dm_cb_create_bond(&create_bond_cb->bdaddr, create_bond_cb->transport);
        } break; case BTIF_DM_CB_REMOVE_BOND:
        {
            btif_dm_cb_remove_bond((bt_bdaddr_t *)p_param);
        } break;
        、、、
    }
    、、、
}
static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transport)
{
    BOOLEAN is_hid = check_cod(bd_addr, COD_HID_POINTING);
    bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING); #if BLE_INCLUDED == TRUE int device_type; int addr_type;
    bdstr_t bdstr;
    bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)); if (transport == BT_TRANSPORT_LE)
    { if (!btif_config_get_int((char const *)&bdstr,"DevType", &device_type))
        {
            btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
        } if (btif_storage_get_remote_addr_type(bd_addr, &addr_type) != BT_STATUS_SUCCESS)
        {
            btif_storage_set_remote_addr_type(bd_addr, BLE_ADDR_PUBLIC);
        }
    } if((btif_config_get_int((char const *)&bdstr,"DevType", &device_type) &&
       (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
       (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) || (transport == BT_TRANSPORT_LE))
    {
        BTA_DmAddBleDevice(bd_addr->address, addr_type, device_type);
    } #endif #if BLE_INCLUDED == TRUE if(is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0) #else if(is_hid) #endif { int status;
        status = btif_hh_connect(bd_addr);//连接? if(status != BT_STATUS_SUCCESS)
            bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);//绑定状态发生变化时,这里开始回调 } else {
        BTA_DmBondByTransport((UINT8 *)bd_addr->address, transport);//第一次调用会走这里 } /*  Track  originator of bond creation  */ pairing_cb.is_local_initiated = TRUE;

} 

Y:\HLOS\system\bt\bta\dm\bta_dm_api.c

void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport)
{
    tBTA_DM_API_BOND *p_msg =
        (tBTA_DM_API_BOND *)osi_malloc(sizeof(tBTA_DM_API_BOND)); p_msg->hdr.event = BTA_DM_API_BOND_EVT; bdcpy(p_msg->bd_addr, bd_addr); p_msg->transport = transport;//消息包装 bta_sys_sendmsg(p_msg);//发送到另一个线程 }

七、蓝牙协议栈给线程间消息的收发

bta_sys_sendmsg这是蓝牙协议栈的进程间收发消息的机制,不是三言两语能说清楚的,若想了解,可以参考android bluedroid协议栈里面的各个组件之间的消息处理机制 
根据BTA_DM_API_BOND_EVT这个类型,可以找到消息接收的地方 
Y:\HLOS\system\bt\bta\dm\bta_dm_main.c

const tBTA_DM_ACTION bta_dm_action[] =
{

    /* device manager local device API events */
    bta_dm_enable,            /* 0 BTA_DM_API_ENABLE_EVT */
    bta_dm_disable,           /* 1 BTA_DM_API_DISABLE_EVT */
    bta_dm_set_dev_name,      /* 2 BTA_DM_API_SET_NAME_EVT */
    bta_dm_set_visibility,    /* 3 BTA_DM_API_SET_VISIBILITY_EVT */
    bta_dm_acl_change,        /* 8 BTA_DM_ACL_CHANGE_EVT */
    bta_dm_add_device,        /* 9 BTA_DM_API_ADD_DEVICE_EVT */
    bta_dm_close_acl,        /* 10 BTA_DM_API_ADD_DEVICE_EVT */

    /* security API events */
    bta_dm_bond,              /* 11 BTA_DM_API_BOND_EVT */
    bta_dm_bond_cancel,       /* 12 BTA_DM_API_BOND_CANCEL_EVT */
    bta_dm_pin_reply,         /* 13 BTA_DM_API_PIN_REPLY_EVT */

    /* power manger events */
    bta_dm_pm_btm_status,     /* 16 BTA_DM_PM_BTM_STATUS_EVT */
    bta_dm_pm_timer,          /* 17 BTA_DM_PM_TIMER_EVT*/

    /* simple pairing events */
    bta_dm_confirm,           /* 18 BTA_DM_API_CONFIRM_EVT */

    bta_dm_set_encryption,    /* BTA_DM_API_SET_ENCRYPTION_EVT */

    /* out of band pairing events */
    bta_dm_loc_oob,           /* 20 BTA_DM_API_LOC_OOB_EVT */
    bta_dm_ci_io_req_act,     /* 21 BTA_DM_CI_IO_REQ_EVT */
    bta_dm_ci_rmt_oob_act,    /* 22 BTA_DM_CI_RMT_OOB_EVT */
、、、
}

Y:\HLOS\system\bt\bta\dm\bta_dm_act.c

void bta_dm_bond (tBTA_DM_MSG *p_data)
{
    tBTM_STATUS status; tBTA_DM_SEC sec_event; char        *p_name; if (p_data->bond.transport == BTA_TRANSPORT_UNKNOWN)//这里看transport类型,走不通渠道
        status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 ); else
        status = BTM_SecBondByTransport ( p_data->bond.bd_addr, p_data->bond.transport, 0, NULL, 0 ); if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED))
    {

        memset(&sec_event, 0, sizeof(tBTA_DM_SEC)); bdcpy(sec_event.auth_cmpl.bd_addr, p_data->bond.bd_addr); p_name = BTM_SecReadDevName(p_data->bond.bd_addr); if (p_name != NULL)
        {
            memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN-1)); sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0; } /*      taken care of by memset [above]
        sec_event.auth_cmpl.key_present = FALSE;
        sec_event.auth_cmpl.success = FALSE;
*/ sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND; if (status == BTM_SUCCESS)
        {
            sec_event.auth_cmpl.success = TRUE; }
        else
        { /* delete this device entry from Sec Dev DB */ bta_dm_remove_sec_dev_entry(p_data->bond.bd_addr); }
        bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event); }

}

Y:\HLOS\system\bt\stack\btm\btm_sec.c

tBTM_STATUS BTM_SecBondByTransport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
                                    UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
{ #if SMP_INCLUDED == TRUE tBT_DEVICE_TYPE     dev_type;
    tBLE_ADDR_TYPE      addr_type;

    BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
    /* LE device, do SMP pairing */ if ((transport == BT_TRANSPORT_LE && (dev_type & BT_DEVICE_TYPE_BLE) == 0) ||
        (transport == BT_TRANSPORT_BR_EDR && (dev_type & BT_DEVICE_TYPE_BREDR) == 0))
    { return BTM_ILLEGAL_ACTION;
    } #endif return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
}

Y:\HLOS\system\bt\stack\btm\btm_sec.c

tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
                                       UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
{
    tBTM_SEC_DEV_REC *p_dev_rec;
    tBTM_STATUS      status;
    UINT8            *p_features;
    UINT8            ii;
    tACL_CONN        *p= btm_bda_to_acl(bd_addr, transport);
    BTM_TRACE_API ("btm_sec_bond_by_transport BDA: %02x:%02x:%02x:%02x:%02x:%02x",
                    bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);

    BTM_TRACE_DEBUG("btm_sec_bond_by_transport: Transport used %d" , transport); /* Other security process is in progress */ if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
    {
        BTM_TRACE_ERROR ("BTM_SecBond: already busy in state: %s", btm_pair_state_descr(btm_cb.pairing_state)); return(BTM_WRONG_MODE);
    } if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL)
    { return(BTM_NO_RESOURCES);
    } if (!controller_get_interface()->get_is_ready()) { BTM_TRACE_ERROR ("%s controller module is not ready", __func__); return(BTM_NO_RESOURCES);
    } BTM_TRACE_DEBUG ("before update sec_flags=0x%x", p_dev_rec->sec_flags);

    /* Finished if connection is active and already paired */ if ( ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
         &&  (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
#if (BLE_INCLUDED == TRUE)
        ||((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
         &&  (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
#endif

         ) { BTM_TRACE_WARNING("BTM_SecBond -> Already Paired"); return(BTM_SUCCESS);
    }

    /* Tell controller to get rid of the link key if it has one stored */ if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS) return(BTM_NO_RESOURCES);

    /* Save the PIN code if we got a valid one */ if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0)) { btm_cb.pin_code_len = pin_len; p_dev_rec->pin_code_length = pin_len;
        memcpy (btm_cb.pin_code, p_pin, PIN_CODE_LEN);
    }

    memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);

    btm_cb.pairing_flags = BTM_PAIR_FLAGS_WE_STARTED_DD;

    p_dev_rec->security_required = BTM_SEC_OUT_AUTHENTICATE;
    p_dev_rec->is_originator     = TRUE; if (trusted_mask)
        BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask); #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE if (transport == BT_TRANSPORT_LE)
    {
        btm_ble_init_pseudo_addr (p_dev_rec, bd_addr);
        p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK; if (SMP_Pair(bd_addr) == SMP_STARTED)
        {
            btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
            p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
            btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE); return BTM_CMD_STARTED;
        }

        btm_cb.pairing_flags = 0; return(BTM_NO_RESOURCES);
    } #endif p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
                                  | BTM_SEC_ROLE_SWITCHED  | BTM_SEC_LINK_KEY_AUTHED);

    BTM_TRACE_DEBUG ("after update sec_flags=0x%x", p_dev_rec->sec_flags); if (!controller_get_interface()->supports_simple_pairing()) {
        /* The special case when we authenticate keyboard. Set pin type to fixed */
        /* It would be probably better to do it from the application, but it is */
        /* complicated */ if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL)
            && (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD)
            && (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED)) { btm_cb.pin_type_changed = TRUE; btsnd_hcic_write_pin_type (HCI_PIN_TYPE_FIXED);
        }
    } for (ii = 0; ii <= HCI_EXT_FEATURES_PAGE_MAX; ii++) { p_features = p_dev_rec->features[ii];
        BTM_TRACE_EVENT("  remote_features page[%1d] = %02x-%02x-%02x-%02x",
                         ii, p_features[0], p_features[1], p_features[2], p_features[3]);
        BTM_TRACE_EVENT("                              %02x-%02x-%02x-%02x",
                             p_features[4], p_features[5], p_features[6], p_features[7]);
    }

    BTM_TRACE_EVENT ("BTM_SecBond: Remote sm4: 0x%x  HCI Handle: 0x%04x", p_dev_rec->sm4, p_dev_rec->hci_handle); #if BTM_SEC_FORCE_RNR_FOR_DBOND == TRUE p_dev_rec->sec_flags &= ~BTM_SEC_NAME_KNOWN; #endif /* If connection already exists... */ if (p && p->hci_handle != BTM_SEC_INVALID_HANDLE)
    { if (!btm_sec_start_authentication (p_dev_rec)) return(BTM_NO_RESOURCES);

        btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ); /* Mark lcb as bonding */ l2cu_update_lcb_4_bonding (bd_addr, TRUE); return(BTM_CMD_STARTED);
    }

    BTM_TRACE_DEBUG ("sec mode: %d sm4:x%x", btm_cb.security_mode, p_dev_rec->sm4); if (!controller_get_interface()->supports_simple_pairing()
        || (p_dev_rec->sm4 == BTM_SM4_KNOWN)) { if ( btm_sec_check_prefetch_pin (p_dev_rec) ) return (BTM_CMD_STARTED);
    } if ((btm_cb.security_mode == BTM_SEC_MODE_SP ||
         btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
         btm_cb.security_mode == BTM_SEC_MODE_SC) &&
         BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
        /* local is 2.1 and peer is unknown */ if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0) {
            /* we are not accepting connection request from peer * -> RNR (to learn if peer is 2.1)
             * RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
            btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
            BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
        } else { /* We are accepting connection request from peer */ btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
        }
        BTM_TRACE_DEBUG ("State:%s sm4: 0x%x sec_state:%d",
            btm_pair_state_descr (btm_cb.pairing_state), p_dev_rec->sm4, p_dev_rec->sec_state); return BTM_CMD_STARTED;
    } /* both local and peer are 2.1  */ status = btm_sec_dd_create_conn(p_dev_rec); if (status != BTM_CMD_STARTED)
    {
        btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);//改变配对的状态
    } return status;
}

这里代码很多,每一句都看懂不现实,现摘出重要的一段看

 if (!controller_get_interface()->supports_simple_pairing())//这里做一个判断,看是否支持简单配对方式
    {
        /* The special case when we authenticate keyboard. Set pin type to fixed */
        /* It would be probably better to do it from the application, but it is */
        /* complicated */ if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL)
            && (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD)
            && (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED)) { btm_cb.pin_type_changed = TRUE; btsnd_hcic_write_pin_type (HCI_PIN_TYPE_FIXED);//这里就可以看到在和hci层打交道了
        }
    }

八、通过HCI向底层发送命令进行控制

BOOLEAN btsnd_hcic_write_pin_type (UINT8 type)
{
    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
    UINT8 *pp = (UINT8 *)(p + 1);

    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1;
    p->offset = 0;

    UINT16_TO_STREAM (pp, HCI_WRITE_PIN_TYPE);
    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_PARAM1);

    UINT8_TO_STREAM (pp, type);

    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);//这里是向hci层发命令, return (TRUE);
} 

可以看出,这里是通过和hci层的通信,host告诉controlor蓝牙地址、数据、命令等,从而控制其底层硬件发起配对操作

本文转自:https://blog.csdn.net/w1107845086/article/details/79636090

【转】蓝牙5.0新特性速览

原文地址:http://www.wowotech.net/bluetooth/bluetooth_5_0_overview.html

1. 前言

2016年12月6日,蓝牙SIG发布了5.0版本的核心规范,该规范从距离、速度等多个方面,对BLE进行了增强,蓝牙官网的总结如下[1]

With the launch of Bluetooth 5, Bluetooth® technology continues to evolve to meet the needs of the industry as the global wireless standard for simple, secure connectivity. With 4x range, 2x speedand 8x broadcasting message capacity, the enhancements of Bluetooth 5 focus on increasing the functionality of Bluetooth for the IoT. These features, along with improved interoperability and coexistence with other wireless technologies, continue to advance the IoT experience by enabling simple and effortless interactions across the vast range of connected devices.

相比蓝牙4.2,新增的特性包括[3]

Several new features are introduced in the Bluetooth Core Specification 5.0 
Release. The major areas of improvement are: 
• Slot Availability Mask (SAM) 
• 2 Msym/s PHY for LE 
• LE Long Range 
• High Duty Cycle Non-Connectable Advertising 
• LE Advertising Extensions 
• LE Channel Selection Algorithm #2

下面对一些比较有意思的做个简单的介绍(后续有时间会做比较细致的分析)。

2. 2 Msym/s PHY for LE

在蓝牙4.2 1M符号速率(symbol rate)的PHY(称作LE 1M PHY)基础上,增加2M符号速率的PHY(称作LE 2M PHY),二者的区别为:

1)LE 1M PHY的符号速率为1Msym/s,为必选PHY(每个LE设备必须支持),支持ECC(error correction coding,可选),根据不同的编码方式,支持3种bit速率:1Mb/s(LE 1M)、500Bb/s(LE Coded)和125Kb/s(LE Coded)。

2)LE 2M PHY的符号速率为2Msym/s,为可选PHY,不支持ECC(error correction coding),bit速率为2Mb/s(LE 2M,uncoded)。

3. LE Long Range

将最大的发送功率,从4.0/4.1/4.2中的10mW增大到5.0的100mW(够粗暴,哈哈)。

关于BLE的发射功率,spec中有张表,贴过来供大家参考:

ble_tx_power

4. High Duty Cycle Non-Connectable Advertising

蓝牙4.0将Scannable Undirected和Non-connectable Undirected两种Advertising Event的advInterval的最小值限制为100ms,这就限制了BLE广播的最高速率(2.48kbps,参考[4])。而蓝牙5.0不再区别对待,将最小值统一限制为20ms,从理论上讲,最高的广播速率就可以提高5倍(12.4kbps)。

5. LE Advertising Extensions

这个扩展比较好玩。

蓝牙4.0/4.1/4.2的广播通道(可参考[4]),比较简单、直接,预留3个(可以更少)Physical Channel,用于传输Advertising Event。可传输的数据长度为6~37 octets(加上了协议开销)。

而蓝牙5.0,则搞出了新花样(实用性大增,从此之后就没有连接的必要了啊!),总结为:

1)抽象出primary advertising channel和secondary advertising channel的概念。

2)primary advertising channel就是蓝牙4.2及以前的、预留出的、用于传输Advertising Event。

3)而secondary advertising channel,则直接复用了剩余的37个data channel,用于传输扩展的Advertising Event(称作Extended Advertising Event)。此时可传输的数据长度为0 ~ 255 octets,相比之前的37,暴增了很多倍,好爽啊!!

4)因此,在原有的用于传输广播数据的PDU(ADV_IND、ADV_DIRECT_IND、ADV_NONCONN_IND以及ADV_SCAN_IND,称作legacy PDUs)的基础上,增加了扩展的PDU(ADV_EXT_IND、AUX_ADV_IND、AUX_SYNC_IND以及AUX_CHAIN_IND,称作extended advertising PDUs)。

5)相应的,Advertising Event也分为Legacy Advertising Event和Extenteded Advertising Event。

【转】蓝牙5-由下而上的技术变革

【导读】 蓝牙5核心规格自2016年12月份推出至今,已有不少蓝牙5.0的产品通过了蓝牙认证,面向了市场。蓝牙5为推动物联网高速发展,显著提升了蓝牙的传播距离,速度和广播消息能力等方面,使得无线连接变得更加简单且安全。那么,蓝牙5是如何实现这些方面的升级呢?
1.蓝牙5的新PHY

蓝牙5的技术提升是基于新的PHY实现的,可以说是一个由下而上的技术革新。蓝牙5的核心规格里有LE 1M,LE 2M和LE Coded。这些不同的PHY有什么区别,又有些什么实际意义呢?


LE 1M PHY
对于蓝牙5,符号速率可以有多个选择,但LE 1M是必选项,是必须支持的。LE 1M是蓝牙4中使用的PHY,在蓝牙5中也会使用到,并且蓝牙5和蓝牙4.2的数据包类型也是一样的,有效载荷均为255个字节,因此当蓝牙5使用LE 1M的PHY时,吞吐量,功耗,传输距离等和蓝牙4.2是一样的。相对于蓝牙4.0,4.1的LE部分,数据包长度变为了8倍,可为mesh及其他网络协议传播更多的数据量,为面向非连接的应用提供了更多的灵活性。
LE 2M PHY
LE 2M PHY是蓝牙5新增的PHY,在不改变数据包类型的情况下,将原来的传输包和接收包所需要的时间缩短为原来的一半,在不考虑数据包间隔时间的情况下,将蓝牙传输的理论速率变成了蓝牙4的俩倍,为后续的高级音频,图像传输应用打下了坚实的基础。

2.png

根据蓝牙技术联盟的资料,可以看到蓝牙5的带宽比4.0/4.1版本高4.6倍,比4.2版本高约1.7倍。更高的带宽可以转化为更高的速度,不仅增强了数据传输速度,优化了蓝牙应用的响应时间,进一步提升了蓝牙产品的使用体验。在2M的速率下,蓝牙的功耗也会随之增高,相对于原来蓝牙4 LE部分10dBm的功率限制,蓝牙5的LE将功率限制在20dBm,直接提高了10倍的功率限值。在传输距离上,LE 2M反而会比LE 1M更短一些。
LE Coded PHY
蓝牙5是依靠LE Coded PHY来实现更远的传播距离的,LE Coded PHY也是使用1M的符号速率,要想增加蓝牙的有效传输距离,就要保证在更远的距离可以实现和原来相同的可以容忍的误码率,但蓝牙5在增加有效传输距离的同时没有增加蓝牙的发射机功率,而是增加了新的处理错误和检测错误的机制,即在传输的数据包中额外添加FEC前向纠错编码,从而达到更远的有效距离。

3.png

蓝牙5的LE Coded PHY又分为LE Coded S=2和LE Coded S=8两种编码方案。在S=2中,FEC编码使用卷积编码器,通过二分之一的码率输出数据位,即2个编码位代替原来一个数据位,这种编码方案下,理论有效数据传输速率降低为500Kb/s,但由于加强了纠错能力,提高了灵敏度,传输距离可以达到蓝牙4低功耗的2倍。在S=8中,通过卷积编码器以八分之一的码率输出数据,8个编码位代替原来一个数据位,理论有效数据传输速率为125Kb/s,纠错能力以及抗干扰能力大大加强,传输距离可以达到蓝牙4低功耗的4倍。

4.png

2.蓝牙5的光明前景
    蓝牙5的技术革新将在许多领域产生重大影响,并且将继续定位于物联网的低功耗技术。通过蓝牙5新的HCI(主机控制器接口)命令,可以在传输和接收时选择不同的PHY,对于不同的应用场景,可以有更好的效果。更快的传输速率,可以给用户更好的体验,更远的传输距离,完全可以覆盖整个房间甚至整个商场的无线设备,为进一步的物联网带来了想象空间。

本文转自:http://www.morlab.com/news/hyzx/2902.html