<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>BLE - 标签 - 有价值炮灰</title>
        <link>https://evilpan.com/tags/ble/</link>
        <description>BLE - 标签 - 有价值炮灰</description>
        <generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>i@pppan.net (evilpan)</managingEditor>
            <webMaster>i@pppan.net (evilpan)</webMaster><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright><lastBuildDate>Sun, 11 Jul 2021 12:40:00 &#43;0800</lastBuildDate><atom:link href="https://evilpan.com/tags/ble/" rel="self" type="application/rss+xml" /><item>
    <title>Android 蓝牙源码学习笔记</title>
    <link>https://evilpan.com/2021/07/11/android-bt/</link>
    <pubDate>Sun, 11 Jul 2021 12:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2021/07/11/android-bt/</guid>
    <description><![CDATA[<p>上文介绍了蓝牙基本原理和潜在的攻击面，但实现部分介绍不多。本文作为补充，以 Android 中的蓝牙协议栈为例，学习并了解在实际系统中蓝牙的工程实现。</p>
<h1 id="术语" class="headerLink">
    <a href="#%e6%9c%af%e8%af%ad" class="header-mark"></a>术语</h1><p>在阅读源码的过程中发现许多函数名称带有意义不明的缩写，下面是笔者整理的一些缩写及其对应含义:</p>
<ul>
<li>BTIF: Bluetooth Interface</li>
<li>BTU : Bluetooth Upper Layer</li>
<li>BTM: Bluetooth Manager</li>
<li>BTE: Bluetooth embedded system</li>
<li>BTA :Blueetooth application layer</li>
<li>CO: call out</li>
<li>CI: call in</li>
<li>HF : Handsfree Profile</li>
<li>HH: HID Host Profile</li>
<li>HL: Health Device Profile</li>
<li>av: audio/vidio</li>
<li>ag: audio gateway</li>
<li>ar: audio/video registration</li>
<li>gattc: GATT client</li>
</ul>
<h1 id="android-bluetooth-stack" class="headerLink">
    <a href="#android-bluetooth-stack" class="header-mark"></a>Android Bluetooth Stack</h1><p>安卓中蓝牙协议栈主要分为三个时期，上古时期使用的是<code>BlueZ</code>，后来在4.2之后自己独立出来称为<code>BlueDroid</code>，现在好像又改名叫<code>Fluoride</code>了。BlueZ时期和PC上的结构差不多，但是安卓上不使用DBus IPC，因此需要将这部分代码去除，其他部分可参考BlueZ的介绍。</p>
<h2 id="70" class="headerLink">
    <a href="#70" class="header-mark"></a>7.0</h2><p>在Android&lt;=7.0时期，蓝牙协议栈的实现架构如下:</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-11-android-bt/0.png'   alt="bd70"  ></p>
<h2 id="80" class="headerLink">
    <a href="#80" class="header-mark"></a>8.0</h2><p>Android 8.0 以后对蓝牙协议栈进行了重构，主要优化是使用HIDL来取代之前的硬件抽象层，方便厂商的接口集成:</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-11-android-bt/1.png'   alt="bd80"  ></p>
<h1 id="实现分析" class="headerLink">
    <a href="#%e5%ae%9e%e7%8e%b0%e5%88%86%e6%9e%90" class="header-mark"></a>实现分析</h1><p>Android蓝牙协议栈的实现在<a href="https://android.googlesource.com/platform/system/bt" target="_blank" rel="noopener noreferrer">system/bt</a>目录中，本节记录下其代码分析的过程，使用的是 Android 10 分支(ae35d7765)。</p>
<p>首先，该目录下包含1000+文件，有点无从入手。一般遇到这种情况我们都是从具体的入口函数出发，比如main函数，但这里并不是一个单纯的客户端程序。蓝牙协议栈一方面是以系统服务的方式提供接口，另一方面也以client的方式给应用程序提供SDK，不管怎样，最终都是需要经过HCI协议去与Controller进行交互。</p>
<p>对于BlueZ而言，蓝牙协议栈部分在内核中实现，socket系统调用提供了<code>AF_BLUETOOTH</code>的 family，可以支持获取HCI、L2CAP、RFCOMM类型的socket；但对于BlueDroid而言，协议栈是在用户层实现的，内核只暴露出HCI(USB/UART)的接口。因此，我们可以从HCI出发，自底向上进行分析，也可以参考上面的框架图，从用户应用程序开始，自顶向下进行分析。</p>
<h2 id="用户层" class="headerLink">
    <a href="#%e7%94%a8%e6%88%b7%e5%b1%82" class="header-mark"></a>用户层</h2><p>首先从用户接口出发，参考Android的开发者文档是如何发现设备以及创建蓝牙连接的:</p>
<ul>
<li><a href="https://developer.android.com/guide/topics/connectivity/bluetooth" target="_blank" rel="noopener noreferrer">https://developer.android.com/guide/topics/connectivity/bluetooth</a></li>
<li><a href="https://developer.android.com/guide/topics/connectivity/bluetooth-le" target="_blank" rel="noopener noreferrer">https://developer.android.com/guide/topics/connectivity/bluetooth-le</a></li>
</ul>
<p>以BR/EDR为例，其中需要注意的是paired和connected的区别:</p>
<ul>
<li><strong>paired</strong> 表示两个设备知道彼此的存在，并且已经协商好了链路秘钥(Link Key)，可用该秘钥来进行认证和创建加密链接</li>
<li><strong>connected</strong> 表示两个已经配对的设备创建了一个RFCOMM链接，共享一个RFCOMM channel</li>
</ul>
<p>Android使用蓝牙接口的流程大致如下:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">java</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-1" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// 获取本地适配器</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">BluetoothAdapter</span><span class="w"> </span><span class="n">bluetoothAdapter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BluetoothAdapter</span><span class="p">.</span><span class="na">getDefaultAdapter</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// 开启蓝牙，需要权限</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">bluetoothAdapter</span><span class="p">.</span><span class="na">isEnabled</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Intent</span><span class="w"> </span><span class="n">enableBtIntent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Intent</span><span class="p">(</span><span class="n">BluetoothAdapter</span><span class="p">.</span><span class="na">ACTION_REQUEST_ENABLE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">startActivityForResult</span><span class="p">(</span><span class="n">enableBtIntent</span><span class="p">,</span><span class="w"> </span><span class="n">REQUEST_ENABLE_BT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">//</span><span class="w"> </span><span class="n">Discover</span><span class="err">、</span><span class="n">Pair</span><span class="err">、</span><span class="n">Connect</span></span></span></code></pre>
</div>
<p>以设置本机蓝牙可被发现(300秒)为例，应用层代码为:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">java</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-2" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="n">Intent</span><span class="w"> </span><span class="n">discoverableIntent</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">new</span><span class="w"> </span><span class="n">Intent</span><span class="p">(</span><span class="n">BluetoothAdapter</span><span class="p">.</span><span class="na">ACTION_REQUEST_DISCOVERABLE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">discoverableIntent</span><span class="p">.</span><span class="na">putExtra</span><span class="p">(</span><span class="n">BluetoothAdapter</span><span class="p">.</span><span class="na">EXTRA_DISCOVERABLE_DURATION</span><span class="p">,</span><span class="w"> </span><span class="n">300</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">startActivity</span><span class="p">(</span><span class="n">discoverableIntent</span><span class="p">);</span></span></span></code></pre>
</div>
<h2 id="settings-activity-binder-client" class="headerLink">
    <a href="#settings-activity-binder-client" class="header-mark"></a>Settings Activity (Binder Client)</h2><p>根据<a href="https://developer.android.com/guide/components/intents-filters" target="_blank" rel="noopener noreferrer">intents-filters</a>的介绍，我们知道这是由于其他App去处理的请求，即<code>com.android.settings/.bluetooth.RequestPermissionActivity</code>，该页面调用弹窗询问(startActivityForResult)用户是否允许本设备被发现，并且在回调(onActivityResult)中注册蓝牙的回调中调用:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">java</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-3" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="n">mBluetoothAdapter</span><span class="p">.</span><span class="na">setScanMode</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="n">BluetoothAdapter</span><span class="p">.</span><span class="na">SCAN_MODE_CONNECTABLE_DISCOVERABLE</span><span class="p">,</span><span class="w"> </span><span class="n">mTimeout</span><span class="p">)</span><span class="err">；</span></span></span></code></pre>
</div>
<p>frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">java</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-4" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="nd">@UnsupportedAppUsage</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">setScanMode</span><span class="p">(</span><span class="nd">@ScanMode</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">mode</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">duration</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">getState</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">STATE_ON</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">mServiceLock</span><span class="p">.</span><span class="na">readLock</span><span class="p">().</span><span class="na">lock</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mService</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">mService</span><span class="p">.</span><span class="na">setScanMode</span><span class="p">(</span><span class="n">mode</span><span class="p">,</span><span class="w"> </span><span class="n">duration</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">RemoteException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Log</span><span class="p">.</span><span class="na">e</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">finally</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">mServiceLock</span><span class="p">.</span><span class="na">readLock</span><span class="p">().</span><span class="na">unlock</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span></span></span></code></pre>
</div>
<blockquote>
  <p>题外话: 上面的annotation表示该接口不是SDK的一部分，在9.0之前APP是可以通过反射进行调用的，9.0之后安卓更新了限制方法，不过也有其他的绕过方式，见: <a href="https://stackoverflow.com/questions/55970137/bypass-androids-hidden-api-restrictions" target="_blank" rel="noopener noreferrer">https://stackoverflow.com/questions/55970137/bypass-androids-hidden-api-restrictions</a></p>
</blockquote><p>其中<code>mService</code>是<code>IBluetooth</code>类型，直指蓝牙服务<code>system/bt/binder/android/bluetooth/IBluetooth.aidl</code>，值得一提的是，该目录下还包含了数十个AIDL文件，用于描述进程所提供的服务。</p>
<h2 id="aidl-server" class="headerLink">
    <a href="#aidl-server" class="header-mark"></a>AIDL Server</h2><p>该AIDL的实现在<code>packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java</code>，该Server的JNI实现在<code>packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp</code>，内部主要使用<code>sBluetoothInterface</code>接口来实现功能，该接口的定义为:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-5" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="n">bt_interface_t</span><span class="o">*</span> <span class="n">sBluetoothInterface</span></span></span></code></pre>
</div>
<p>该接口的实现在<code>btif/src/bluetooth.cc</code>中。</p>
<p>回到SetScanMode，其实现在<code>system/bt/service/adapter.cc</code>:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-6" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="kt">bool</span> <span class="nf">SetScanMode</span><span class="p">(</span><span class="kt">int</span> <span class="n">scan_mode</span><span class="p">)</span> <span class="k">override</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">switch</span> <span class="p">(</span><span class="n">scan_mode</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">BT_SCAN_MODE_NONE</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">BT_SCAN_MODE_CONNECTABLE</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">default</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">LOG</span><span class="p">(</span><span class="n">ERROR</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Unknown scan mode: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">scan_mode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">auto</span> <span class="n">bd_scanmode</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="n">bt_scan_mode_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">scan_mode</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">SetAdapterProperty</span><span class="p">(</span><span class="n">BT_PROPERTY_ADAPTER_SCAN_MODE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bd_scanmode</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="k">sizeof</span><span class="p">(</span><span class="n">bd_scanmode</span><span class="p">)))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">LOG</span><span class="p">(</span><span class="n">ERROR</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Failed to set scan mode to : &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">scan_mode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>核心是<code>SetAdapterProperty</code>:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-7" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// Sends a request to set the given HAL adapter property type and value.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">bool</span> <span class="nf">SetAdapterProperty</span><span class="p">(</span><span class="n">bt_property_type_t</span> <span class="n">type</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">int</span> <span class="n">length</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">CHECK</span><span class="p">(</span><span class="n">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="n">CHECK</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">bt_property_t</span> <span class="n">property</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">property</span><span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">length</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">property</span><span class="p">.</span><span class="n">val</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">property</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">type</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">status</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">      <span class="n">hal</span><span class="o">::</span><span class="n">BluetoothInterface</span><span class="o">::</span><span class="n">Get</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">GetHALInterface</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">set_adapter_property</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">          <span class="o">&amp;</span><span class="n">property</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">BT_STATUS_SUCCESS</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">VLOG</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Failed to set property&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>其中<code>GetHALInterface</code>是蓝牙的核心接口<code>bt_interface_t</code>，定义在接口子系统中<code>system/bt/btif/src/bluetooth.cc</code>，随后依次调用:</p>
<ul>
<li>set_adapter_property</li>
<li>btif_set_adapter_property (btif/src/btif_core.c)</li>
<li>BTA_DmSetVisibility (bta/dm/bta_dm_api.cc)</li>
</ul>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-8" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl">  <span class="cm">/** This function sets the Bluetooth connectable, discoverable, pairable and
</span></span></span><span class="line"><span class="cl"><span class="cm">   * conn paired only modes of local device
</span></span></span><span class="line"><span class="cl"><span class="cm">   */</span>  
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">BTA_DmSetVisibility</span><span class="p">(</span><span class="n">tBTA_DM_DISC</span> <span class="n">disc_mode</span><span class="p">,</span> <span class="n">tBTA_DM_CONN</span> <span class="n">conn_mode</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                           <span class="kt">uint8_t</span> <span class="n">pairable_mode</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">conn_paired_only</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">do_in_main_thread</span><span class="p">(</span><span class="n">FROM_HERE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">base</span><span class="o">::</span><span class="n">Bind</span><span class="p">(</span><span class="n">bta_dm_set_visibility</span><span class="p">,</span> <span class="n">disc_mode</span><span class="p">,</span> <span class="n">conn_mode</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                 <span class="n">pairable_mode</span><span class="p">,</span> <span class="n">conn_paired_only</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span></span></span></code></pre>
</div>
<p>do_in_main_thread是将任务push到对应的线程任务池中执行，所执行的函数是<code>bta_dm_set_visibility</code>(bta/dm/bta_dm_act.cc)，主要功能是根据参数的逻辑分别设置对应的属性:</p>
<ul>
<li>BTM_SetDiscoverability</li>
<li>BTM_SetConnectability</li>
<li>BTM_SetPairableMode</li>
</ul>
<p><code>stack/btm/btm_inq.cc</code></p>
<div class="code-block highlight is-closed show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-9" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl">  <span class="cm">/*******************************************************************************
</span></span></span><span class="line"><span class="cl"><span class="cm">   *
</span></span></span><span class="line"><span class="cl"><span class="cm">   * Function         BTM_SetDiscoverability
</span></span></span><span class="line"><span class="cl"><span class="cm">   *
</span></span></span><span class="line"><span class="cl"><span class="cm">   * Description      This function is called to set the device into or out of
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  discoverable mode. Discoverable mode means inquiry
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  scans are enabled.  If a value of &#39;0&#39; is entered for window
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  or interval, the default values are used.
</span></span></span><span class="line"><span class="cl"><span class="cm">   *
</span></span></span><span class="line"><span class="cl"><span class="cm">   * Returns          BTM_SUCCESS if successful
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  BTM_BUSY if a setting of the filter is already in progress
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  BTM_NO_RESOURCES if couldn&#39;t get a memory pool buffer
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  BTM_ILLEGAL_VALUE if a bad parameter was detected
</span></span></span><span class="line"><span class="cl"><span class="cm">   *                  BTM_WRONG_MODE if the device is not up.
</span></span></span><span class="line"><span class="cl"><span class="cm">   *
</span></span></span><span class="line"><span class="cl"><span class="cm">   ******************************************************************************/</span>  
</span></span><span class="line"><span class="cl"><span class="n">tBTM_STATUS</span> <span class="nf">BTM_SetDiscoverability</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="n">inq_mode</span><span class="p">,</span> <span class="kt">uint16_t</span> <span class="n">window</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                     <span class="kt">uint16_t</span> <span class="n">interval</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">BTM_TRACE_API</span><span class="p">(</span><span class="s">&#34;BTM_SetDiscoverability&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">controller_get_interface</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">supports_ble</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="n">btm_ble_set_discoverability</span><span class="p">((</span><span class="kt">uint16_t</span><span class="p">)(</span><span class="n">inq_mode</span><span class="p">))</span> <span class="o">==</span> <span class="n">BTM_SUCCESS</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">discoverable_mode</span> <span class="o">&amp;=</span> <span class="p">(</span><span class="o">~</span><span class="n">BTM_BLE_DISCOVERABLE_MASK</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">discoverable_mode</span> <span class="o">|=</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="n">inq_mode</span> <span class="o">&amp;</span> <span class="n">BTM_BLE_DISCOVERABLE_MASK</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="n">inq_mode</span> <span class="o">&amp;=</span> <span class="o">~</span><span class="n">BTM_BLE_DISCOVERABLE_MASK</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="cm">/*** Check mode parameter ***/</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">inq_mode</span> <span class="o">&gt;</span> <span class="n">BTM_MAX_DISCOVERABLE</span><span class="p">)</span> <span class="k">return</span> <span class="p">(</span><span class="n">BTM_ILLEGAL_VALUE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Make sure the controller is active */</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">controller_get_interface</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_is_ready</span><span class="p">())</span> <span class="k">return</span> <span class="p">(</span><span class="n">BTM_DEV_RESET</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* If the window and/or interval is &#39;0&#39;, set to default values */</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">window</span><span class="p">)</span> <span class="n">window</span> <span class="o">=</span> <span class="n">BTM_DEFAULT_DISC_WINDOW</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">interval</span><span class="p">)</span> <span class="n">interval</span> <span class="o">=</span> <span class="n">BTM_DEFAULT_DISC_INTERVAL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">BTM_TRACE_API</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s">&#34;BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window &#34;</span>
</span></span><span class="line"><span class="cl">        <span class="s">&#34;0x%04x, interval 0x%04x&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">inq_mode</span><span class="p">,</span> <span class="n">window</span><span class="p">,</span> <span class="n">interval</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">      <span class="cm">/*** Check for valid window and interval parameters ***/</span>
</span></span><span class="line"><span class="cl">      <span class="cm">/*** Only check window and duration if mode is connectable ***/</span>
</span></span><span class="line"><span class="cl">	  <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  
</span></span><span class="line"><span class="cl">      <span class="cm">/* Set the IAC if needed */</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">inq_mode</span> <span class="o">!=</span> <span class="n">BTM_NON_DISCOVERABLE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="n">inq_mode</span> <span class="o">&amp;</span> <span class="n">BTM_LIMITED_DISCOVERABLE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/* Use the GIAC and LIAC codes for limited discoverable mode */</span>
</span></span><span class="line"><span class="cl">        <span class="n">memcpy</span><span class="p">(</span><span class="n">temp_lap</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">limited_inq_lap</span><span class="p">,</span> <span class="n">LAP_LEN</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">memcpy</span><span class="p">(</span><span class="n">temp_lap</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">general_inq_lap</span><span class="p">,</span> <span class="n">LAP_LEN</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">btsnd_hcic_write_cur_iac_lap</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="n">LAP</span> <span class="o">*</span> <span class="k">const</span><span class="p">)</span><span class="n">temp_lap</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">btsnd_hcic_write_cur_iac_lap</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="n">LAP</span> <span class="o">*</span> <span class="k">const</span><span class="p">)</span> <span class="o">&amp;</span> <span class="n">general_inq_lap</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">scan_mode</span> <span class="o">|=</span> <span class="n">HCI_INQUIRY_SCAN_ENABLED</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="cm">/* Send down the inquiry scan window and period if changed */</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">((</span><span class="n">window</span> <span class="o">!=</span> <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">inq_scan_window</span><span class="p">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="n">interval</span> <span class="o">!=</span> <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">inq_scan_period</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">btsnd_hcic_write_inqscan_cfg</span><span class="p">(</span><span class="n">interval</span><span class="p">,</span> <span class="n">window</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">inq_scan_window</span> <span class="o">=</span> <span class="n">window</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">inq_scan_period</span> <span class="o">=</span> <span class="n">interval</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">connectable_mode</span> <span class="o">&amp;</span> <span class="n">BTM_CONNECTABLE_MASK</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">scan_mode</span> <span class="o">|=</span> <span class="n">HCI_PAGE_SCAN_ENABLED</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">btsnd_hcic_write_scan_enable</span><span class="p">(</span><span class="n">scan_mode</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">discoverable_mode</span> <span class="o">&amp;=</span> <span class="p">(</span><span class="o">~</span><span class="n">BTM_DISCOVERABLE_MASK</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">btm_cb</span><span class="p">.</span><span class="n">btm_inq_vars</span><span class="p">.</span><span class="n">discoverable_mode</span> <span class="o">|=</span> <span class="n">inq_mode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Change the service class bit if mode has changed */</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="p">(</span><span class="n">BTM_SUCCESS</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span></span></span></code></pre>
</div>
<p>这其中涉及了几个API:</p>
<ul>
<li>btm_ble_set_discoverability</li>
<li>btsnd_hcic_write_cur_iac_lap</li>
<li>btsnd_hcic_write_inqscan_cfg</li>
<li>btsnd_hcic_write_scan_enable</li>
</ul>
<p>第一个API是BLE相关，内部实际上最终也调用了<code>btsnd_hcic_xxx</code>的类似接口。<code>IAC</code>意为Inquiry Access Code，蓝牙baseband定义了几个固定IAC，分别是LIAC和GIAC(见<a href="https://www.bluetooth.com/specifications/assigned-numbers/baseband/" target="_blank" rel="noopener noreferrer">baseband</a>)。LAP是蓝牙地址的一部分，如下图所示:</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-11-android-bt/2.png'   alt="BDADDR"  ></p>
<ul>
<li>NAP: Non-significant Address Part， NAP的值在跳频同步帧中会用到</li>
<li>UAP: Upper Address Part，UAP的值会参与对蓝牙协议算法的选择</li>
<li>LAP: Lower Address Part，由设备厂商分配，LAP的值作为Access Code的一部分，唯一确定某个蓝牙设备</li>
<li>SAP (significant address part) = UAP + LAP</li>
</ul>
<p>让我们继续回到代码中，以<code>btsnd_hcic_write_cur_iac_lap</code>为例，其实现如下:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-10" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// stack/hcic/hcicmds.cc
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">btsnd_hcic_write_cur_iac_lap</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">num_cur_iac</span><span class="p">,</span> <span class="n">LAP</span><span class="o">*</span> <span class="k">const</span> <span class="n">iac_lap</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">BT_HDR</span><span class="o">*</span> <span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="n">BT_HDR</span><span class="o">*</span><span class="p">)</span><span class="n">osi_malloc</span><span class="p">(</span><span class="n">HCI_CMD_BUF_SIZE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">pp</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span><span class="o">*</span><span class="p">)(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">p</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">=</span> <span class="n">HCIC_PREAMBLE_SIZE</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="n">LAP_LEN</span> <span class="o">*</span> <span class="n">num_cur_iac</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">p</span><span class="o">-&gt;</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">UINT16_TO_STREAM</span><span class="p">(</span><span class="n">pp</span><span class="p">,</span> <span class="n">HCI_WRITE_CURRENT_IAC_LAP</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">UINT8_TO_STREAM</span><span class="p">(</span><span class="n">pp</span><span class="p">,</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">len</span> <span class="o">-</span> <span class="n">HCIC_PREAMBLE_SIZE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">UINT8_TO_STREAM</span><span class="p">(</span><span class="n">pp</span><span class="p">,</span> <span class="n">num_cur_iac</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">num_cur_iac</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">LAP_TO_STREAM</span><span class="p">(</span><span class="n">pp</span><span class="p">,</span> <span class="n">iac_lap</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">btu_hcif_send_cmd</span><span class="p">(</span><span class="n">LOCAL_BR_EDR_CONTROLLER_ID</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p><code>UINTx_TO_STREAM(pp, n)</code>的作用是将整数以小端的形式写入<code>p-&gt;data</code>中，最终调用<code>btu_hcif_send_cmd</code>函数发送数据(stack/btu/btu_hcif.cc):</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-11" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="cm">/*******************************************************************************
</span></span></span><span class="line"><span class="cl"><span class="cm">*
</span></span></span><span class="line"><span class="cl"><span class="cm">* Function         btu_hcif_send_cmd
</span></span></span><span class="line"><span class="cl"><span class="cm">*
</span></span></span><span class="line"><span class="cl"><span class="cm">* Description      This function is called to send commands to the Host
</span></span></span><span class="line"><span class="cl"><span class="cm">*                  Controller.
</span></span></span><span class="line"><span class="cl"><span class="cm">*
</span></span></span><span class="line"><span class="cl"><span class="cm">* Returns          void
</span></span></span><span class="line"><span class="cl"><span class="cm">*
</span></span></span><span class="line"><span class="cl"><span class="cm">******************************************************************************/</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">btu_hcif_send_cmd</span><span class="p">(</span><span class="n">UNUSED_ATTR</span> <span class="kt">uint8_t</span> <span class="n">controller_id</span><span class="p">,</span> <span class="n">BT_HDR</span><span class="o">*</span> <span class="n">p_buf</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">p_buf</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">uint16_t</span> <span class="n">opcode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">p_buf</span><span class="o">-&gt;</span><span class="n">data</span> <span class="o">+</span> <span class="n">p_buf</span><span class="o">-&gt;</span><span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">void</span><span class="o">*</span> <span class="n">vsc_callback</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">STREAM_TO_UINT16</span><span class="p">(</span><span class="n">opcode</span><span class="p">,</span> <span class="n">stream</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Eww...horrible hackery here
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="cm">/* If command was a VSC, then extract command_complete callback */</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">((</span><span class="n">opcode</span> <span class="o">&amp;</span> <span class="n">HCI_GRP_VENDOR_SPECIFIC</span><span class="p">)</span> <span class="o">==</span> <span class="n">HCI_GRP_VENDOR_SPECIFIC</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="n">opcode</span> <span class="o">==</span> <span class="n">HCI_BLE_RAND</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">opcode</span> <span class="o">==</span> <span class="n">HCI_BLE_ENCRYPT</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">vsc_callback</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)(</span><span class="n">p_buf</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Skip parameter length before logging
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">stream</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">btu_hcif_log_command_metrics</span><span class="p">(</span><span class="n">opcode</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                 <span class="n">android</span><span class="o">::</span><span class="n">bluetooth</span><span class="o">::</span><span class="n">hci</span><span class="o">::</span><span class="n">STATUS_UNKNOWN</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">hci_layer_get_interface</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">transmit_command</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">p_buf</span><span class="p">,</span> <span class="n">btu_hcif_command_complete_evt</span><span class="p">,</span> <span class="n">btu_hcif_command_status_evt</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">vsc_callback</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>可见<code>p_buf-&gt;data</code>中保存的就是HCI数据，前16位为opcode，其中高6字节为ogf，低10字节为ocf，也就是我们平时使用<code>hcitool cmd</code>时的前两个参数。</p>
<h2 id="hci-子系统" class="headerLink">
    <a href="#hci-%e5%ad%90%e7%b3%bb%e7%bb%9f" class="header-mark"></a>HCI 子系统</h2><p>继续跟踪<code>transmit_command</code>，就来到了HCI子系统中(hci/src/hci_layer.cc):</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-12" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">transmit_command</span><span class="p">(</span><span class="n">BT_HDR</span><span class="o">*</span> <span class="n">command</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                           <span class="n">command_complete_cb</span> <span class="n">complete_callback</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                           <span class="n">command_status_cb</span> <span class="n">status_callback</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">waiting_command_t</span><span class="o">*</span> <span class="n">wait_entry</span> <span class="o">=</span> <span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">waiting_command_t</span><span class="o">*&gt;</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">osi_calloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">waiting_command_t</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">command</span><span class="o">-&gt;</span><span class="n">data</span> <span class="o">+</span> <span class="n">command</span><span class="o">-&gt;</span><span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">STREAM_TO_UINT16</span><span class="p">(</span><span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">opcode</span><span class="p">,</span> <span class="n">stream</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">complete_callback</span> <span class="o">=</span> <span class="n">complete_callback</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">status_callback</span> <span class="o">=</span> <span class="n">status_callback</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">command</span> <span class="o">=</span> <span class="n">command</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">context</span> <span class="o">=</span> <span class="n">context</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Store the command message type in the event field
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// in case the upper layer didn&#39;t already
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">command</span><span class="o">-&gt;</span><span class="n">event</span> <span class="o">=</span> <span class="n">MSG_STACK_TO_HC_HCI_CMD</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">enqueue_command</span><span class="p">(</span><span class="n">wait_entry</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p><code>enqueue_command</code>如其名字所述，就是将待执行的HCI命令放到队列<code>command_queue</code>的末尾中。那么这个任务队列在哪消费呢？简单搜索可以发现:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-13" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// Event/packet receiving functions
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">process_command_credits</span><span class="p">(</span><span class="kt">int</span> <span class="n">credits</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">command_credits_lock</span><span class="p">(</span><span class="n">command_credits_mutex</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">hci_thread</span><span class="p">.</span><span class="n">IsRunning</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// HCI Layer was shut down or not running
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Subtract commands in flight.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">command_credits</span> <span class="o">=</span> <span class="n">credits</span> <span class="o">-</span> <span class="n">get_num_waiting_commands</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">command_credits</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">command_queue</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">hci_thread</span><span class="p">.</span><span class="n">DoInThread</span><span class="p">(</span><span class="n">FROM_HERE</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">command_queue</span><span class="p">.</span><span class="n">front</span><span class="p">())))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">LOG</span><span class="p">(</span><span class="n">ERROR</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">__func__</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;: failed to enqueue command&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="n">command_queue</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="n">command_credits</span><span class="o">--</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>其调用链路为:</p>
<ul>
<li>BluetoothHciCallbacks::hciEventReceived (hci/src/hci_layer_android.cc)</li>
<li>hci_event_received</li>
<li>filter_incoming_event</li>
<li>process_command_credits</li>
</ul>
<h2 id="接收数据" class="headerLink">
    <a href="#%e6%8e%a5%e6%94%b6%e6%95%b0%e6%8d%ae" class="header-mark"></a>接收数据</h2><p><code>BluetoothHciCallbacks::hciEventReceived</code>这个函数回调是在HCI初始化的时候调用的<code>BluetoothHci::initialize</code>(vendor_libs/linux/interface/bluetooth_hci.cc):</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-14" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="n">Return</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">&gt;</span> <span class="n">BluetoothHci</span><span class="o">::</span><span class="n">initialize</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="k">const</span> <span class="o">::</span><span class="n">android</span><span class="o">::</span><span class="n">sp</span><span class="o">&lt;</span><span class="n">IBluetoothHciCallbacks</span><span class="o">&gt;&amp;</span> <span class="n">cb</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGI</span><span class="p">(</span><span class="s">&#34;BluetoothHci::initialize()&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">cb</span> <span class="o">==</span> <span class="k">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">ALOGE</span><span class="p">(</span><span class="s">&#34;cb == nullptr! -&gt; Unable to call initializationComplete(ERR)&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nf">Void</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">death_recipient_</span><span class="o">-&gt;</span><span class="n">setHasDied</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">cb</span><span class="o">-&gt;</span><span class="n">linkToDeath</span><span class="p">(</span><span class="n">death_recipient_</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">hci_fd</span> <span class="o">=</span> <span class="n">openBtHci</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">hidl_status</span> <span class="o">=</span> <span class="n">cb</span><span class="o">-&gt;</span><span class="n">initializationComplete</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">hci_fd</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">Status</span><span class="o">::</span><span class="nl">SUCCESS</span> <span class="p">:</span> <span class="n">Status</span><span class="o">::</span><span class="n">INITIALIZATION_ERROR</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">hidl_status</span><span class="p">.</span><span class="n">isOk</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">ALOGE</span><span class="p">(</span><span class="s">&#34;VendorInterface -&gt; Unable to call initializationComplete(ERR)&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">hci</span><span class="o">::</span><span class="n">H4Protocol</span><span class="o">*</span> <span class="n">h4_hci</span> <span class="o">=</span> <span class="k">new</span> <span class="n">hci</span><span class="o">::</span><span class="n">H4Protocol</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">hci_fd</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">cb</span><span class="p">](</span><span class="k">const</span> <span class="n">hidl_vec</span><span class="o">&lt;</span><span class="kt">uint8_t</span><span class="o">&gt;&amp;</span> <span class="n">packet</span><span class="p">)</span> <span class="p">{</span> <span class="n">cb</span><span class="o">-&gt;</span><span class="n">hciEventReceived</span><span class="p">(</span><span class="n">packet</span><span class="p">);</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">cb</span><span class="p">](</span><span class="k">const</span> <span class="n">hidl_vec</span><span class="o">&lt;</span><span class="kt">uint8_t</span><span class="o">&gt;&amp;</span> <span class="n">packet</span><span class="p">)</span> <span class="p">{</span> <span class="n">cb</span><span class="o">-&gt;</span><span class="n">aclDataReceived</span><span class="p">(</span><span class="n">packet</span><span class="p">);</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">cb</span><span class="p">](</span><span class="k">const</span> <span class="n">hidl_vec</span><span class="o">&lt;</span><span class="kt">uint8_t</span><span class="o">&gt;&amp;</span> <span class="n">packet</span><span class="p">)</span> <span class="p">{</span> <span class="n">cb</span><span class="o">-&gt;</span><span class="n">scoDataReceived</span><span class="p">(</span><span class="n">packet</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fd_watcher_</span><span class="p">.</span><span class="n">WatchFdForNonBlockingReads</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">hci_fd</span><span class="p">,</span> <span class="p">[</span><span class="n">h4_hci</span><span class="p">](</span><span class="kt">int</span> <span class="n">fd</span><span class="p">)</span> <span class="p">{</span> <span class="n">h4_hci</span><span class="o">-&gt;</span><span class="n">OnDataReady</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="n">hci_handle_</span> <span class="o">=</span> <span class="n">h4_hci</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">unlink_cb_</span> <span class="o">=</span> <span class="p">[</span><span class="n">cb</span><span class="p">](</span><span class="n">sp</span><span class="o">&lt;</span><span class="n">BluetoothDeathRecipient</span><span class="o">&gt;&amp;</span> <span class="n">death_recipient</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="n">death_recipient</span><span class="o">-&gt;</span><span class="n">getHasDied</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="n">ALOGI</span><span class="p">(</span><span class="s">&#34;Skipping unlink call, service died.&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">else</span>
</span></span><span class="line"><span class="cl">        <span class="n">cb</span><span class="o">-&gt;</span><span class="n">unlinkToDeath</span><span class="p">(</span><span class="n">death_recipient</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nf">Void</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p><code>fd_watcher_</code>本质上是针对<code>hci_fd</code>文件句柄的读端事件监控，后者由<code>openBtHci</code>函数产生，该函数由厂商实现，接口文件是<code>hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal</code>。在Linux中的参考实现如下:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-15" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// system/bt/vendor_libs/linux/interface/bluetooth_hci.cc
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">BluetoothHci</span><span class="o">::</span><span class="n">openBtHci</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGI</span><span class="p">(</span> <span class="s">&#34;%s&#34;</span><span class="p">,</span> <span class="n">__func__</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">hci_interface</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">rfkill_state_</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">rfKill</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_BLUETOOTH</span><span class="p">,</span> <span class="n">SOCK_RAW</span><span class="p">,</span> <span class="n">BTPROTO_HCI</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGE</span><span class="p">(</span> <span class="s">&#34;Bluetooth socket error: %s&#34;</span><span class="p">,</span> <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">bt_soc_fd_</span> <span class="o">=</span> <span class="n">fd</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">waitHciDev</span><span class="p">(</span><span class="n">hci_interface</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGE</span><span class="p">(</span> <span class="s">&#34;HCI interface (%d) not found&#34;</span><span class="p">,</span> <span class="n">hci_interface</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="o">::</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="nc">sockaddr_hci</span> <span class="n">addr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">addr</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">addr</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="n">addr</span><span class="p">.</span><span class="n">hci_family</span> <span class="o">=</span> <span class="n">AF_BLUETOOTH</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">addr</span><span class="p">.</span><span class="n">hci_dev</span> <span class="o">=</span> <span class="n">hci_interface</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">addr</span><span class="p">.</span><span class="n">hci_channel</span> <span class="o">=</span> <span class="n">HCI_CHANNEL_USER</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">bind</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="nc">sockaddr</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGE</span><span class="p">(</span> <span class="s">&#34;HCI Channel Control: %s&#34;</span><span class="p">,</span> <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">      <span class="o">::</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">ALOGI</span><span class="p">(</span> <span class="s">&#34;HCI device ready&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fd</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<h2 id="发送数据" class="headerLink">
    <a href="#%e5%8f%91%e9%80%81%e6%95%b0%e6%8d%ae" class="header-mark"></a>发送数据</h2><p>继续回头接着上节之前的内容讲，我们的任务队列是在<code>process_command_credits</code>中被消费的，取出来之后需要进入到<code>hci_thread</code>线程中执行。从接收数据一节中也能看出，hci接口本身使用的是串行总线，因此不能并发地发送数据，所有命令都是在之前的命令响应后再发送。</p>
<p>值得一提的是，enqueue_command实际上绑定的是函数<code>event_command_ready</code>，以包含我们命令内容和对应回调的类型<code>waiting_command_t</code>为参数:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-16" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">enqueue_command</span><span class="p">(</span><span class="n">waiting_command_t</span><span class="o">*</span> <span class="n">wait_entry</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">base</span><span class="o">::</span><span class="n">Closure</span> <span class="n">callback</span> <span class="o">=</span> <span class="n">base</span><span class="o">::</span><span class="n">Bind</span><span class="p">(</span><span class="o">&amp;</span><span class="n">event_command_ready</span><span class="p">,</span> <span class="n">wait_entry</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="c1">//...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="n">command_queue</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>因此，负责执行HCI发送命令的是event_command_ready函数:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-17" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl">  <span class="k">static</span> <span class="kt">void</span> <span class="nf">event_command_ready</span><span class="p">(</span><span class="n">waiting_command_t</span><span class="o">*</span> <span class="n">wait_entry</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">/// Move it to the list of commands awaiting response
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">recursive_timed_mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">          <span class="n">commands_pending_response_mutex</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">timestamp</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">steady_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="n">list_append</span><span class="p">(</span><span class="n">commands_pending_response</span><span class="p">,</span> <span class="n">wait_entry</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Send it off
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">packet_fragmenter</span><span class="o">-&gt;</span><span class="n">fragment_and_dispatch</span><span class="p">(</span><span class="n">wait_entry</span><span class="o">-&gt;</span><span class="n">command</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">update_command_response_timer</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span></span></span></code></pre>
</div>
<p>首先将command放到一个等待响应的队列里，然后分片发送:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-18" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">fragment_and_dispatch</span><span class="p">(</span><span class="n">BT_HDR</span><span class="o">*</span> <span class="n">packet</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">CHECK</span><span class="p">(</span><span class="n">packet</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">uint16_t</span> <span class="n">event</span> <span class="o">=</span> <span class="n">packet</span><span class="o">-&gt;</span><span class="n">event</span> <span class="o">&amp;</span> <span class="n">MSG_EVT_MASK</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">packet</span><span class="o">-&gt;</span><span class="n">data</span> <span class="o">+</span> <span class="n">packet</span><span class="o">-&gt;</span><span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// We only fragment ACL packets
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="n">event</span> <span class="o">!=</span> <span class="n">MSG_STACK_TO_HC_HCI_ACL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">callbacks</span><span class="o">-&gt;</span><span class="n">fragmented</span><span class="p">(</span><span class="n">packet</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ACL/L2CAP fragment...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span></span></span></code></pre>
</div>
<p>实现中只对ACL类型的HCI数据进行分片发送，不管是不是分片，都对最后一个packet调用<code>callbacks-&gt;fragmented()</code>，callbacks的类型是<code>packet_fragmenter_callbacks_t</code>，在<code>packet_fragmenter_t-&gt;init</code>中初始化并设置。而packet_fragmenter的初始化发生在<code>hci_module_start_up()</code>中，HCI层定义的回调如下:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-19" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="n">packet_fragmenter_callbacks_t</span> <span class="n">packet_fragmenter_callbacks</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">transmit_fragment</span><span class="p">,</span> <span class="n">dispatch_reassembled</span><span class="p">,</span> <span class="n">fragmenter_transmit_finished</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span></span></span></code></pre>
</div>
<p>fragmented即对应transmit_fragment，对应定义如下:</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">cpp</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-20" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="c1">// Callback for the fragmenter to send a fragment
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">transmit_fragment</span><span class="p">(</span><span class="n">BT_HDR</span><span class="o">*</span> <span class="n">packet</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">send_transmit_finished</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">btsnoop</span><span class="o">-&gt;</span><span class="n">capture</span><span class="p">(</span><span class="n">packet</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// HCI command packets are freed on a different thread when the matching
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// event is received. Check packet-&gt;event before sending to avoid a race.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="n">free_after_transmit</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="n">packet</span><span class="o">-&gt;</span><span class="n">event</span> <span class="o">&amp;</span> <span class="n">MSG_EVT_MASK</span><span class="p">)</span> <span class="o">!=</span> <span class="n">MSG_STACK_TO_HC_HCI_CMD</span> <span class="o">&amp;&amp;</span>
</span></span><span class="line"><span class="cl">        <span class="n">send_transmit_finished</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">hci_transmit</span><span class="p">(</span><span class="n">packet</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">free_after_transmit</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">buffer_allocator</span><span class="o">-&gt;</span><span class="n">free</span><span class="p">(</span><span class="n">packet</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p><code>hci_transmit</code>有不同平台的实现，分别在:</p>
<ul>
<li>hci/src/hci_layer_linux.c</li>
<li>hci/src/hci_layer_android.c</li>
</ul>
<p>前者是通过<code>write</code>直接向<em>HCI socket</em>的fd写入，后者是调用<code>IBluetoothHci::sendHciCommand</code>去实现，接口定义同样是在<code>hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal</code>文件中。</p>
<p>因为不同手机厂商的SoC中集成蓝牙芯片的接口不同，有的是使用USB连接，有的是使用UART连接，因此需要给安卓提供一个统一的操作接口，这个接口就很适合由HAL(HIDL)来进行抽象。这部分实现通常是使用Linux中已有的UART/USB驱动进行操作，以提高代码的复用性。</p>
<h1 id="小结" class="headerLink">
    <a href="#%e5%b0%8f%e7%bb%93" class="header-mark"></a>小结</h1><p>本文通过从从用户层的一个蓝牙接口进行跟踪，一直向下分析到HCI的硬件抽象层。在这个过程中，穿插了蓝牙中的各个子模块，比如BTA、BTM、BTU 等，并在某些回调注册的节点中分析了对应的的初始化过程。最后根据初始化以及HCI命令的任务队列实现，我们也得知了接收数据/事件时的运行流程，当然还包括ACL分片/重组的逻辑等。对整个BlueDroid系统形成大致理解，有助于为后续的代码审计和漏洞分析奠定基础。</p>
<h1 id="参考链接" class="headerLink">
    <a href="#%e5%8f%82%e8%80%83%e9%93%be%e6%8e%a5" class="header-mark"></a>参考链接</h1><ul>
<li><a href="http://www.bluez.org/" target="_blank" rel="noopener noreferrer">http://www.bluez.org/</a></li>
<li><a href="https://pdfs.semanticscholar.org/7adc/bbf12a30964be7ec4c81a9618fccd7fc0639.pdf" target="_blank" rel="noopener noreferrer">evolution of bluetooth drivers in Linux kernel</a></li>
<li><a href="https://people.csail.mit.edu/albert/bluez-intro/c404.html" target="_blank" rel="noopener noreferrer">programing bluetooth</a></li>
<li><a href="https://elinux.org/images/8/89/Janc.pdf" target="_blank" rel="noopener noreferrer">Bluetooth on modern Linux</a></li>
<li><a href="https://source.android.com/devices/bluetooth" target="_blank" rel="noopener noreferrer">bluedroid</a></li>
<li><a href="https://medium.com/@muhamed.riyas/android-bluetooth-architecture-853645eff17f" target="_blank" rel="noopener noreferrer">https://medium.com/@muhamed.riyas/android-bluetooth-architecture-853645eff17f</a></li>
<li><a href="https://www.sciencedirect.com/topics/computer-science/bluetooth-stack" target="_blank" rel="noopener noreferrer">https://www.sciencedirect.com/topics/computer-science/bluetooth-stack</a></li>
<li><a href="https://link.springer.com/content/pdf/10.1007%2F978-0-387-75462-8_20.pdf" target="_blank" rel="noopener noreferrer">https://link.springer.com/content/pdf/10.1007%2F978-0-387-75462-8_20.pdf</a></li>
<li><a href="https://www.cnblogs.com/blogs-of-lxl/p/7010061.html" target="_blank" rel="noopener noreferrer">https://www.cnblogs.com/blogs-of-lxl/p/7010061.html</a></li>
</ul>]]></description>
</item><item>
    <title>蓝牙安全与攻击案例分析</title>
    <link>https://evilpan.com/2021/07/10/bluetooth-sec/</link>
    <pubDate>Sat, 10 Jul 2021 12:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2021/07/10/bluetooth-sec/</guid>
    <description><![CDATA[<p>本文是 2020 年中旬对于蓝牙技术栈安全研究的笔记，主要针对传统蓝牙和低功耗蓝牙在协议层和软件安全性上攻击面分析，并介绍了一些影响较大的蓝牙漏洞原理，比如协议层的 KNOB、BIAS 漏洞，软件实现上的 BlueBorne、SweynTooth 以及 BlueFrag 漏洞等。</p>
<h1 id="前言" class="headerLink">
    <a href="#%e5%89%8d%e8%a8%80" class="header-mark"></a>前言</h1><p>蓝牙(Bluetooth)是一个短距离无线传输的技术，工作在免证的ISM频段。最初名字为Wibree，在90年代由Nokia设计开发，随后转交给蓝牙特别兴趣小组(SIG)专门维护。</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/10.png'   alt="sig"  ></p>
<p>蓝牙标准经过了数十年不愠不火的发展，核心版本从1.0迭代了到目前的5.2，其中在2010年推出的蓝牙4.0版本标准中引进了Bluetooth Smart或者Buletooth Low Energy(BLE)。由于在功耗上有了极大改善，加上智能手机和智能设备的发展，BLE的应用也进入了爆发期。</p>
<p>4.0之前蓝牙通常称为经典蓝牙(Classic Bluetooth)，包括1.0提出的BR(Basic Rate，基础速率)以及2.0提出的EDR(Enhanced Data Rate，增强数据速率)，两者往往放在一起表示与低功耗蓝牙相对的传统蓝牙。BR/EDR常用于相对短距离无线的连续连接，比如耳机的音频传输。</p>
<p>为了进一步提高蓝牙传输速率，在3.0中又提出了基于802.11的AMP(Alternate MAC and PHY layer extension)拓展，这是和BR/EDR不并存的一种传输模式。</p>
<h1 id="核心系统" class="headerLink">
    <a href="#%e6%a0%b8%e5%bf%83%e7%b3%bb%e7%bb%9f" class="header-mark"></a>核心系统</h1><p>BR/EDR和BLE虽然都称为蓝牙，但它们在实现上大相径庭。前者主要侧重于点对点的通信，连接性和传输速率是考虑的重点；而BLE则侧重于低功耗的设计，在射频层和基带层上优化了多播和广播的支持。传统上Controller芯片只支持一种射频模式，但越来越多设备中也同时支持两种系统，以覆盖尽量多的使用场景。</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/9.png'   alt="framework"  ></p>
<p>蓝牙的核心系统架构包含一个Host和一个或多个Controller，Host可以理解为主核或者主板，运行主流的富操作系统；而Controller可以看做是蓝牙芯片，运行的是裸机程序或者RTOS，主要功能是对射频信号进行编解码。Host和Controller之间通过HCI接口(Host Controller Interface)进行通信，可通过UART、USB等物理接口进行传输。核心系统中包含的组件和之间的关系如下图所示：</p>
<p><figure><a class="lightgallery" href="/img/2021-07-10-bluetooth-sec/0.png" title="core" data-thumbnail="/img/2021-07-10-bluetooth-sec/0.png" data-sub-html="<h2>Core_v5.2 Vol 1: Architecture, Mixing, and Conventions. Part A: Architecture</h2><p>core</p>"><img  loading="lazy" src='/img/2021-07-10-bluetooth-sec/0.png'   alt="core"  ></a><figcaption class="image-caption">Core_v5.2 Vol 1: Architecture, Mixing, and Conventions. Part A: Architecture</figcaption>
</figure></p>
<p>其中Host部分主要是基于L2CAP抽象出的逻辑信道实现应用层的协议和功能，涉及的关键组件和协议有：</p>
<ul>
<li>Channel Manager：负责创建、管理和释放L2CAP channel。</li>
<li>L2CAP Resource Manager：负责管理PDU数据的顺序、调度、分片、重组等功能，是L2CAP核心功能的一部分。</li>
<li>SMP：Security Manager Protocol，实现BLE系统中的点对点安全认证功能，包括秘钥生成和认证等；BR/EDR系统的对应功能则在Controller的Link Manager中实现。</li>
<li>ATT：Atrribute Protocol，应用层attribute client和server之间的协议。</li>
<li>GATT：Generic Attribute Profile，表示ATT server或者client的功能，profile描述了服务和属性的层级结构，主要用于LE profile服务发现中。</li>
<li>GAP：Generic Access Profile，表示所有蓝牙设备通用的基础功能，比如传输层、协议、应用所使用的模式或流程等。GAP服务包括设备和服务发现、连接模式、安全认证和关联模型等。</li>
</ul>
<p>Controller部分中更多是逻辑链路和物理链路的管理，包括：</p>
<ul>
<li>Device Manager：基带(baseband)中控制设备行为的模块，主要负责不与传输直接相关的部分，比如查询周围蓝牙设备，连接蓝牙设备，切换蓝牙设备的状态(discoverable/connectable)，以及修改蓝牙名称、属性等。</li>
<li>Link Manager：负责创建、修改和释放逻辑链路(logical links)以及对应的逻辑传输(logical transports)，并更新设备之间对应物理链路(physical links)的相关参数。在BR/EDR系统中，与对端的Link Manager通过LMP协议(Link Manager Protocol)进行通信；在BLE系统中则使用的是LL协议(Link Layer Protocol)。</li>
<li>Baseband Resource Manager：负责管理所有到射频媒介的访问。在链路层中，有两种类型的“连接”：
<ul>
<li>SCO：Synchronous Connection Orientated，实时窄带数据传输，如电话音频等，无重传</li>
<li>ACL：Asynchronous Connection-Less，异步无连接，用以其他所有数据的传输</li>
</ul>
</li>
<li>Link Controller：负责对指定物理信道(逻辑链路和逻辑传输)的蓝牙数据进行编解码。</li>
</ul>
<p>蓝牙核心系统的每个组件或协议都可以用独立的章节去介绍，整个结构的宏观理解对后面梳理蓝牙的攻击面是非常有必要的。从前面的图中我们可以看到，BR/EDR和BLE在链路层以下是相当不同的，前者为LM而后者为LL，下面分别进行介绍。</p>
<h2 id="bredr" class="headerLink">
    <a href="#bredr" class="header-mark"></a>BR/EDR</h2><p>在传统蓝牙(即BR/EDR)中，2.4GHz的ISM频段分成<strong>79</strong>个频段，每个大小为<strong>1MHz</strong>，并使用特定的跳频模式(Hopping Pattern)来决定一条物理信道，从而减少不同临近终端之间的射频干扰。BR/EDR使用点对点的主从模式，其中Master为确定跳频模式的一方，Slave为与Master时钟和跳频模式同步的其他端点。</p>
<p>传统蓝牙建立链路层连接主要经历两个阶段：Inquiry和Paging。</p>
<p><strong>Inquiry</strong>阶段，Master发送查询请求，周围(10米内)可被发现的设备(discoverable)收到请求后会发送查询响应(Inquiry Response)。在查询过程中，因为与周围设备还未连接，因此它们很可能处于不同的信道(跳频序列)，实际上发送查询的设备会在不同的频率进行发送，而接收方(处于standby模式)则以更高地频率进行足够长时间的查询扫描(Inquiry Scan)以确保能被正确唤起。查询响应中包含设备ID和时钟等信息。</p>
<p><strong>Paging</strong>阶段，主要解决的是链路层的连接问题。与Inquiry类似，此时各方同样没有进行时钟和频率的同步。Master与Slave的连接需要经过以下六步：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/3.png'   alt="paging"  ></p>
<p>连接状态的两个设备所处于的抽象网络称为<code>piconet</code>，这是一个星状网络，一个Master可以有最多七个Slave，但是Master本身也可以是其他piconet的Slave，这种网络拓扑称为<code>scatternet</code>。传统蓝牙处理链路层连接的管理器称为LM，即Link Manager，两个LM之间通过LMP协议进行通信。</p>
<p>这只是链路层的连接，和我们平常所说的蓝牙<strong>配对</strong>(pairing)并不是一回事。Paging只是保证了在物理层链路的连通性，进行应用层的通信往往还需要经历两步：</p>
<ul>
<li>服务发现(Service Discovery)：用以确认对端所支持的服务</li>
<li>服务连接(Service Connection)：使用某个对端设备特定的服务或者配置(Profile)</li>
</ul>
<p>但是实际上在服务发现之前，蓝牙引入了一层安全性保障，确保双方是自愿连接的，沟通连接意愿的过程就称为配对。经过配对后的设备会分别记住对方，在下一次连接时就不需要进行重新配对，而是使用之前保存的连接秘钥(Link Key)直接进行认证和连接：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/4.png'   alt="LM"  ></p>
<p>蓝牙Spec中定义了<em>legacy authentication</em>和<em>secure authentication</em>情况下的认证流程和状态。当两个设备没有共同的link key时，就需要使用<em>pairing</em>流程来协商创建初始化秘钥Kinit。 关于配对流程的分析在后面会详细介绍。</p>
<ul>
<li><a href="https://courses.cs.washington.edu/courses/cse474/18wi/pdfs/lectures/BlueTooth.pdf" target="_blank" rel="noopener noreferrer">https://courses.cs.washington.edu/courses/cse474/18wi/pdfs/lectures/BlueTooth.pdf</a></li>
<li><a href="https://stackoverflow.com/questions/36396456/bluetooth-difference-between-pairing-and-paging-bonding" target="_blank" rel="noopener noreferrer">https://stackoverflow.com/questions/36396456/bluetooth-difference-between-pairing-and-paging-bonding</a></li>
</ul>
<h2 id="ble" class="headerLink">
    <a href="#ble" class="header-mark"></a>BLE</h2><p>在BLE中，2.4GHz的ISM频段分成<strong>40</strong>个频段，每个大小为<strong>2MHz</strong>，其中3个信道为广播信道(advertising channel)，其余37个为通用信道(general purpose channel)。BLE也支持对建立连接后的端点在通用信道中进行跳频通信。</p>
<blockquote>
  <p>各个信道的频率为: <code>f = 2402 + k * 2 MHz, k = 0, 1, ... , 39</code></p>
</blockquote><p>BLE链路层的状态机包括以下状态：</p>
<ul>
<li>Standby State</li>
<li>Advertising State</li>
<li>Scanning State</li>
<li>Initiating State</li>
<li>Connection State</li>
<li>Synchronization State</li>
<li>Isochronous Broadcasting State</li>
</ul>
<p>任一时刻只能处于其中的一种状态，有限状态机的转换过程如下：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/2.png'   alt="FSM"  ></p>
<p>实际中的链路层的状态机不一定要实现上述完整的状态，但蓝牙标准中定义了一些相互依赖的状态组合，实现了其中一种就必须要实现另外一种。任何其他状态都可以直接进入Standby状态，而只有Advertising和Initiating状态才能进入Connection状态。Connection状态中连接的双方分别根据来源状态定义为：</p>
<ul>
<li>Master Role：从Initiating状态进入</li>
<li>Slave Role：从Advertising状态进入</li>
</ul>
<p>与传统蓝牙类似，一个Slave只能与一个Master进行连接。在BLE中，链路层数据包所包含的数据称为协议数据单元(PDU)，Advertising的三个物理信道包含Advertising PDU、Scanning PDU和Initiating PDU，数据信道包含LL Data PDU和LL Control PDU等，不同的PDU包含不同类型的Payload。当然这都是发生在双方Controller端的LL之间，Host端还是主要使用HCI协议对其进行封装，根据不同的场景我们可能需要专注某一端的的实现，比如对于蓝牙芯片固件的研究更多是对LL端的数据进行分析，其他情况下对于应用层或者开发者则更多地关注Host端的HCI、L2CAP、ATT等协议。</p>
<h2 id="security" class="headerLink">
    <a href="#security" class="header-mark"></a>Security</h2><p>蓝牙的服务发现和调用不考虑安全性的话可以直接在同步完物理信道后直接进行应用层交互，但为了避免窃听和中间人等攻击，甚至是为了避免错误连接到其他同名设备，蓝牙服务也是必须要有安全性保障的。初次接触蓝牙Spec的人可能会对蓝牙连接和配对的概念比较困惑，因为蓝牙标准在不同版本中定义了不同的配对模型，而BR/EDR和BLE的配对过程又发生在不同的模块中。比如BR/EDR配对过程由双方<strong>Controller端</strong>的LM(Link Manager)使用LMP协议进行协商，而BLE的配对过程则主要通过<strong>Host端</strong>的协议栈(Security Manager)进行协商。</p>
<p>从时间线上来看，BR/EDR分为几个阶段：</p>
<ul>
<li>2.1之前：使用Legacy Pairing，后续版本中称为<code>BR/EDR legacy</code></li>
<li>2.1：使用 Secure Simple Pairing</li>
<li>4.2：使用 Secure Connection</li>
</ul>
<p>BLE也经历了几个阶段的变化：</p>
<ul>
<li>4.0和4.1：使用 Secure Simple Pairing，后续版本中称为<code>BLE legacy</code></li>
<li>4.2：使用 Secure Connection</li>
</ul>
<p><em>Legacy Pairing</em> 使用双方输入或者固定的PIN CODE来进行认证，现在已经非常少见，因此可以不用关注。</p>
<p><em>Secure Simple Pairing</em> 的配对方式主要经过以下4步(以BR/EDR为例)：</p>
<ol>
<li>IO capabilities exchange：交换对方的特性，比如是否支持显示和键盘输入等，用以后续协商认证手段</li>
<li>Public key exchange：交换椭圆曲线的公钥</li>
<li>Authentication stage 1：身份认证</li>
<li>Authentication stage 2：ECDH Key校验</li>
</ol>
<p>对于身份认证，BR/EDR定义了4种认证方式：</p>
<ul>
<li>Just Works：静默认证，主要用于没有显示和输入功能的设备，如耳机等</li>
<li>Numeric Comparison：双方生成随机数并计算出一个6位数字进行比对确认</li>
<li>Passkey Entry Authentication：主要用于一方有显示功能另外一方有输入功能的场景</li>
<li>OOB(Out Of Band)：使用蓝牙射频以外的其他通道(如NFC)来交换认证信息</li>
</ul>
<p>前面说了BR/EDR 2.1和BLE4.0/4.1都使用Secure Simple Pairing进行配对，为什么还特地强调是BR/EDR呢？因为虽然他们都叫做SSP，但实际上也存在不同的地方，比如BLE的SSP没有使用ECDH，因此数字的认证只能防止被动窃听(passive eavesdropping)，不能防止中间人攻击，并且BLE中没有Numeric Comparison的认证方式。</p>
<p>不过，这也只是过去式了。在4.2以后，BLE和BR/EDR终于统一了配对流程，称为<em>Secure Connection</em>。其在SSP的基础上进行了安全性的增强，下面是BR/EDR的对比：</p>

<div class="table-wrapper">
  <table>
    <thead>
        <tr>
            <th style="text-align: ">安全特性\配对类型</th>
            <th style="text-align: ">Legacy</th>
            <th style="text-align: ">Secure Simple Pairing</th>
            <th style="text-align: ">Secure Connection</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="text-align: ">加密</td>
            <td style="text-align: ">E0</td>
            <td style="text-align: ">E0</td>
            <td style="text-align: ">AES-CCM</td>
        </tr>
        <tr>
            <td style="text-align: ">认证</td>
            <td style="text-align: ">SAFER+</td>
            <td style="text-align: ">SAFER+</td>
            <td style="text-align: ">HMAC-SHA256</td>
        </tr>
        <tr>
            <td style="text-align: ">秘钥生成</td>
            <td style="text-align: ">SAFER+</td>
            <td style="text-align: ">P-192 ECDH HMAC-SHA-256</td>
            <td style="text-align: ">P-256 ECDH HMAC-SHA-256</td>
        </tr>
    </tbody>
  </table>
</div>
<p>而BLE也是殊途同归，最新实现的配对方式也升级成了功能相同的 Secure Connection。</p>
<ul>
<li><a href="https://stackoverflow.com/questions/39592435/pairing-differences-between-bluetooth-and-bluetooth-le" target="_blank" rel="noopener noreferrer">https://stackoverflow.com/questions/39592435/pairing-differences-between-bluetooth-and-bluetooth-le</a></li>
<li><a href="https://security.stackexchange.com/questions/116027/difference-between-secure-simple-pairing-and-secure-connections-in-bluetooth" target="_blank" rel="noopener noreferrer">https://security.stackexchange.com/questions/116027/difference-between-secure-simple-pairing-and-secure-connections-in-bluetooth</a></li>
</ul>
<h1 id="常见协议" class="headerLink">
    <a href="#%e5%b8%b8%e8%a7%81%e5%8d%8f%e8%ae%ae" class="header-mark"></a>常见协议</h1><p>在前面的介绍中我们已经多次提到，主机系统称为Host，蓝牙射频芯片的系统称为Controller，它们之间的通信接口称为HCI(Host Controller Interface)，同时这也是其传输协议的名字。HCI是Host端所能接触的最底层协议，通过内核的HCI驱动进行操作，基于HCI逐步往上封装和实现了一系列高级协议，本节就以自底向上的角度去进行介绍。</p>
<h2 id="hci" class="headerLink">
    <a href="#hci" class="header-mark"></a>HCI</h2><p>HCI协议是HCI接口最底层的协议，可根据传输层的介质分为不同类型，例如：</p>
<ul>
<li>UART传输层：在btsnoop中表示为hci_h4</li>
<li>USB传输层：在btsnoop中表示为hci_h5</li>
<li>SD传输层：Secure Digital</li>
<li>&hellip;</li>
</ul>
<p>HCI数据包分为command、event和data三种类型。command表示Host发送给Controller的命令，event为Controller发送给Host的事件，data通常是实际的蓝牙传输数据。</p>
<blockquote>
  <p>See: <a href="https://software-dl.ti.com/simplelink/esd/simplelink_cc13x2_sdk/1.60.00.29_new/exports/docs/ble5stack/vendor_specific_guide/BLE_Vendor_Specific_HCI_Guide/hci_interface.html" target="_blank" rel="noopener noreferrer">https://software-dl.ti.com/simplelink/esd/simplelink_cc13x2_sdk/1.60.00.29_new/exports/docs/ble5stack/vendor_specific_guide/BLE_Vendor_Specific_HCI_Guide/hci_interface.html</a></p>
</blockquote><p>HCI command的格式为：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">text</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-7" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><pre tabindex="0"><code>16bit opcode | 8bit 参数长度 | 可变参数</code></pre></code></pre>
</div>
<p>其中opcode又分为两部分，高6位为OGF(Opcode Group Field)，低10位为OCF(Opcode Command Field)。在Linuz中我们常用的bluez框架也可以直接发送hci命令：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">sh</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-8" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl">$ hcitool cmd --help
</span></span><span class="line"><span class="cl">Usage:
</span></span><span class="line"><span class="cl">        cmd &lt;ogf&gt; &lt;ocf&gt; <span class="o">[</span>parameters<span class="o">]</span>
</span></span><span class="line"><span class="cl">Example:
</span></span><span class="line"><span class="cl">        cmd 0x03 0x0013 0x41 0x42 0x43 0x44</span></span></code></pre>
</div>
<p>HCI event的格式为：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">text</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-9" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><pre tabindex="0"><code>8bit event code | 8bit 参数长度 | 可变参数</code></pre></code></pre>
</div>
<p>通常Host发送的command都会收到Controller的返回event，提示命令的执行结果。例如，HCI命令<code>0x200c</code>表示<code>LE Set Scan Enable</code>，并通过参数控制开启和关闭BLE的扫描，Controller执行完毕后返回event code <code>0x0e</code>，即<code>Command Complete</code>，并附带status作为参数表示结果是否成功。详细的命令和事件列表可以参考<code>Core_v5.2 Vol 4: Host Controller Interface, Part E-7 HCI commands and events</code>。</p>
<p>除了command和event，HCI中还包括的一大载荷就是数据，比如前面提到的同步数据包SCO、ISO(isochronous)和无连接数据包ACL等。</p>
<h2 id="acl" class="headerLink">
    <a href="#acl" class="header-mark"></a>ACL</h2><p>HCI的ACL协议主要用于在Host和Controller之间传输数据，ACL数据包的格式如下：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">text</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-10" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><pre tabindex="0"><code>12bit   | 2bit    | 2bit    | 16bit             | varlen
Handle 	| PB flag | BC flag | Data Total Length | data</code></pre></code></pre>
</div>
<p>其中，Handle用于区分Host与Controller之间的逻辑链路，PB为Packet Boundary即包边界标志，BC(Broadcast)为广播标志。由于数据总长度只用2个字节表示，因此数据加上头部最多也只有65535字节，这意味着在发送过大的数据时需要在ACL层进行分包和重组，PB Flag就是为了这个目的而设置的，根据PB Flag的值可以表示当前数据包在完整数据中所处的位置。</p>
<h2 id="l2cap" class="headerLink">
    <a href="#l2cap" class="header-mark"></a>L2CAP</h2><p>ACL只提供了一个数据传输协议，类比于网络协议栈中的IP协议，在其之上使用的L2CAP协议可以类比于TCP/UDP协议，实现了更为完善的数据传输功能，包括：</p>
<ol>
<li>协议/信道(L2CAP channel)多路复用</li>
<li>分段(segmentation)和重组(reassembly)</li>
<li>基于L2CAP channel的流量控制机制</li>
<li>错误控制重传机制</li>
<li>支持流式传输(streaming)</li>
<li>分片(fragmentation)和重组(recombination)</li>
<li>QoS(Quality of Service)</li>
<li>&hellip;</li>
</ol>
<p>L2CAP channel表示两个设备之间的一条逻辑链路，使用channel id(CID)进行区分，并以此为基本单元在Controller逻辑链路上进行多路复用。在基于连接的信道(connection-oriented channels)中，L2CAP PDU也称为B-Frame，其格式如下：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">text</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-11" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><pre tabindex="0"><code>16bit length | 16bit CID | information payload</code></pre></code></pre>
</div>
<p>前32bit称为L2CAP header，length是除了header以外的payload长度。在不同的L2CAP模式中，information payload的内容也不尽相同，比如在Supervisor Frame(S-Frame)、Information Frame(I-Frame)。而对于无连接的L2CAP数据包，在payload之前还包含大于等于2字节的PSM(Protocol/Service Multiplexer)，头部还是和B-Frame一致的。</p>
<p>在L2CAP之上，有着各种各样的应用层协议，比如服务发现协议SDP，蓝牙传输协议RFCOMM/OBEX，BLE的属性协议ATT，甚至是通用以太网协议BNEP以及其上的TCP/IP网络栈等。通过分层和抽象使得上层应用无需关心底层的细节，从而实现了整个蓝牙协议栈的普适性和拓展性。</p>
<h1 id="协议安全" class="headerLink">
    <a href="#%e5%8d%8f%e8%ae%ae%e5%ae%89%e5%85%a8" class="header-mark"></a>协议安全</h1><p>这里的协议安全不是指网络协议栈的安全性，而是蓝牙核心协议，或者说蓝牙标准本身的安全性。虽然蓝牙SIG小组在制定标准前都经过了多方讨论和研究，可依然可能存在一些没有考虑周到的临界情况。</p>
<h2 id="knob" class="headerLink">
    <a href="#knob" class="header-mark"></a>KNOB</h2><p>KNOB Attack是2018年3月发现，并在同年10月报告给蓝牙SIG和CERT的一个通用协议漏洞。漏洞点主要出现在LMP协议的秘钥协商阶段，正常来说，两个蓝牙设备连接和配对的过程如下：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/5.png'   alt="LMP"  ></p>
<p>配对之后会先进行蓝牙秘钥协商，协商过程使用的是配对过程协商的ECDH临时秘钥以保证协商过程保密。协商过程使用LMP协议，在各自的Controller端实现：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/6.png'   alt="controller"  ></p>
<p>问题就出在<code>LMP entropy（熵)</code>协商的阶段，因为这部分的协商过程是没有经过ECDH秘钥保护的，所以就容易受到中间人攻击，恶意的攻击者可以将熵设置得尽可能小，从而可以在后面快速地爆破出Kc并实时解密蓝牙的传输数据。这也是为什么该攻击称为KNOB(Key Negotiation of Bluetooth) Attack的原因。</p>
<p>该漏洞的编号为<a href="https://www.kb.cert.org/vuls/id/918987/" target="_blank" rel="noopener noreferrer">CVE-2019-9506</a>，由于是蓝牙核心协议中的设计漏洞，因此影响了大量的蓝牙设备，比如Broadcom、CYW、Apple、Snapdragon等蓝牙芯片。修复方法自然是对秘钥熵协商的过程进行加密，不过这个要等SIG更新进标准中，而标准的更新和推进又相对缓慢，因此很多蓝牙芯片厂商也各自更新了固件做简单的patch。该漏洞的直接危害就是导致蓝牙链路的中间人攻击，导致传输信息泄露或者劫持，实际攻击场景比如蓝牙键盘、蓝牙鼠标等应该是受影响比较大的。</p>
<p>参考资料：</p>
<ul>
<li><a href="https://knobattack.com/" target="_blank" rel="noopener noreferrer">https://knobattack.com/</a></li>
<li><a href="https://github.com/francozappa/knob" target="_blank" rel="noopener noreferrer">https://github.com/francozappa/knob</a></li>
<li><a href="https://francozappa.github.io/publication/knob/slides.pdf" target="_blank" rel="noopener noreferrer">https://francozappa.github.io/publication/knob/slides.pdf</a></li>
</ul>
<h2 id="bias" class="headerLink">
    <a href="#bias" class="header-mark"></a>BIAS</h2><p>BIAS全称为<code>Bluetooth Impersonation Attacks</code>，是2020年5月左右公开的另外一个蓝牙协议的漏洞，CERT编号为<a href="https://nvd.nist.gov/vuln/detail/CVE-2020-10135" target="_blank" rel="noopener noreferrer">CVE-2020-10135</a>。该漏洞实际上是一系列协议设计缺陷导致的认证错误，最终导致对未配对的设备进行连接(或者说伪造成已配对的设备)。</p>
<p>该漏洞主要是针对传统蓝牙(BR/EDR)的配对过程。前面已经说过，在蓝牙协议的发展中，安全配对主要分为三个阶段，即Legacy Pairing、SSP和Secure Connection。配对的作用是让从未见过的设备建立可信、安全的链路层链接，宏观来看就是我们常见的输入配对数字过程，微观上是协商了一个双方持有的长期秘钥LTK(Long Term Key，或者说链接秘钥LK(Link Key)，LTK用来生成后续安全链接的会话秘钥(Session Key)。两个设备只用配对一次，但可使用保存的LTK进行多次安全连接。</p>
<p>在蓝牙连接的过程中，数据是不经过加密或者校验的。连接建立的主要作用是让两个设备交换它们公开的capability信息、互相校验对方的长期秘钥并计算会话秘钥。如果连接的设备支持Secure Connection，就使用安全连接方法建立链接，连接的过程使用AES-CCM经过加密和完整性保护；否则，就使用Legacy Secure Connection(简称为LSC)，连接过程使用E0流加密方法进行加密，并按照对应的流程进行连接。安全连接的建立同样通过LMP协议进行。</p>
<p>之所以介绍这些背景，是因为漏洞的成因与背景相关性较大，在上面的基础上，BIAS漏洞可以描述为以下问题：</p>
<ol>
<li>
<p>LSC过程中master发起连接请求，slave返回自己的LTK认证响应，但master可以不进行校验，也就是说在LSC中对LTK的校验只是单向的，即master校验slave的LTK即可。因此在LSC中攻击者可以轻易伪造成master进行连接。</p>
</li>
<li>
<p>在LSC过程中，攻击者若想伪造成slave，则可以在收到master的连接请求后发起<strong>Role Switch</strong>角色互换请求，将自己变成master，从而在1的基础上伪造成Slave。</p>
</li>
<li>
<p>在Secure Connection的情况下，攻击者可以通过返回<strong>Secure Connection not Support</strong>来发起降级攻击，从而使用LSC进行后续连接，即回退到1/2的场景中进行对端伪造。</p>
</li>
<li>
<p>在Secure Connection的情况下，另一种攻击方法是反射攻击。即在收到Secure Connection的请求后发起<strong>Role Switch</strong>操作，并且伪造对端的认证请求，由于两端的LTK相同，因此对端可以返回合法的认证响应；之后再发起一次Role Switch，将合法的认证响应转发给对端，从而完成安全链接。</p>
</li>
</ol>
<p>BIAS漏洞产生的根源是蓝牙协议中不严谨的定义，比如为了兼容性允许Secure Connection降级，并且Role Switch的设计完全没有考虑安全性，对其发起的时机不加判断导致被滥用。从漏洞危害来看，BIAS的直接影响是可以绕过了手动确认的配对认证与目标设备进行连接，一个典型的例子是可以伪造成目标电脑或手机曾经配对过的蓝牙耳机设备，并静默地与目标进行连接，从而实现间接控制扬声器和麦克风的效果。</p>
<p>参考资料：</p>
<ul>
<li><a href="https://francozappa.github.io/about-bias/" target="_blank" rel="noopener noreferrer">https://francozappa.github.io/about-bias/</a></li>
<li><a href="https://www.bluetooth.com/learn-about-bluetooth/bluetooth-technology/bluetooth-security/bias-vulnerability/" target="_blank" rel="noopener noreferrer">Bluetooth SIG Statement Regarding the Bluetooth Impersonation Attacks (BIAS) Security Vulnerability</a></li>
</ul>
<h2 id="其他" class="headerLink">
    <a href="#%e5%85%b6%e4%bb%96" class="header-mark"></a>其他</h2><p>上面介绍的只是两个比较知名的协议漏洞，类似的协议设计问题还有很多，比如《<a href="http://jin.ece.ufl.edu/papers/USENIX2020-BLE.PDF" target="_blank" rel="noopener noreferrer">Breaking Secure Pairing of Bluetooth Low Energy Using Downgrade Attacks</a>》中就介绍了一种针对SCO(Secure Connection Only)模式的降级攻击。实际上蓝牙核心协议的每次修订，都或多或少对以前版本的疏漏进行了修补。蓝牙协议上出现的安全问题往往影响广泛并且难以修复，因为SIG更新协议需要一定时间，从协议更新到各个厂商的实现和测试也旷日持久。通常这类问题出现后都是厂商自身根据自己的理解进行缓解性修补，这也另一方面影响了漏洞修复的质量。</p>
<h1 id="实现安全" class="headerLink">
    <a href="#%e5%ae%9e%e7%8e%b0%e5%ae%89%e5%85%a8" class="header-mark"></a>实现安全</h1><p>由于蓝牙协议是如此复杂，而且协议本身还随着时间的变迁而不断更新进化，这对于蓝牙的实现造成了巨大挑战。这要求蓝牙固件的开发者一方面要深入理解蓝牙协议的实现过程，另一方面也要对软件安全开发本身有一定认识。尤其是在Controller端，目前还没有一个公开的蓝牙参考实现，蓝牙芯片的内部代码都是各个厂商珍藏的<code>intellectual property</code>。</p>
<p>蓝牙的协议本身都复杂到经常出现非预期的安全问题，那蓝牙的实现就更不用说了。从诺基亚时代开始，就出现过许多代码实现导致的蓝牙软件安全漏洞，比如BlueJack、BlueBugging、BlueBump、Bluesmack、SweynTooth、BlueBorne、BlueFrag等等，……下面挑选几个比较著名的漏洞进行分析。</p>
<h2 id="blueborne" class="headerLink">
    <a href="#blueborne" class="header-mark"></a>BlueBorne</h2><p>BlueBorne是2017年左右公开的一组蓝牙漏洞，当年影响了多个平台和系统，甚至包括IoT设备如Amazon Echo和Google Home等。虽然时过境迁了，但也值得回顾一下。涉及到的漏洞如下：</p>
<ul>
<li>CVE-2017-0781/CVE-2017-0782：Android中l2cap/bnep的内存破坏，可导致RCE</li>
<li>CVE-2017-0785：Android中SDP协议continuation请求偏移校验不当导致的信息泄露</li>
<li>CVE-2017-0783：Android中PANU交互不当导致的中间人攻击</li>
<li>CVE-2017-8628：Windows中蓝牙驱动实现不当导致的中间人攻击</li>
<li>CVE-2017-1000250：Linux BlueZ中SDP实现不当导致的信息泄露，与前面Android中的SDP漏洞原理类似</li>
<li>CVE-2017-1000251：Linux BlueZ中处理L2CAP配置响应不当导致的栈溢出，可进一步造成RCE</li>
<li>CVE-2017-14315：iOS中LEAP (Low Energy Audio Protocol)协议的堆溢出，可进一步造成RCE</li>
</ul>
<p>印象中这是首次在蓝牙实现上批量公开的严重漏洞，在审计蓝牙协议实现时可以发现一些常见的错误模式，比如用户可控长度字段时导致的信息泄露和溢出，这些模式在不同平台的实现中可能都有类似的纰漏，因此所产生的安全问题在不同平台中的迁移性是比较高的。</p>
<p>参考资料：</p>
<ul>
<li><a href="https://www.armis.com/blueborne/" target="_blank" rel="noopener noreferrer">https://www.armis.com/blueborne/</a></li>
<li><a href="https://info.armis.com/rs/645-PDC-047/images/BlueBorne%20Technical%20White%20Paper_20171130.pdf" target="_blank" rel="noopener noreferrer">https://info.armis.com/rs/645-PDC-047/images/BlueBorne%20Technical%20White%20Paper_20171130.pdf</a></li>
<li><a href="https://source.android.com/security/bulletin/2017-09-01" target="_blank" rel="noopener noreferrer">https://source.android.com/security/bulletin/2017-09-01</a></li>
</ul>
<h2 id="sweyntooth" class="headerLink">
    <a href="#sweyntooth" class="header-mark"></a>SweynTooth</h2><p><a href="https://asset-group.github.io/disclosures/sweyntooth/" target="_blank" rel="noopener noreferrer">SweynTooth漏洞</a>也是一系列漏洞的集合，在2019年左右公开。虽然把它归类到实现安全中，但其中大部分漏洞的本质是各个厂商在实现蓝牙核心协议未定义行为时引发的异常。低功耗蓝牙BLE的消息交互流程如下图所示：</p>
<p><img class="tw-inline" loading="lazy" src='/img/2021-07-10-bluetooth-sec/8.png'   alt="messages"  ></p>
<p>从这个图中可以引申出许多有趣的问题，比如：”如果LL加密流程在配对的过程中发起会怎么样？“……直觉来看有可能会造成全零LTK的安装、秘钥大小溢出、公钥不合法等错误。但由于蓝牙核心协议中对这种情况没有明确说明，因此这类的错误处理就全由厂商安装自己的理解去实现了。</p>
<p>一个蓝牙产品在打上蓝牙Logo之前需要经过蓝牙的认证，进行一系列基线兼容性检查，但这个检查也不是面面俱到的。因此，有的即便蓝牙核心协议中有明确定义的行为，在实际测试中也会发现一些SoC厂商的实现不一致。比如，蓝牙核心协议中定义peripheral在同一个central-peripheral连接中应该只响应一次version request请求，但实际上Telink的设备会响应多次，这都是基线测试难以顾及到的地方。</p>
<p>作者也就是在测试这些Corner Case的情况下，发现了一系列Bug/漏洞，命名为SweynTooth，例如：</p>
<ul>
<li>CVE-2019-16336, CVE-2019-17519：链路层Length字段溢出，导致DoS和潜在的RCE</li>
<li>CVE-2019-17061, CVE-2019-17060：链路层的LLID处理不当导致死锁</li>
<li>CVE-2019-17517：处理L2CAP包时对长度字段的校验错误导致内存越界拷贝</li>
<li>&hellip;.</li>
<li><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-19194" target="_blank" rel="noopener noreferrer">CVE-2019-19194</a>：Telink SMP的Secure Connection实现在配对过程中发起LE加密流程时会导致全零LTK的安装</li>
</ul>
<p>加起来一共12个公开漏洞，不过利用场景都很有限，除了全零LTK漏洞外，大部分只能造成蓝牙芯片的固件崩溃重新启动或者死锁。不过，从这组漏洞中我们也能看到蓝牙固件的实现也是有不少问题的，蓝牙芯片固件的代码本身难以进行热更新，在一些特殊的HCI Event配合下，我们甚至可以从Controller中获取Host的命令执行权限。</p>
<h2 id="bluefrag" class="headerLink">
    <a href="#bluefrag" class="header-mark"></a>BlueFrag</h2><p>BlueFrag是2020年2月在Android安全通告中披露的一个严重漏洞，影响蓝牙子系统可实现远程命令执行。该漏洞主要是在Android中的L2CAP层实现上，是由于L2CAP的分片和重组包长度计算出错导致的内存破坏。</p>
<p>漏洞修复如下：</p>
<div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2">
  <div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    ">      
    <button 
      class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"
      aria-hidden="true">
          <div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg></div>
          <p class="tw-select-none !tw-my-1">diff</p>
      </button>

   <div class="tw-flex">
      <button 
        class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle line numbers"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"/></svg></button>

      <button 
        class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" 
        title="Toggle code wrap"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"/></svg></button>
      
      <button 
        class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden"
        title="Copy code">
          <span class="copy-icon tw-block"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg></span>
          <span class="check-icon tw-hidden"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/></svg></span>
      </button>
        
      <button 
        class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" 
        disabled
        aria-hidden="true"><svg class="icon"
    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"/></svg></button>
    </div>
  </div>
  <pre style="counter-reset: codeblock;" class="tw-block tw-m-0 tw-p-0"><code 
    id="codeblock-id-12" 
    class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      "><span class="line"><span class="cl"><span class="gh">diff --git a/hci/src/packet_fragmenter.cc b/hci/src/packet_fragmenter.cc
</span></span></span><span class="line"><span class="cl"><span class="gh">index 5036ed5..143fc23 100644
</span></span></span><span class="line"><span class="cl"><span class="gh"></span><span class="gd">--- a/hci/src/packet_fragmenter.cc
</span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+++ b/hci/src/packet_fragmenter.cc
</span></span></span><span class="line"><span class="cl"><span class="gi"></span><span class="gu">@@ -221,7 +221,8 @@
</span></span></span><span class="line"><span class="cl"><span class="gu"></span>                  &#34;%s got packet which would exceed expected length of %d. &#34;
</span></span><span class="line"><span class="cl">                  &#34;Truncating.&#34;,
</span></span><span class="line"><span class="cl">                  __func__, partial_packet-&gt;len);
</span></span><span class="line"><span class="cl"><span class="gd">-        packet-&gt;len = partial_packet-&gt;len - partial_packet-&gt;offset;
</span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+        packet-&gt;len =
</span></span></span><span class="line"><span class="cl"><span class="gi">+            (partial_packet-&gt;len - partial_packet-&gt;offset) + packet-&gt;offset;
</span></span></span><span class="line"><span class="cl"><span class="gi"></span>         projected_offset = partial_packet-&gt;len;
</span></span><span class="line"><span class="cl">       }
</span></span></code></pre>
</div>
<p>值得一提的是，这个漏洞本身会导致memcpy拷贝负数长度，正常情况下会一直拷贝直至触发非法内存空间，但在Android的libc实现上memcpy优化的实现会令拷贝前面的若干字节以及末尾的64字节退出，从而出现一个可控的内存越界读写，在此基础上可以进一步实现控制流劫持导致远程命令执行。 Android中L2CAP的实现在用户层中，称为BlueDroid，用户进程为com.android.bluetooth，因此执行命令后所获得的权限也是bluetooth权限。</p>
<p>参考资料：</p>
<ul>
<li><a href="https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/" target="_blank" rel="noopener noreferrer">https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/</a></li>
<li><a href="https://android.googlesource.com/platform/system/bt/&#43;/3cb7149d8fed2d7d77ceaa95bf845224c4db3baf%5e!/#F0" target="_blank" rel="noopener noreferrer">https://android.googlesource.com/platform/system/bt/+/3cb7149d8fed2d7d77ceaa95bf845224c4db3baf%5E%21/#F0</a></li>
</ul>
<h1 id="应用安全" class="headerLink">
    <a href="#%e5%ba%94%e7%94%a8%e5%ae%89%e5%85%a8" class="header-mark"></a>应用安全</h1><p>前面介绍的都是比较底层的协议，而在一般安全论坛和关于蓝牙安全的相关文章中介绍的通常更多是应用相关的安全，比如蓝牙智能门锁的重放、越权等问题。这部分协议的交互主要在LTK协商之后，基于会话秘钥加密的信道传输应用层信息，当然也可以是BLE中基于广播的通信。</p>
<p>在上层的通信中，一个重要的概念就是Profile，表示设备所支持功能的一种垂直切分。其中既包括所有设备都通用的如<code>Generic Access Profile(GAP)</code>和<code>Generic Attribute Profile(GATT)</code>，也包括基于特定用途的Profile如<code>Proximity Profile</code>和<code>Glucose Profile</code>等。Profile本质上定义了如何使用协议来实现某种通用或者特定的目的。</p>
<p>Profile的存在是蓝牙协议与众不同的一个地方，为什么会有这么多Profile，而不是像通用协议一样，定义好协议结构和字段，然后进行通用拓展呢？在《计算机网络》中有这么一段话:</p>
<blockquote>
  <p>真的有必要分清楚所有应用的细节，并且为每一种应用提供不同的协议栈吗？也许没有这个必要。但是，由于存在多个不同的工作组，他们分别负责设计标准的不同部分，因此，每个工作组都只关注特定的问题，从而形成了自己的Profile。你可以把这个看成是康威法则在起作用。或许蓝牙标准根本不用25个协议栈，两个就可以了，一个用于文件传输，另外一个用于流式实时通信。</p>
</blockquote><p>可见SIG蓝牙特别兴趣小组各自为战是蓝牙Profile的形式发展至今的重要原因之一。</p>
<p>GATT定义了一个标准的数据模型与流程用以设备发现、读写和推送数据。一个GATT server中通常包含多个Service，而每个Service又可以包含多个<strong>Characteristic</strong>。每个Characteristic都有一个16位或者128位的UUID，并带有可选的数据描述<strong>Descriptor</strong>。Characteristic是GATT通信中最小的数据单元，封装了一个单一的数据点，其中可能包含一组相关的数据，比如加速传感器x/y/z轴的坐标数据。根据权限的不同，我们可以向Characteristic中读写数据。</p>
<p>举个例子，对于心率计而言，可能有一个<strong>Heart Rate Service</strong>，其中包括两个Characteristic，分别是HM(Heart Rate Measurement)和BSL(Body Sensor Location)，前者还包含一个Descriptor，CCCD(Client Characteristic Configuration Descriptor)，这是一个常见的descriptor，用来表示通知开关状态。</p>
<p><figure><a class="lightgallery" href="/img/2021-07-10-bluetooth-sec/7.png" title="service" data-thumbnail="/img/2021-07-10-bluetooth-sec/7.png" data-sub-html="<h2>示例: 蓝牙的心跳服务结构</h2><p>service</p>"><img  loading="lazy" src='/img/2021-07-10-bluetooth-sec/7.png'   alt="service"  ></a><figcaption class="image-caption">示例: 蓝牙的心跳服务结构</figcaption>
</figure></p>
<p>其中大部分常用的属性在蓝牙SIG文档中都定义了对应的UUID，当然也包括一部分Vendor Specific的UUID留给厂商自行去拓展和定义。</p>
<p>研究蓝牙应用安全的一个常用办法是在收发数据时候进行抓包，比如Android中支持在开发者模式中打开蓝牙日志，iOS支持使用XCode的拓展工具PacketLogger进行抓包。此外还可以通过对应用进行逆向或者动态追踪的方式来观察应用层的交互数据，从而挖掘背后存在的安全漏洞。由于这类问题与具体的产品和应用有关，这里就不举例说明了，感兴趣的朋友可以参考相关蓝牙应用设备的公开安全通告。</p>
<h1 id="小结" class="headerLink">
    <a href="#%e5%b0%8f%e7%bb%93" class="header-mark"></a>小结</h1><p>从漏洞的影响面来看，协议类的蓝牙漏洞通常影响广泛且难以修复，因为需要修改协议并推进各个蓝牙厂商去进行重新实现和更新；从危害性来看，协议类的漏洞往往影响的是蓝牙信道的安全，在一般场景中危害相对有限；而实现类的漏洞通常导致内存破坏，被攻击者精心构造利用则可以造成整个系统的沦陷，一旦被利用就很可能是个严重的 RCE；应用类的漏洞通常是厂商的应用开发者所造成的疏忽，在某些情况下可导致智能设备被劫持控制，虽然修复较为容易，但这类漏洞频繁出现在不同的蓝牙应用中，因此其安全影响也是不可忽视的。</p>]]></description>
</item></channel>
</rss>
