├── .github
├── ISSUE_TEMPLATE
│ ├── bug.yml
│ └── config.yml
├── README-zh_Hans.md
└── workflows
│ └── main.yml
├── .gitignore
├── IntelBTPatcher
├── Info.plist
├── IntelBTPatcher.cpp
└── IntelBTPatcher.hpp
├── IntelBluetoothFirmware.xcodeproj
└── project.pbxproj
├── IntelBluetoothFirmware
├── BtIntel.cpp
├── BtIntel.h
├── BtIntelFw.cpp
├── BtIntelVSC.cpp
├── FwData.h
├── Hci.h
├── Info.plist
├── IntelBluetoothFirmware.cpp
├── IntelBluetoothFirmware.hpp
├── IntelBluetoothOpsGen1.cpp
├── IntelBluetoothOpsGen1.hpp
├── IntelBluetoothOpsGen2.cpp
├── IntelBluetoothOpsGen2.hpp
├── IntelBluetoothOpsGen3.cpp
├── IntelBluetoothOpsGen3.hpp
├── Log.h
├── USBDeviceController.cpp
├── USBDeviceController.hpp
├── fw
│ ├── ibt-0040-0041.ddc
│ ├── ibt-0040-0041.sfi
│ ├── ibt-0040-1020.ddc
│ ├── ibt-0040-1020.sfi
│ ├── ibt-0040-1050.ddc
│ ├── ibt-0040-1050.sfi
│ ├── ibt-0040-2120.ddc
│ ├── ibt-0040-2120.sfi
│ ├── ibt-0040-4150.ddc
│ ├── ibt-0040-4150.sfi
│ ├── ibt-0041-0041.ddc
│ ├── ibt-0041-0041.sfi
│ ├── ibt-0180-0041.ddc
│ ├── ibt-0180-0041.sfi
│ ├── ibt-0180-1050.ddc
│ ├── ibt-0180-1050.sfi
│ ├── ibt-0180-4150.ddc
│ ├── ibt-0180-4150.sfi
│ ├── ibt-0291-0291.ddc
│ ├── ibt-0291-0291.sfi
│ ├── ibt-1040-0041.ddc
│ ├── ibt-1040-0041.sfi
│ ├── ibt-1040-1020.ddc
│ ├── ibt-1040-1020.sfi
│ ├── ibt-1040-1050.ddc
│ ├── ibt-1040-1050.sfi
│ ├── ibt-1040-2120.ddc
│ ├── ibt-1040-2120.sfi
│ ├── ibt-1040-4150.ddc
│ ├── ibt-1040-4150.sfi
│ ├── ibt-11-5.ddc
│ ├── ibt-11-5.sfi
│ ├── ibt-12-16.ddc
│ ├── ibt-12-16.sfi
│ ├── ibt-17-0-1.ddc
│ ├── ibt-17-0-1.sfi
│ ├── ibt-17-1.ddc
│ ├── ibt-17-1.sfi
│ ├── ibt-17-16-1.ddc
│ ├── ibt-17-16-1.sfi
│ ├── ibt-17-2.ddc
│ ├── ibt-17-2.sfi
│ ├── ibt-18-0-1.ddc
│ ├── ibt-18-0-1.sfi
│ ├── ibt-18-1.ddc
│ ├── ibt-18-1.sfi
│ ├── ibt-18-16-1.ddc
│ ├── ibt-18-16-1.sfi
│ ├── ibt-18-2.ddc
│ ├── ibt-18-2.sfi
│ ├── ibt-19-0-0.ddc
│ ├── ibt-19-0-0.sfi
│ ├── ibt-19-0-1.ddc
│ ├── ibt-19-0-1.sfi
│ ├── ibt-19-0-3.ddc
│ ├── ibt-19-0-3.sfi
│ ├── ibt-19-0-4.ddc
│ ├── ibt-19-0-4.sfi
│ ├── ibt-19-16-4.ddc
│ ├── ibt-19-16-4.sfi
│ ├── ibt-19-240-1.ddc
│ ├── ibt-19-240-1.sfi
│ ├── ibt-19-240-4.ddc
│ ├── ibt-19-240-4.sfi
│ ├── ibt-19-32-0.ddc
│ ├── ibt-19-32-0.sfi
│ ├── ibt-19-32-1.ddc
│ ├── ibt-19-32-1.sfi
│ ├── ibt-19-32-4.ddc
│ ├── ibt-19-32-4.sfi
│ ├── ibt-20-0-3.ddc
│ ├── ibt-20-0-3.sfi
│ ├── ibt-20-1-3.ddc
│ ├── ibt-20-1-3.sfi
│ ├── ibt-20-1-4.ddc
│ ├── ibt-20-1-4.sfi
│ ├── ibt-hw-37.7.10-fw-1.0.1.2d.d.bseq
│ ├── ibt-hw-37.7.10-fw-1.0.2.3.d.bseq
│ ├── ibt-hw-37.7.10-fw-1.80.1.2d.d.bseq
│ ├── ibt-hw-37.7.10-fw-1.80.2.3.d.bseq
│ ├── ibt-hw-37.7.bseq
│ ├── ibt-hw-37.8.10-fw-1.10.2.27.d.bseq
│ ├── ibt-hw-37.8.10-fw-1.10.3.11.e.bseq
│ ├── ibt-hw-37.8.10-fw-22.50.19.14.f.bseq
│ └── ibt-hw-37.8.bseq
├── linux.h
├── zutil.c
└── zutil.h
├── IntelBluetoothInjector
└── Info.plist
├── LICENSE
├── README.md
├── iwlwifi-firmware-license
└── scripts
├── fw_gen.sh
└── zlib_compress_fw.py
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report
3 |
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Thanks for taking the time to fill out this bug report!
9 |
10 | - type: dropdown
11 | id: docs
12 | attributes:
13 | label: Have you read the docs?
14 | options:
15 | - 'No'
16 | - 'Yes'
17 | validations:
18 | required: true
19 |
20 | - type: input
21 | id: macos-ver
22 | attributes:
23 | label: macOS Version
24 | description: Which version of macOS are you using?
25 | placeholder: macOS 12
26 | validations:
27 | required: true
28 |
29 | - type: input
30 | id: kext-ver
31 | attributes:
32 | label: Kext Version
33 | description: Which version of the Kext are you using?
34 | placeholder: v2.2.0
35 | validations:
36 | required: true
37 |
38 | - type: input
39 | id: card-model
40 | attributes:
41 | label: Wireless Adapter Model and USB Product ID
42 | description: USB Product ID can be obtained from Hackintool when using macOS versions prior to Monterey or only when Bluetooth is working on macOS Monterey and newer.
When bluetooth is not working on macOS Monterey and newer, the only method to obtain the USB Product ID is through IORegistry.
43 | placeholder: Intel 9560AC (0xAAA)
44 | validations:
45 | required: true
46 |
47 | - type: textarea
48 | id: description
49 | attributes:
50 | label: Description
51 | description: A clear and concise description of what the bug is
52 | validations:
53 | required: true
54 |
55 | - type: textarea
56 | id: info
57 | attributes:
58 | label: Info in System Report - Bluetooth
59 | description: Copy and paste all contents with sensitive information removed down below
(Text in this field will be automatically formatted into code, so no need for backticks.)
60 | render: shell
61 | validations:
62 | required: true
63 |
64 | - type: textarea
65 | id: logs
66 | attributes:
67 | label: Relevant log output
68 | description: Output of `sudo dmesg | grep -i IntelBluetooth` with DebugEnhancer.kext installed.
(Text in this field will be automatically formatted into code, so no need for backticks.)
69 | render: shell
70 | validations:
71 | required: true
72 |
73 | - type: textarea
74 | id: panic-logs
75 | attributes:
76 | label: Kernel Panic Logs
77 | description: In case there is a kernel panic, add `keepsyms=1` in boot-args then paste the panic info below
(Text in this field will be automatically formatted into code, so no need for backticks.)
78 | render: shell
79 | validations:
80 | required: false
81 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Documentation
4 | url: https://openintelwireless.github.io/IntelBluetoothFirmware/
5 | about: Install guides and FAQ
6 | - name: Gitter Chat Room
7 | url: https://gitter.im/OpenIntelWireless/IntelBluetoothFirmware
8 | about: Community chat room for IntelBluetoothFirmware
9 |
--------------------------------------------------------------------------------
/.github/README-zh_Hans.md:
--------------------------------------------------------------------------------
1 | # IntelBluetoothFirmware
2 |
3 | 
4 |
5 | - [English](/README.md)
6 | - **简体中文**
7 |
8 | ## 简介
9 |
10 | IntelBluetoothFirmware 是一个用于在 macOS 中启用原生蓝牙的固件上传驱动,固件的二进制文件来自 Linux。
11 |
12 | 经过数月的测试后,这个驱动已经被证实可以正常稳定工作。
13 |
14 | [](https://gitter.im/OpenIntelWireless/IntelBluetoothFirmware?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
15 |
16 | ## 文档
17 |
18 | **请在使用驱动或提交 issue 之前仔细阅读文档!**
19 |
20 | - [支持列表](https://openintelwireless.github.io/IntelBluetoothFirmware/Compat.html)
21 | - [安装方法](https://openintelwireless.github.io/IntelBluetoothFirmware/Installation.html)
22 | - [常见疑问](https://openintelwireless.github.io/IntelBluetoothFirmware/FAQ.html)
23 | - [排错方法](https://openintelwireless.github.io/IntelBluetoothFirmware/Troubleshooting.html)
24 |
25 | ## 参考资料
26 |
27 | - [torvalds/linux](https://github.com/torvalds/linux)
28 | - [acidanthera/BrcmPatchRAM](https://github.com/acidanthera/BrcmPatchRAM)
29 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request, workflow_dispatch]
4 |
5 | jobs:
6 |
7 | build:
8 |
9 | runs-on: macos-latest
10 |
11 | steps:
12 |
13 | - uses: actions/checkout@v4
14 |
15 | - name: Get Lilu SHA
16 | id: get-lilu-sha
17 | run: |
18 | echo "hash=$(git ls-remote https://github.com/acidanthera/Lilu.git HEAD | awk '{ print $1 }')" >> "$GITHUB_OUTPUT"
19 |
20 | - name: Cache Lilu
21 | id: cache-lilu
22 | uses: actions/cache@v4
23 | with:
24 | path: Lilu.kext
25 | key: Lilu-${{ steps.get-lilu-sha.outputs.hash }}
26 |
27 | - name: Install MacKernelSDK
28 | run: |
29 | git clone --depth=1 https://github.com/acidanthera/MacKernelSDK.git
30 |
31 | - name: Install Lilu SDK
32 | if: steps.cache-lilu.outputs.cache-hit != 'true'
33 | run: |
34 | git clone --depth=1 https://github.com/acidanthera/Lilu.git
35 | cd Lilu || exit 1
36 | ln -s ../MacKernelSDK MacKernelSDK
37 | xcodebuild -configuration Debug -arch x86_64 | xcpretty && ret=${PIPESTATUS[0]}
38 | if [[ $ret -ne 0 || ! -d build/Debug/Lilu.kext ]]; then
39 | exit 1
40 | fi
41 | cp -R build/Debug/Lilu.kext ../
42 |
43 | - name: Debug Build
44 | run: |
45 | xcodebuild -alltargets -configuration Debug | xcpretty && exit ${PIPESTATUS[0]}
46 |
47 | - name: Release Build
48 | run: |
49 | xcodebuild -alltargets -configuration Release | xcpretty && exit ${PIPESTATUS[0]}
50 |
51 | - name: Upload to Artifacts
52 | uses: actions/upload-artifact@v4
53 | with:
54 | name: ${{ github.event.repository.name }}
55 | path: build/*/*.zip
56 | if-no-files-found: error
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | DerivedData
3 | build
4 | xcuserdata
5 | xcshareddata
6 | project.xcworkspace
7 | FwBinary.cpp
8 | MacKernelSDK
9 | Lilu.kext
10 | zlib_compress_fw.pyc
11 |
--------------------------------------------------------------------------------
/IntelBTPatcher/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | IOKitPersonalities
22 |
23 | IntelBTPatcher
24 |
25 | CFBundleIdentifier
26 | $(PRODUCT_BUNDLE_IDENTIFIER)
27 | IOClass
28 | $(PRODUCT_NAME:rfc1034identifier)
29 | IOMatchCategory
30 | $(PRODUCT_NAME:rfc1034identifier)
31 | IOProviderClass
32 | IOResources
33 | IOResourceMatch
34 | IOKit
35 |
36 |
37 | NSHumanReadableCopyright
38 | Copyright © 2022 zxystd. All rights reserved.
39 | OSBundleLibraries
40 |
41 | as.vit9696.Lilu
42 | 1.2.0
43 | com.apple.iokit.IOUSBHostFamily
44 | 1.2
45 | com.apple.kpi.bsd
46 | 12.0.0
47 | com.apple.kpi.dsep
48 | 12.0.0
49 | com.apple.kpi.iokit
50 | 12.0.0
51 | com.apple.kpi.libkern
52 | 12.0.0
53 | com.apple.kpi.mach
54 | 12.0.0
55 | com.apple.kpi.unsupported
56 | 12.0.0
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/IntelBTPatcher/IntelBTPatcher.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBTPatcher.cpp
3 | // IntelBTPatcher
4 | //
5 | // Created by zxystd on 2021/2/8.
6 | //
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include "IntelBTPatcher.hpp"
13 |
14 | static CIntelBTPatcher ibtPatcher;
15 | static CIntelBTPatcher *callbackIBTPatcher = nullptr;
16 |
17 | static const char *bootargOff[] {
18 | "-ibtcompatoff"
19 | };
20 |
21 | static const char *bootargDebug[] {
22 | "-ibtcompatdbg"
23 | };
24 |
25 | static const char *bootargBeta[] {
26 | "-ibtcompatbeta"
27 | };
28 |
29 | PluginConfiguration ADDPR(config) {
30 | xStringify(PRODUCT_NAME),
31 | parseModuleVersion(xStringify(MODULE_VERSION)),
32 | LiluAPI::AllowNormal | LiluAPI::AllowInstallerRecovery | LiluAPI::AllowSafeMode,
33 | bootargOff,
34 | arrsize(bootargOff),
35 | bootargDebug,
36 | arrsize(bootargDebug),
37 | bootargBeta,
38 | arrsize(bootargBeta),
39 | KernelVersion::MountainLion,
40 | KernelVersion::Sequoia,
41 | []() {
42 | ibtPatcher.init();
43 | }
44 | };
45 |
46 | static const char *IntelBTPatcher_IOBluetoothFamily[] { "/System/Library/Extensions/IOBluetoothFamily.kext/Contents/MacOS/IOBluetoothFamily" };
47 |
48 | static KernelPatcher::KextInfo IntelBTPatcher_IOBluetoothInfo {
49 | "com.apple.iokit.IOBluetoothFamily",
50 | IntelBTPatcher_IOBluetoothFamily,
51 | 1,
52 | {true, true},
53 | {},
54 | KernelPatcher::KextInfo::Unloaded
55 | };
56 |
57 | static const char *IntelBTPatcher_IOUSBHostFamily[] {
58 | "/System/Library/Extensions/IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily" };
59 |
60 | static KernelPatcher::KextInfo IntelBTPatcher_IOUsbHostInfo {
61 | "com.apple.iokit.IOUSBHostFamily",
62 | IntelBTPatcher_IOUSBHostFamily,
63 | 1,
64 | {true, true},
65 | {},
66 | KernelPatcher::KextInfo::Unloaded
67 | };
68 |
69 | bool CIntelBTPatcher::_randomAddressInit = false;
70 |
71 | bool CIntelBTPatcher::init()
72 | {
73 | DBGLOG(DRV_NAME, "%s", __PRETTY_FUNCTION__);
74 | callbackIBTPatcher = this;
75 | if (getKernelVersion() < KernelVersion::Monterey) {
76 | lilu.onKextLoadForce(&IntelBTPatcher_IOBluetoothInfo, 1,
77 | [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
78 | callbackIBTPatcher->processKext(patcher, index, address, size);
79 | }, this);
80 | } else {
81 | lilu.onKextLoadForce(&IntelBTPatcher_IOUsbHostInfo, 1,
82 | [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
83 | callbackIBTPatcher->processKext(patcher, index, address, size);
84 | }, this);
85 | }
86 | return true;
87 | }
88 |
89 | void CIntelBTPatcher::free()
90 | {
91 | DBGLOG(DRV_NAME, "%s", __PRETTY_FUNCTION__);
92 | }
93 |
94 | void CIntelBTPatcher::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size)
95 | {
96 | DBGLOG(DRV_NAME, "%s", __PRETTY_FUNCTION__);
97 | if (getKernelVersion() < KernelVersion::Monterey) {
98 | if (IntelBTPatcher_IOBluetoothInfo.loadIndex == index) {
99 | DBGLOG(DRV_NAME, "%s", IntelBTPatcher_IOBluetoothInfo.id);
100 |
101 | KernelPatcher::RouteRequest findQueueRequestRequest {
102 | "__ZN25IOBluetoothHostController17FindQueuedRequestEtP22BluetoothDeviceAddresstbPP21IOBluetoothHCIRequest",
103 | newFindQueueRequest,
104 | oldFindQueueRequest
105 | };
106 | patcher.routeMultiple(index, &findQueueRequestRequest, 1, address, size);
107 | if (patcher.getError() == KernelPatcher::Error::NoError) {
108 | DBGLOG(DRV_NAME, "routed %s", findQueueRequestRequest.symbol);
109 | } else {
110 | SYSLOG(DRV_NAME, "failed to resolve %s, error = %d", findQueueRequestRequest.symbol, patcher.getError());
111 | patcher.clearError();
112 | }
113 |
114 | }
115 | } else {
116 | if (IntelBTPatcher_IOUsbHostInfo.loadIndex == index) {
117 | SYSLOG(DRV_NAME, "%s", IntelBTPatcher_IOUsbHostInfo.id);
118 |
119 | KernelPatcher::RouteRequest hostDeviceRequest {
120 | "__ZN15IOUSBHostDevice13deviceRequestEP9IOServiceRN11StandardUSB13DeviceRequestEPvP18IOMemoryDescriptorRjP19IOUSBHostCompletionj",
121 | newHostDeviceRequest,
122 | oldHostDeviceRequest
123 | };
124 | patcher.routeMultiple(index, &hostDeviceRequest, 1, address, size);
125 | if (patcher.getError() == KernelPatcher::Error::NoError) {
126 | SYSLOG(DRV_NAME, "routed %s", hostDeviceRequest.symbol);
127 | } else {
128 | SYSLOG(DRV_NAME, "failed to resolve %s, error = %d", hostDeviceRequest.symbol, patcher.getError());
129 | patcher.clearError();
130 | }
131 | }
132 | }
133 | }
134 |
135 | #pragma mark - For Bigsur-, patch unhandled 0x2019 opcode
136 |
137 | #define HCI_OP_LE_START_ENCRYPTION 0x2019
138 |
139 | IOReturn CIntelBTPatcher::newFindQueueRequest(void *that, unsigned short arg1, void *addr, unsigned short arg2, bool arg3, void **hciRequestPtr)
140 | {
141 | IOReturn ret = FunctionCast(newFindQueueRequest, callbackIBTPatcher->oldFindQueueRequest)(that, arg1, addr, arg2, arg3, hciRequestPtr);
142 | if (ret != 0 && arg1 == HCI_OP_LE_START_ENCRYPTION) {
143 | ret = FunctionCast(newFindQueueRequest, callbackIBTPatcher->oldFindQueueRequest)(that, arg1, addr, 0xffff, arg3, hciRequestPtr);
144 | DBGLOG(DRV_NAME, "%s ret: %d arg1: 0x%04x arg2: 0x%04x arg3: %d ptr: %p", __FUNCTION__, ret, arg1, arg2, arg3, *hciRequestPtr);
145 | }
146 | return ret;
147 | }
148 |
149 | #pragma mark - For Monterey+ patch for intercept HCI REQ and RESP
150 |
151 | StandardUSB::DeviceRequest randomAddressRequest;
152 | // Hardcoded Random Address HCI Command
153 | const uint8_t randomAddressHci[9] = {0x05, 0x20, 0x06, 0x94, 0x50, 0x64, 0xD0, 0x78, 0x6B};
154 | IOBufferMemoryDescriptor *writeHCIDescriptor = nullptr;
155 |
156 | #define MAX_HCI_BUF_LEN 255
157 | #define HCI_OP_RESET 0x0c03
158 | #define HCI_OP_LE_SET_SCAN_PARAM 0x200B
159 | #define HCI_OP_LE_SET_SCAN_ENABLE 0x200C
160 |
161 | IOReturn CIntelBTPatcher::newHostDeviceRequest(void *that, IOService *provider, StandardUSB::DeviceRequest &request, void *data, IOMemoryDescriptor *descriptor, unsigned int &length, IOUSBHostCompletion *completion, unsigned int timeout)
162 | {
163 | HciCommandHdr *hdr = nullptr;
164 | uint32_t hdrLen = 0;
165 | char hciBuf[MAX_HCI_BUF_LEN] = {0};
166 |
167 | if (data == nullptr) {
168 | if (descriptor != nullptr &&
169 | (getKernelVersion() < KernelVersion::Sequoia || !descriptor->prepare(kIODirectionOut))) {
170 | if (descriptor->getLength() > 0) {
171 | descriptor->readBytes(0, hciBuf, min(descriptor->getLength(), MAX_HCI_BUF_LEN));
172 | hdrLen = (uint32_t)min(descriptor->getLength(), MAX_HCI_BUF_LEN);
173 | }
174 | if (getKernelVersion() >= KernelVersion::Sequoia)
175 | descriptor->complete(kIODirectionOut);
176 | }
177 | hdr = (HciCommandHdr *)hciBuf;
178 | if (hdr->opcode == HCI_OP_LE_SET_SCAN_PARAM) {
179 | if (!_randomAddressInit) {
180 | randomAddressRequest.bmRequestType = makeDeviceRequestbmRequestType(kRequestDirectionOut, kRequestTypeClass, kRequestRecipientInterface);
181 | randomAddressRequest.bRequest = 0xE0;
182 | randomAddressRequest.wIndex = 0;
183 | randomAddressRequest.wValue = 0;
184 | randomAddressRequest.wLength = 9;
185 | length = 9;
186 | if (writeHCIDescriptor == nullptr)
187 | writeHCIDescriptor = IOBufferMemoryDescriptor::withBytes(randomAddressHci, 9, kIODirectionOut);
188 | writeHCIDescriptor->prepare(kIODirectionOut);
189 | IOReturn ret = FunctionCast(newHostDeviceRequest, callbackIBTPatcher->oldHostDeviceRequest)(that, provider, randomAddressRequest, nullptr, writeHCIDescriptor, length, nullptr, timeout);
190 | writeHCIDescriptor->complete();
191 | const char *randAddressDump = _hexDumpHCIData((uint8_t *)randomAddressHci, 9);
192 | if (randAddressDump) {
193 | SYSLOG(DRV_NAME, "[PATCH] Sending Random Address HCI %lld %s", ret, randAddressDump);
194 | IOFree((void *)randAddressDump, 9 * 3 + 1);
195 | }
196 | _randomAddressInit = true;
197 | SYSLOG(DRV_NAME, "[PATCH] Resend LE SCAN PARAM HCI %lld", ret);
198 | }
199 | }
200 | } else {
201 | hdr = (HciCommandHdr *)data;
202 | hdrLen = request.wLength - 3;
203 | }
204 | if (hdr) {
205 | // HCI reset, we need to send Random address again
206 | if (hdr->opcode == HCI_OP_RESET)
207 | _randomAddressInit = false;
208 | #if DEBUG
209 | DBGLOG(DRV_NAME, "[%s] bRequest: 0x%x direction: %s type: %s recipient: %s wValue: 0x%02x wIndex: 0x%02x opcode: 0x%04x len: %d length: %d async: %d", provider->getName(), request.bRequest, requestDirectionNames[(request.bmRequestType & kDeviceRequestDirectionMask) >> kDeviceRequestDirectionPhase], requestRecipientNames[(request.bmRequestType & kDeviceRequestRecipientMask) >> kDeviceRequestRecipientPhase], requestTypeNames[(request.bmRequestType & kDeviceRequestTypeMask) >> kDeviceRequestTypePhase], request.wValue, request.wIndex, hdr->opcode, hdr->len, request.wLength, completion != nullptr);
210 | if (hdrLen) {
211 | const char *dump = _hexDumpHCIData((uint8_t *)hdr, hdrLen);
212 | if (dump) {
213 | DBGLOG(DRV_NAME, "[Request]: %s", dump);
214 | IOFree((void *)dump, hdrLen * 3 + 1);
215 | }
216 | }
217 | #endif
218 | }
219 | return FunctionCast(newHostDeviceRequest, callbackIBTPatcher->oldHostDeviceRequest)(that, provider, request, data, descriptor, length, completion, timeout);
220 | }
221 |
--------------------------------------------------------------------------------
/IntelBTPatcher/IntelBTPatcher.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBTPatcher.h
3 | // IntelBTPatcher
4 | //
5 | // Created by zxystd on 2021/2/8.
6 | //
7 |
8 | #ifndef IntelBTPatcher_h
9 | #define IntelBTPatcher_h
10 |
11 | #include
12 |
13 | #include
14 |
15 | #define DRV_NAME "ibtp"
16 |
17 | class BluetoothDeviceAddress;
18 |
19 | typedef struct {
20 | void *owner;
21 | IOMemoryDescriptor *dataBuffer;
22 | IOUSBHostCompletionAction action;
23 | } AsyncOwnerData;
24 |
25 | typedef struct __attribute__((packed))
26 | {
27 | uint16_t opcode; /* OCF & OGF */
28 | uint8_t len;
29 | uint8_t data[];
30 | } HciCommandHdr;
31 |
32 | typedef struct __attribute__((packed))
33 | {
34 | uint8_t evt;
35 | uint8_t len;
36 | } HciEventHdr;
37 |
38 | typedef struct __attribute__((packed))
39 | {
40 | HciEventHdr evt;
41 | uint8_t numCommands;
42 | uint16_t opcode;
43 | uint8_t data[];
44 | } HciResponse;
45 |
46 | const char *requestDirectionNames[] = {
47 | "OUT",
48 | "IN"
49 | };
50 |
51 | const char *requestTypeNames[] = {
52 | "Standard",
53 | "Class",
54 | "Vendor"
55 | };
56 |
57 | const char *requestRecipientNames[] = {
58 | "Device",
59 | "Interface",
60 | "Endpoint",
61 | "Other"
62 | };
63 |
64 | const char* _hexDumpHCIData(uint8_t *buf, size_t len)
65 | {
66 | ssize_t str_len = len * 3 + 1;
67 | char *str = (char*)IOMalloc(str_len);
68 | if (!str)
69 | return nullptr;
70 | for (size_t i = 0; i < len; i++)
71 | snprintf(str + 3 * i, (len - i) * 3, "%02x ", buf[i]);
72 | str[MAX(str_len - 2, 0)] = 0;
73 | return str;
74 | }
75 |
76 | class CIntelBTPatcher {
77 | public:
78 | bool init();
79 | void free();
80 |
81 | void processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
82 | static IOReturn newFindQueueRequest(void *that, unsigned short arg1, void *addr, unsigned short arg2, bool arg3, void **hciRequestPtr);
83 |
84 | static IOReturn newHostDeviceRequest(void *that, IOService *provider, StandardUSB::DeviceRequest &request, void *data, IOMemoryDescriptor *descriptor, unsigned int &length,IOUSBHostCompletion *completion, unsigned int timeout);
85 |
86 |
87 | mach_vm_address_t oldFindQueueRequest {};
88 | mach_vm_address_t oldHostDeviceRequest {};
89 |
90 | private:
91 | static bool _randomAddressInit;
92 | };
93 |
94 | #endif /* IntelBTPatcher_h */
95 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/BtIntel.cpp:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // BtIntel.cpp
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/11/17.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #include "BtIntel.h"
15 | #include "Log.h"
16 |
17 | #define super OSObject
18 | OSDefineMetaClassAndAbstractStructors(BtIntel, OSObject)
19 |
20 | bool BtIntel::
21 | initWithDevice(IOService *client, IOUSBHostDevice *dev)
22 | {
23 | XYLog("%s\n", __PRETTY_FUNCTION__);
24 | if (!super::init()) {
25 | return false;
26 | }
27 |
28 | m_pUSBDeviceController = new USBDeviceController();
29 | if (!m_pUSBDeviceController->init(client, dev)) {
30 | return false;
31 | }
32 | if (!m_pUSBDeviceController->initConfiguration()) {
33 | return false;
34 | }
35 | if (!m_pUSBDeviceController->findInterface()) {
36 | return false;
37 | }
38 | if (!m_pUSBDeviceController->findPipes()) {
39 | return false;
40 | }
41 | return true;
42 | }
43 |
44 | void BtIntel::
45 | free()
46 | {
47 | XYLog("%s\n", __PRETTY_FUNCTION__);
48 | OSSafeReleaseNULL(m_pUSBDeviceController);
49 | super::free();
50 | }
51 |
52 | bool BtIntel::
53 | intelSendHCISync(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, int timeout)
54 | {
55 | // XYLog("%s cmd: 0x%02x len: %d\n", __PRETTY_FUNCTION__, cmd->opcode, cmd->len);
56 | IOReturn ret;
57 | if ((ret = m_pUSBDeviceController->sendHCIRequest(cmd, timeout)) != kIOReturnSuccess) {
58 | XYLog("%s sendHCIRequest failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
59 | return false;
60 | }
61 | if ((ret = m_pUSBDeviceController->interruptPipeRead(event, eventBufSize, size, timeout)) != kIOReturnSuccess) {
62 | XYLog("%s interruptPipeRead failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
63 | return false;
64 | }
65 | return true;
66 | }
67 |
68 | bool BtIntel::
69 | intelSendHCISyncEvent(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, uint8_t syncEvent, int timeout)
70 | {
71 | IOReturn ret;
72 | if ((ret = m_pUSBDeviceController->sendHCIRequest(cmd, timeout)) != kIOReturnSuccess) {
73 | XYLog("%s sendHCIRequest failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
74 | return false;
75 | }
76 | do {
77 | ret = m_pUSBDeviceController->interruptPipeRead(event, eventBufSize, size, timeout);
78 | if (ret != kIOReturnSuccess) {
79 | XYLog("%s interruptPipeRead failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
80 | break;
81 | }
82 | if (*(uint8_t *)event == syncEvent) {
83 | return true;
84 | }
85 | } while (true);
86 | return false;
87 | }
88 |
89 | bool BtIntel::
90 | intelBulkHCISync(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, int timeout)
91 | {
92 | // XYLog("%s cmd: 0x%02x len: %d\n", __FUNCTION__, cmd->opcode, cmd->len);
93 | IOReturn ret;
94 | if ((ret = m_pUSBDeviceController->bulkWrite(cmd, HCI_COMMAND_HDR_SIZE + cmd->len, timeout)) != kIOReturnSuccess) {
95 | XYLog("%s bulkWrite failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
96 | return false;
97 | }
98 | if ((ret = m_pUSBDeviceController->bulkPipeRead(event, eventBufSize, size, timeout)) != kIOReturnSuccess) {
99 | XYLog("%s bulkPipeRead failed: %s %d\n", __FUNCTION__, m_pUSBDeviceController->stringFromReturn(ret), ret);
100 | return false;
101 | }
102 | return true;
103 | }
104 |
105 | bool BtIntel::
106 | securedSend(uint8_t fragmentType, uint32_t len, const uint8_t *fragment)
107 | {
108 | bool ret = true;
109 | uint8_t buf[CMD_BUF_MAX_SIZE];
110 | HciCommandHdr *hciCommand = (HciCommandHdr *)buf;
111 |
112 | while (len > 0) {
113 | uint8_t fragment_len = (len > 252) ? 252 : len;
114 |
115 | memset(buf, 0, sizeof(buf));
116 | hciCommand->opcode = OSSwapHostToLittleInt16(0xfc09);
117 | hciCommand->len = fragment_len + 1;
118 | hciCommand->data[0] = fragmentType;
119 | memcpy(hciCommand->data + 1, fragment, fragment_len);
120 |
121 | if (!(ret = intelBulkHCISync(hciCommand, NULL, 0, NULL, HCI_INIT_TIMEOUT))) {
122 | XYLog("secure send failed\n");
123 | return ret;
124 | }
125 |
126 | len -= fragment_len;
127 | fragment += fragment_len;
128 | }
129 |
130 | return ret;
131 | }
132 |
133 | bool BtIntel::
134 | intelVersionInfo(IntelVersion *ver)
135 | {
136 | const char *variant;
137 |
138 | /* The hardware platform number has a fixed value of 0x37 and
139 | * for now only accept this single value.
140 | */
141 | if (ver->hw_platform != 0x37) {
142 | XYLog("Unsupported Intel hardware platform (%u)\n",
143 | ver->hw_platform);
144 | return false;
145 | }
146 |
147 | /* Check for supported iBT hardware variants of this firmware
148 | * loading method.
149 | *
150 | * This check has been put in place to ensure correct forward
151 | * compatibility options when newer hardware variants come along.
152 | */
153 | switch (ver->hw_variant) {
154 | case 0x0b: /* SfP */
155 | case 0x0c: /* WsP */
156 | case 0x11: /* JfP */
157 | case 0x12: /* ThP */
158 | case 0x13: /* HrP */
159 | case 0x14: /* CcP */
160 | break;
161 | default:
162 | XYLog("Unsupported Intel hardware variant (%u)\n",
163 | ver->hw_variant);
164 | return false;
165 | }
166 |
167 | switch (ver->fw_variant) {
168 | case 0x06:
169 | variant = "Bootloader";
170 | break;
171 | case 0x23:
172 | variant = "Firmware";
173 | break;
174 | default:
175 | XYLog("Unsupported firmware variant(%02x)\n", ver->fw_variant);
176 | return false;
177 | }
178 |
179 | XYLog("%s revision %u.%u build %u week %u %u\n",
180 | variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
181 | ver->fw_build_num, ver->fw_build_ww,
182 | 2000 + ver->fw_build_yy);
183 |
184 | return true;
185 | }
186 |
187 | bool BtIntel::
188 | intelBoot(uint32_t bootAddr)
189 | {
190 | uint8_t buf[CMD_BUF_MAX_SIZE];
191 | uint32_t actLen = 0;
192 | HciResponse *resp = (HciResponse *)buf;
193 |
194 | if (!sendIntelReset(bootAddr)) {
195 | XYLog("Intel Soft Reset failed\n");
196 | resetToBootloader();
197 | return false;
198 | }
199 |
200 | /* The bootloader will not indicate when the device is ready. This
201 | * is done by the operational firmware sending bootup notification.
202 | *
203 | * Booting into operational firmware should not take longer than
204 | * 1 second. However if that happens, then just fail the setup
205 | * since something went wrong.
206 | */
207 | IOReturn ret = m_pUSBDeviceController->interruptPipeRead(buf, sizeof(buf), &actLen, 1000);
208 | if (ret != kIOReturnSuccess || actLen <= 0) {
209 | XYLog("Intel boot failed\n");
210 | if (ret == kIOReturnTimeout) {
211 | XYLog("Reset to bootloader\n");
212 | resetToBootloader();
213 | }
214 | return false;
215 | }
216 | if (resp->evt.evt == 0xff && resp->numCommands == 0x02) {
217 | XYLog("Notify: Device reboot done\n");
218 | return true;
219 | }
220 | return false;
221 | }
222 |
223 | bool BtIntel::
224 | loadDDCConfig(const char *ddcFileName)
225 | {
226 | const uint8_t *fw_ptr;
227 | uint8_t buf[CMD_BUF_MAX_SIZE];
228 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
229 |
230 | OSData *fwData = requestFirmwareData(ddcFileName);
231 |
232 | if (fwData == NULL) {
233 | XYLog("DDC file not found: %s\n", ddcFileName);
234 | return false;
235 | }
236 |
237 | XYLog("Load DDC config: %s %d\n", ddcFileName, fwData->getLength());
238 |
239 | fw_ptr = (uint8_t *)fwData->getBytesNoCopy();
240 |
241 | /* DDC file contains one or more DDC structure which has
242 | * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
243 | */
244 | while (fwData->getLength() > fw_ptr - (uint8_t *)fwData->getBytesNoCopy()) {
245 | uint8_t cmd_plen = fw_ptr[0] + sizeof(uint8_t);
246 |
247 | cmd->opcode = OSSwapHostToLittleInt16(0xfc8b);
248 | cmd->len = cmd_plen;
249 | memcpy(cmd->data, fw_ptr, cmd->len);
250 | if (!intelSendHCISync(cmd, NULL, 0, NULL, HCI_INIT_TIMEOUT)) {
251 | XYLog("Failed to send Intel_Write_DDC\n");
252 | return false;
253 | }
254 |
255 | fw_ptr += cmd_plen;
256 | }
257 | OSSafeReleaseNULL(fwData);
258 |
259 | XYLog("Load DDC config done\n");
260 | return true;
261 | }
262 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/BtIntel.h:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // BtIntel.h
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/11/17.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #ifndef BtIntel_h
15 | #define BtIntel_h
16 |
17 | #include
18 | #include
19 |
20 | #include "USBDeviceController.hpp"
21 | #include "Hci.h"
22 |
23 | typedef struct __attribute__((packed)) {
24 | uint8_t status;
25 | uint8_t hw_platform;
26 | uint8_t hw_variant;
27 | uint8_t hw_revision;
28 | uint8_t fw_variant;
29 | uint8_t fw_revision;
30 | uint8_t fw_build_num;
31 | uint8_t fw_build_ww;
32 | uint8_t fw_build_yy;
33 | uint8_t fw_patch_num;
34 | } IntelVersion;
35 |
36 | typedef struct __attribute__((packed)) {
37 | uint8_t result;
38 | uint16_t opcode;
39 | uint8_t status;
40 | } IntelSecureSendResult;
41 |
42 | typedef struct __attribute__((packed)) {
43 | uint8_t reset_type;
44 | uint8_t patch_enable;
45 | uint8_t ddc_reload;
46 | uint8_t boot_option;
47 | uint32_t boot_param;
48 | } IntelReset;
49 |
50 | typedef struct __attribute__((packed)) {
51 | uint8_t b[6];
52 | } bdaddr_t;
53 |
54 | typedef struct __attribute__((packed)) {
55 | uint8_t type;
56 | uint8_t len;
57 | uint8_t val[];
58 | } IntelTLV;
59 |
60 | typedef struct __attribute__((packed)) {
61 | uint32_t cnvi_top;
62 | uint32_t cnvr_top;
63 | uint32_t cnvi_bt;
64 | uint32_t cnvr_bt;
65 | uint16_t dev_rev_id;
66 | uint8_t img_type;
67 | uint16_t timestamp;
68 | uint8_t build_type;
69 | uint32_t build_num;
70 | uint8_t secure_boot;
71 | uint8_t otp_lock;
72 | uint8_t api_lock;
73 | uint8_t debug_lock;
74 | uint8_t min_fw_build_nn;
75 | uint8_t min_fw_build_cw;
76 | uint8_t min_fw_build_yy;
77 | uint8_t limited_cce;
78 | uint8_t sbe_type;
79 | uint32_t git_sha1;
80 | bdaddr_t otp_bd_addr;
81 | } IntelVersionTLV;
82 |
83 | typedef struct __attribute__((packed)) {
84 | uint8_t zero;
85 | uint8_t num_cmds;
86 | uint8_t source;
87 | uint8_t reset_type;
88 | uint8_t reset_reason;
89 | uint8_t ddc_status;
90 | } IntelBootUp;
91 |
92 | typedef struct __attribute__((packed)) {
93 | uint8_t status;
94 | uint8_t otp_format;
95 | uint8_t otp_content;
96 | uint8_t otp_patch;
97 | uint16_t dev_revid;
98 | uint8_t secure_boot;
99 | uint8_t key_from_hdr;
100 | uint8_t key_type;
101 | uint8_t otp_lock;
102 | uint8_t api_lock;
103 | uint8_t debug_lock;
104 | bdaddr_t otp_bdaddr;
105 | uint8_t min_fw_build_nn;
106 | uint8_t min_fw_build_cw;
107 | uint8_t min_fw_build_yy;
108 | uint8_t limited_cce;
109 | uint8_t unlocked_state;
110 | } IntelBootParams;
111 |
112 | typedef struct __attribute__((packed)) {
113 | uint8_t page1[16];
114 | } IntelDebugFeatures;
115 |
116 | typedef struct __attribute__((packed))
117 | {
118 | uint16_t opcode; /* OCF & OGF */
119 | uint8_t len;
120 | } FWCommandHdr;
121 |
122 | #define HCI_OP_INTEL_VERSION 0xfc05
123 | #define HCI_OP_INTEL_RESET 0xfc52
124 | #define HCI_OP_INTEL_RESET_BOOT 0xfc01
125 |
126 | #define HCI_OP_INTEL_ENTER_MFG 0xfc11
127 | #define HCI_OP_READ_INTEL_BOOT_PARAMS 0xfc0d
128 | #define HCI_OP_INTEL_EVENT_MASK 0xfc52
129 |
130 | #define INTEL_HW_PLATFORM(cnvx_bt) ((uint8_t)(((cnvx_bt) & 0x0000ff00) >> 8))
131 | #define INTEL_HW_VARIANT(cnvx_bt) ((uint8_t)(((cnvx_bt) & 0x003f0000) >> 16))
132 | #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)
133 | #define INTEL_CNVX_TOP_STEP(cnvx_top) (((cnvx_top) & 0x0f000000) >> 24)
134 | #define INTEL_CNVX_TOP_PACK_SWAB(t, s) OSSwapInt16(((uint16_t)(((t) << 4) | (s))))
135 |
136 | #define BDADDR_INTEL (&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
137 | #define RSA_HEADER_LEN 644
138 | #define CSS_HEADER_OFFSET 8
139 | #define ECDSA_OFFSET 644
140 | #define ECDSA_HEADER_LEN 320
141 |
142 | #define CMD_BUF_MAX_SIZE 256
143 |
144 | class BtIntel : public OSObject {
145 | OSDeclareAbstractStructors(BtIntel)
146 | public:
147 |
148 | virtual bool initWithDevice(IOService *client, IOUSBHostDevice *dev);
149 |
150 | virtual void free() override;
151 |
152 | virtual bool setup() = 0;
153 |
154 | virtual bool shutdown() = 0;
155 |
156 | virtual bool getFirmwareName(char *fwname, size_t len) = 0;
157 |
158 | bool securedSend(uint8_t fragmentType, uint32_t len, const uint8_t *fragment);
159 |
160 | bool enterMfg();
161 |
162 | bool exitMfg(bool reset, bool patched);
163 |
164 | bool setEventMask(bool debug);
165 |
166 | bool setEventMaskMfg(bool debug);
167 |
168 | bool readVersion(IntelVersion *version);
169 |
170 | bool sendIntelReset(uint32_t bootParam);
171 |
172 | bool readBootParams(IntelBootParams *params);
173 |
174 | bool resetToBootloader();
175 |
176 | bool intelVersionInfo(IntelVersion *ver);
177 |
178 | bool intelBoot(uint32_t bootAddr);
179 |
180 | bool readDebugFeatures(IntelDebugFeatures *features);
181 |
182 | bool setDebugFeatures(IntelDebugFeatures *features);
183 |
184 | bool loadDDCConfig(const char *ddcFileName);
185 |
186 | OSData *firmwareConvertion(OSData *originalFirmware);
187 |
188 | OSData *requestFirmwareData(const char *fwName, bool noWarn = false);
189 |
190 | protected:
191 |
192 | bool intelSendHCISync(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, int timeout);
193 |
194 | bool intelSendHCISyncEvent(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, uint8_t syncEvent, int timeout);
195 |
196 | bool intelBulkHCISync(HciCommandHdr *cmd, void *event, uint32_t eventBufSize, uint32_t *size, int timeout);
197 |
198 | protected:
199 | USBDeviceController *m_pUSBDeviceController;
200 | };
201 |
202 | #endif /* BtIntel_h */
203 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/BtIntelFw.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // BtIntelFirmware.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/16.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "Log.h"
10 | #include "BtIntel.h"
11 | #include "FwData.h"
12 |
13 | OSData *BtIntel::
14 | firmwareConvertion(OSData *originalFirmware)
15 | {
16 | unsigned int numBytes = originalFirmware->getLength() * 4;
17 | unsigned int actualBytes = numBytes;
18 | OSData *fwData = NULL;
19 | unsigned char* _fwBytes = (unsigned char *)IOMalloc(numBytes);
20 | if (!uncompressFirmware(_fwBytes, &actualBytes, (unsigned char *)originalFirmware->getBytesNoCopy(), originalFirmware->getLength())) {
21 | IOFree(_fwBytes, numBytes);
22 | return NULL;
23 | }
24 | fwData = OSData::withBytes(_fwBytes, actualBytes);
25 | IOFree(_fwBytes, numBytes);
26 | return fwData;
27 | }
28 |
29 | OSData *BtIntel::
30 | requestFirmwareData(const char *fwName, bool noWarn)
31 | {
32 | OSData * _fwData = getFWDescByName(fwName);
33 | if (!_fwData) {
34 | if (!noWarn)
35 | XYLog("Firmware: %s Not found!\n", fwName);
36 | return NULL;
37 | }
38 | XYLog("Found device firmware %s \n", fwName);
39 | OSData *fwData = firmwareConvertion(_fwData);
40 | OSSafeReleaseNULL(_fwData);
41 | if (fwData == NULL) {
42 | XYLog("Firmware %s uncompress fail!\n", fwName);
43 | return NULL;
44 | }
45 | return fwData;
46 | }
47 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/BtIntelVSC.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // BtIntelVSC.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/16.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "Log.h"
10 | #include "BtIntel.h"
11 |
12 | bool BtIntel::
13 | enterMfg()
14 | {
15 | uint8_t buf[CMD_BUF_MAX_SIZE];
16 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
17 |
18 | memset(buf, 0, sizeof(buf));
19 | cmd->opcode = OSSwapHostToLittleInt16(0xfc11);
20 | cmd->len = 2;
21 | cmd->data[0] = 0x01;
22 | cmd->data[1] = 0x00;
23 |
24 | return intelSendHCISync(cmd, NULL, 0, NULL, HCI_CMD_TIMEOUT);
25 | }
26 |
27 | bool BtIntel::
28 | exitMfg(bool reset, bool patched)
29 | {
30 | uint8_t buf[CMD_BUF_MAX_SIZE];
31 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
32 |
33 | memset(buf, 0, sizeof(buf));
34 | cmd->opcode = OSSwapHostToLittleInt16(0xfc11);
35 | cmd->len = 2;
36 | cmd->data[0] = 0x00;
37 | cmd->data[1] = 0x00;
38 |
39 | /* The 2nd command parameter specifies the manufacturing exit method:
40 | * 0x00: Just disable the manufacturing mode (0x00).
41 | * 0x01: Disable manufacturing mode and reset with patches deactivated.
42 | * 0x02: Disable manufacturing mode and reset with patches activated.
43 | */
44 | if (reset)
45 | cmd->data[1] |= patched ? 0x02 : 0x01;
46 |
47 | return intelSendHCISync(cmd, NULL, 0, NULL, HCI_CMD_TIMEOUT);
48 | }
49 |
50 | bool BtIntel::
51 | setEventMask(bool debug)
52 | {
53 | uint8_t buf[CMD_BUF_MAX_SIZE];
54 | uint8_t mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
55 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
56 |
57 | if (debug)
58 | mask[1] |= 0x62;
59 | memset(buf, 0, sizeof(buf));
60 | cmd->opcode = OSSwapHostToLittleInt16(0xfc52);
61 | cmd->len = 8;
62 | memcpy(cmd->data, mask, 8);
63 |
64 | return intelSendHCISync(cmd, NULL, 0, NULL, HCI_INIT_TIMEOUT);
65 | }
66 |
67 | bool BtIntel::
68 | setEventMaskMfg(bool debug)
69 | {
70 | bool ret;
71 | if (!enterMfg()) {
72 | return false;
73 | }
74 |
75 | ret = setEventMask(debug);
76 |
77 | if (!exitMfg(false, false)) {
78 | return false;
79 | }
80 |
81 | return ret;
82 | }
83 |
84 | bool BtIntel::
85 | readVersion(IntelVersion *version)
86 | {
87 | uint32_t actLen = 0;
88 | HciCommandHdr cmd = {
89 | .opcode = OSSwapHostToLittleInt16(0xfc05),
90 | .len = 0,
91 | };
92 | uint8_t buf[CMD_BUF_MAX_SIZE];
93 | HciResponse *resp = (HciResponse *)buf;
94 |
95 | memset(buf, 0, sizeof(buf));
96 | if (!intelSendHCISync(&cmd, resp, sizeof(buf), &actLen, HCI_CMD_TIMEOUT)) {
97 | XYLog("Reading Intel version information failed\n");
98 | return false;
99 | }
100 |
101 | if (actLen - 5 != sizeof(*version)) {
102 | XYLog("Intel version event size mismatch (act: %d, ver: %d)\n", actLen, (int)sizeof(*version));
103 | return false;
104 | }
105 |
106 | memcpy(version, resp->data, actLen - 5);
107 |
108 | return true;
109 | }
110 |
111 | bool BtIntel::
112 | sendIntelReset(uint32_t bootParam)
113 | {
114 | uint8_t buf[CMD_BUF_MAX_SIZE];
115 | IntelReset params = {
116 | 0x00, 0x01, 0x00, 0x01, 0x00000000
117 | };
118 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
119 |
120 | params.boot_param = OSSwapHostToLittleInt32(bootParam);
121 |
122 | cmd->opcode = OSSwapHostToLittleInt16(0xfc01);
123 | cmd->len = sizeof(params);
124 | memcpy(cmd->data, ¶ms, sizeof(params));
125 | return m_pUSBDeviceController->sendHCIRequest(cmd, HCI_INIT_TIMEOUT) == kIOReturnSuccess;
126 | }
127 |
128 | bool BtIntel::
129 | readBootParams(IntelBootParams *params)
130 | {
131 | uint32_t actLen = 0;
132 | HciCommandHdr cmd = {
133 | .opcode = OSSwapHostToLittleInt16(0xfc0d),
134 | .len = 0,
135 | };
136 | uint8_t buf[CMD_BUF_MAX_SIZE];
137 | HciResponse *resp = (HciResponse *)buf;
138 |
139 | memset(buf, 0, sizeof(buf));
140 | if (!intelSendHCISync(&cmd, resp, sizeof(buf), &actLen, HCI_INIT_TIMEOUT)) {
141 | XYLog("Reading Intel boot parameters failed\n");
142 | return false;
143 | }
144 |
145 | if (actLen - 5 != sizeof(*params)) {
146 | XYLog("Intel boot parameters size mismatch\n");
147 | return false;
148 | }
149 |
150 | memcpy(params, resp->data, actLen - 5);
151 |
152 | if (params->status) {
153 | XYLog("Intel boot parameters command failed (%02x)\n", params->status);
154 | return false;
155 | }
156 |
157 | XYLog("Device revision is %u\n",
158 | OSSwapLittleToHostInt16(params->dev_revid));
159 |
160 | XYLog("Secure boot is %s\n",
161 | params->secure_boot ? "enabled" : "disabled");
162 |
163 | XYLog("OTP lock is %s\n",
164 | params->otp_lock ? "enabled" : "disabled");
165 |
166 | XYLog("API lock is %s\n",
167 | params->api_lock ? "enabled" : "disabled");
168 |
169 | XYLog("Debug lock is %s\n",
170 | params->debug_lock ? "enabled" : "disabled");
171 |
172 | XYLog("Minimum firmware build %u week %u %u\n",
173 | params->min_fw_build_nn, params->min_fw_build_cw,
174 | 2000 + params->min_fw_build_yy);
175 |
176 | return true;
177 | }
178 |
179 | bool BtIntel::
180 | resetToBootloader()
181 | {
182 | XYLog("%s\n", __FUNCTION__);
183 | bool ret;
184 | uint8_t buf[CMD_BUF_MAX_SIZE];
185 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
186 | IntelReset params;
187 |
188 | /* Send Intel Reset command. This will result in
189 | * re-enumeration of BT controller.
190 | *
191 | * Intel Reset parameter description:
192 | * reset_type : 0x00 (Soft reset),
193 | * 0x01 (Hard reset)
194 | * patch_enable : 0x00 (Do not enable),
195 | * 0x01 (Enable)
196 | * ddc_reload : 0x00 (Do not reload),
197 | * 0x01 (Reload)
198 | * boot_option: 0x00 (Current image),
199 | * 0x01 (Specified boot address)
200 | * boot_param: Boot address
201 | *
202 | */
203 | params.reset_type = 0x01;
204 | params.patch_enable = 0x01;
205 | params.ddc_reload = 0x01;
206 | params.boot_option = 0x00;
207 | params.boot_param = OSSwapHostToLittleInt32(0x00000000);
208 |
209 | cmd->opcode = OSSwapHostToLittleInt16(0xfc01);
210 | cmd->len = sizeof(params);
211 | memcpy(cmd->data, ¶ms, sizeof(params));
212 |
213 | ret = m_pUSBDeviceController->sendHCIRequest(cmd, HCI_INIT_TIMEOUT);
214 |
215 | /* Current Intel BT controllers(ThP/JfP) hold the USB reset
216 | * lines for 2ms when it receives Intel Reset in bootloader mode.
217 | * Whereas, the upcoming Intel BT controllers will hold USB reset
218 | * for 150ms. To keep the delay generic, 150ms is chosen here.
219 | */
220 | IOSleep(150);
221 |
222 | return ret;
223 | }
224 |
225 | bool BtIntel::
226 | readDebugFeatures(IntelDebugFeatures *features)
227 | {
228 | uint8_t buf[CMD_BUF_MAX_SIZE], temp[CMD_BUF_MAX_SIZE];
229 | uint actLen = 0;
230 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
231 | HciResponse *resp = (HciResponse *)temp;
232 | uint8_t page_no = 1;
233 |
234 | memset(buf, 0, sizeof(buf));
235 | cmd->opcode = OSSwapHostToLittleInt16(0xfca6);
236 | cmd->len = sizeof(page_no);
237 | cmd->data[0] = page_no;
238 |
239 | if (!intelSendHCISync(cmd, resp, sizeof(temp), &actLen, HCI_INIT_TIMEOUT)) {
240 | XYLog("Reading supported features failed\n");
241 | return false;
242 | }
243 |
244 | if (actLen - 5 != sizeof(features->page1) + 3) {
245 | XYLog("Supported features event size mismatch\n");
246 | return false;
247 | }
248 |
249 | memcpy(features->page1, resp->data + 3, sizeof(features->page1));
250 | XYLog("Read debug features done\n");
251 |
252 | return true;
253 | }
254 |
255 | bool BtIntel::
256 | setDebugFeatures(IntelDebugFeatures *features)
257 | {
258 | uint8_t buf[CMD_BUF_MAX_SIZE];
259 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
260 | uint8_t mask[11] = { 0x0a, 0x92, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00,
261 | 0x00, 0x00, 0x00 };
262 |
263 | if (!features) {
264 | XYLog("No debug features!\n");
265 | return false;
266 | }
267 |
268 | if (!(features->page1[0] & 0x3f)) {
269 | XYLog("Telemetry exception format not supported\n");
270 | return false;
271 | }
272 |
273 | memset(buf, 0, sizeof(buf));
274 | cmd->opcode = OSSwapHostToLittleInt16(0xfc8b);
275 | cmd->len = 11;
276 | memcpy(cmd->data, mask, 11);
277 |
278 | if (!intelSendHCISync(cmd, NULL, 0, NULL, HCI_INIT_TIMEOUT)) {
279 | XYLog("Setting Intel telemetry ddc write event mask failed\n");
280 | return false;
281 | }
282 |
283 | XYLog("Set debug features done\n");
284 |
285 | return true;
286 | }
287 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/FwData.h:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // FwData.h
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/12/22.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #ifndef FwData_h
15 | #define FwData_h
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | struct FwDesc {
22 | const char *name;
23 | const unsigned char *var;
24 | const long int size;
25 | };
26 |
27 | #define IBT_FW(fw_name, fw_var, fw_size) \
28 | .name = fw_name, .var = fw_var, .size = fw_size
29 |
30 |
31 | extern const struct FwDesc fwList[];
32 | extern const int fwNumber;
33 |
34 | static inline OSData *getFWDescByName(const char* name) {
35 | for (int i = 0; i < fwNumber; i++) {
36 | if (strcmp(fwList[i].name, name) == 0) {
37 | FwDesc desc = fwList[i];
38 | return OSData::withBytes(desc.var, (unsigned int)desc.size);
39 | }
40 | }
41 | return NULL;
42 | }
43 |
44 | static inline bool uncompressFirmware(unsigned char *dest, uint *destLen, unsigned char *source, uint sourceLen)
45 | {
46 | z_stream stream;
47 | int err;
48 |
49 | stream.next_in = source;
50 | stream.avail_in = sourceLen;
51 | stream.next_out = dest;
52 | stream.avail_out = *destLen;
53 | stream.zalloc = zcalloc;
54 | stream.zfree = zcfree;
55 | err = inflateInit(&stream);
56 | if (err != Z_OK) {
57 | return false;
58 | }
59 | err = inflate(&stream, Z_FINISH);
60 | if (err != Z_STREAM_END) {
61 | inflateEnd(&stream);
62 | return false;
63 | }
64 | *destLen = (uint)stream.total_out;
65 |
66 | err = inflateEnd(&stream);
67 | return err == Z_OK;
68 | }
69 |
70 | #endif /* FwData_h */
71 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/Hci.h:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // Hci.h
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/11/17.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #ifndef Hci_h
15 | #define Hci_h
16 |
17 | typedef struct __attribute__((packed))
18 | {
19 | uint16_t opcode; /* OCF & OGF */
20 | uint8_t len;
21 | uint8_t data[];
22 | } HciCommandHdr;
23 |
24 | typedef struct __attribute__((packed))
25 | {
26 | uint8_t evt;
27 | uint8_t len;
28 | } HciEventHdr;
29 |
30 | typedef struct __attribute__((packed))
31 | {
32 | HciEventHdr evt;
33 | uint8_t numCommands;
34 | uint16_t opcode;
35 | uint8_t data[];
36 | } HciResponse;
37 |
38 | typedef struct __attribute__((packed))
39 | {
40 | uint8_t status;
41 | uint8_t numCommands;
42 | uint16_t opcode;
43 | } HciCmdStatus;
44 |
45 | /* ---- HCI Events ---- */
46 | #define HCI_EV_INQUIRY_COMPLETE 0x01
47 | #define HCI_EV_INQUIRY_RESULT 0x02
48 | #define HCI_EV_CONN_COMPLETE 0x03
49 | #define HCI_EV_CONN_REQUEST 0x04
50 | #define HCI_EV_DISCONN_COMPLETE 0x05
51 | #define HCI_EV_AUTH_COMPLETE 0x06
52 | #define HCI_EV_REMOTE_NAME 0x07
53 | #define HCI_EV_ENCRYPT_CHANGE 0x08
54 | #define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09
55 | #define HCI_EV_REMOTE_FEATURES 0x0b
56 | #define HCI_EV_REMOTE_VERSION 0x0c
57 | #define HCI_EV_QOS_SETUP_COMPLETE 0x0d
58 | #define HCI_EV_CMD_COMPLETE 0x0e
59 | #define HCI_EV_CMD_STATUS 0x0f
60 | #define HCI_EV_HARDWARE_ERROR 0x10
61 | #define HCI_EV_ROLE_CHANGE 0x12
62 | #define HCI_EV_NUM_COMP_PKTS 0x13
63 | #define HCI_EV_MODE_CHANGE 0x14
64 | #define HCI_EV_PIN_CODE_REQ 0x16
65 | #define HCI_EV_LINK_KEY_REQ 0x17
66 | #define HCI_EV_LINK_KEY_NOTIFY 0x18
67 | #define HCI_EV_CLOCK_OFFSET 0x1c
68 | #define HCI_EV_PKT_TYPE_CHANGE 0x1d
69 | #define HCI_EV_PSCAN_REP_MODE 0x20
70 | #define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
71 | #define HCI_EV_REMOTE_EXT_FEATURES 0x23
72 | #define HCI_EV_SYNC_CONN_COMPLETE 0x2c
73 | #define HCI_EV_SYNC_CONN_CHANGED 0x2d
74 | #define HCI_EV_SNIFF_SUBRATE 0x2e
75 | #define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
76 | #define HCI_EV_KEY_REFRESH_COMPLETE 0x30
77 | #define HCI_EV_IO_CAPA_REQUEST 0x31
78 | #define HCI_EV_IO_CAPA_REPLY 0x32
79 | #define HCI_EV_USER_CONFIRM_REQUEST 0x33
80 | #define HCI_EV_USER_PASSKEY_REQUEST 0x34
81 | #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
82 | #define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
83 | #define HCI_EV_USER_PASSKEY_NOTIFY 0x3b
84 | #define HCI_EV_KEYPRESS_NOTIFY 0x3c
85 | #define HCI_EV_REMOTE_HOST_FEATURES 0x3d
86 | #define HCI_EV_LE_META 0x3e
87 | #define HCI_EV_PHY_LINK_COMPLETE 0x40
88 | #define HCI_EV_CHANNEL_SELECTED 0x41
89 | #define HCI_EV_DISCONN_PHY_LINK_COMPLETE 0x42
90 | #define HCI_EV_LOGICAL_LINK_COMPLETE 0x45
91 | #define HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE 0x46
92 | #define HCI_EV_NUM_COMP_BLOCKS 0x48
93 | #define HCI_EV_SYNC_TRAIN_COMPLETE 0x4F
94 | #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54
95 |
96 | /* HCI timeouts */
97 | #define HCI_DISCONN_TIMEOUT 2000 /* 2 seconds */
98 | #define HCI_PAIRING_TIMEOUT 60000 /* 60 seconds */
99 | #define HCI_INIT_TIMEOUT 10000 /* 10 seconds */
100 | #define HCI_CMD_TIMEOUT 2000 /* 2 seconds */
101 | #define HCI_ACL_TX_TIMEOUT 45000 /* 45 seconds */
102 | #define HCI_AUTO_OFF_TIMEOUT 2000 /* 2 seconds */
103 | #define HCI_POWER_OFF_TIMEOUT 5000 /* 5 seconds */
104 | #define HCI_LE_CONN_TIMEOUT 20000 /* 20 seconds */
105 | #define HCI_LE_AUTOCONN_TIMEOUT 4000 /* 4 seconds */
106 |
107 | /* HCI data types */
108 | #define HCI_COMMAND_PKT 0x01
109 | #define HCI_ACLDATA_PKT 0x02
110 | #define HCI_SCODATA_PKT 0x03
111 | #define HCI_EVENT_PKT 0x04
112 | #define HCI_DIAG_PKT 0xf0
113 | #define HCI_VENDOR_PKT 0xff
114 |
115 | /* ----- HCI Commands ---- */
116 | #define HCI_OP_NOP 0x0000
117 | #define HCI_OP_INQUIRY 0x0401
118 | #define HCI_OP_INQUIRY_CANCEL 0x0402
119 | #define HCI_OP_PERIODIC_INQ 0x0403
120 | #define HCI_OP_EXIT_PERIODIC_INQ 0x0404
121 | #define HCI_OP_CREATE_CONN 0x0405
122 | #define HCI_OP_DISCONNECT 0x0406
123 | #define HCI_OP_ADD_SCO 0x0407
124 | #define HCI_OP_CREATE_CONN_CANCEL 0x0408
125 | #define HCI_OP_ACCEPT_CONN_REQ 0x0409
126 | #define HCI_OP_REJECT_CONN_REQ 0x040a
127 | #define HCI_OP_LINK_KEY_REPLY 0x040b
128 | #define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
129 | #define HCI_OP_PIN_CODE_REPLY 0x040d
130 | #define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
131 | #define HCI_OP_CHANGE_CONN_PTYPE 0x040f
132 | #define HCI_OP_AUTH_REQUESTED 0x0411
133 | #define HCI_OP_SET_CONN_ENCRYPT 0x0413
134 | #define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415
135 | #define HCI_OP_REMOTE_NAME_REQ 0x0419
136 | #define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a
137 | #define HCI_OP_READ_REMOTE_FEATURES 0x041b
138 | #define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c
139 | #define HCI_OP_READ_REMOTE_VERSION 0x041d
140 | #define HCI_OP_READ_CLOCK_OFFSET 0x041f
141 | #define HCI_OP_SETUP_SYNC_CONN 0x0428
142 | #define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429
143 | #define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a
144 | #define HCI_OP_IO_CAPABILITY_REPLY 0x042b
145 | #define HCI_OP_USER_CONFIRM_REPLY 0x042c
146 | #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
147 | #define HCI_OP_USER_PASSKEY_REPLY 0x042e
148 | #define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
149 | #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
150 | #define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433
151 | #define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434
152 | #define HCI_OP_CREATE_PHY_LINK 0x0435
153 | #define HCI_OP_ACCEPT_PHY_LINK 0x0436
154 | #define HCI_OP_DISCONN_PHY_LINK 0x0437
155 | #define HCI_OP_CREATE_LOGICAL_LINK 0x0438
156 | #define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
157 | #define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
158 | #define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
159 | #define HCI_OP_SET_CSB 0x0441
160 | #define HCI_OP_START_SYNC_TRAIN 0x0443
161 | #define HCI_OP_REMOTE_OOB_EXT_DATA_REPLY 0x0445
162 | #define HCI_OP_SNIFF_MODE 0x0803
163 | #define HCI_OP_EXIT_SNIFF_MODE 0x0804
164 | #define HCI_OP_ROLE_DISCOVERY 0x0809
165 | #define HCI_OP_SWITCH_ROLE 0x080b
166 | #define HCI_OP_READ_LINK_POLICY 0x080c
167 | #define HCI_OP_WRITE_LINK_POLICY 0x080d
168 | #define HCI_OP_READ_DEF_LINK_POLICY 0x080e
169 | #define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
170 | #define HCI_OP_SNIFF_SUBRATE 0x0811
171 | #define HCI_OP_SET_EVENT_MASK 0x0c01
172 | #define HCI_OP_RESET 0x0c03
173 | #define HCI_OP_SET_EVENT_FLT 0x0c05
174 |
175 | /* Command opcode pack/unpack */
176 | #define hci_opcode_pack(ogf, ocf) ((__u16) ((ocf & 0x03ff)|(ogf << 10)))
177 | #define hci_opcode_ogf(op) (op >> 10)
178 | #define hci_opcode_ocf(op) (op & 0x03ff)
179 |
180 | /* ---- HCI Packet structures ---- */
181 | #define HCI_COMMAND_HDR_SIZE 3
182 | #define HCI_EVENT_HDR_SIZE 2
183 | #define HCI_ACL_HDR_SIZE 4
184 | #define HCI_SCO_HDR_SIZE 3
185 |
186 | #endif /* Hci_h */
187 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleShortVersionString
18 | $(MODULE_VERSION)
19 | CFBundleVersion
20 | $(MODULE_VERSION)
21 | IOKitPersonalities
22 |
23 | IntelBluetoothFirmware_0026
24 |
25 | CFBundleIdentifier
26 | com.zxystd.IntelBluetoothFirmware
27 | IOClass
28 | IntelBluetoothFirmware
29 | IOMatchCategory
30 | IntelBluetoothFirmware
31 | IOProbeScore
32 | 4000
33 | IOProviderClass
34 | IOUSBHostDevice
35 | idProduct
36 | 38
37 | idVendor
38 | 32903
39 |
40 | IntelBluetoothFirmware_0032
41 |
42 | CFBundleIdentifier
43 | com.zxystd.IntelBluetoothFirmware
44 | IOClass
45 | IntelBluetoothFirmware
46 | IOMatchCategory
47 | IntelBluetoothFirmware
48 | IOProbeScore
49 | 4000
50 | IOProviderClass
51 | IOUSBHostDevice
52 | idProduct
53 | 50
54 | idVendor
55 | 32903
56 |
57 | IntelBluetoothFirmware_0035
58 |
59 | CFBundleIdentifier
60 | com.zxystd.IntelBluetoothFirmware
61 | IOClass
62 | IntelBluetoothFirmware
63 | IOMatchCategory
64 | IntelBluetoothFirmware
65 | IOProbeScore
66 | 4000
67 | IOProviderClass
68 | IOUSBHostDevice
69 | idProduct
70 | 53
71 | idVendor
72 | 32903
73 |
74 | IntelBluetoothFirmware_0036
75 |
76 | CFBundleIdentifier
77 | com.zxystd.IntelBluetoothFirmware
78 | IOClass
79 | IntelBluetoothFirmware
80 | IOMatchCategory
81 | IntelBluetoothFirmware
82 | IOProbeScore
83 | 4000
84 | IOProviderClass
85 | IOUSBHostDevice
86 | idProduct
87 | 54
88 | idVendor
89 | 32903
90 |
91 | IntelBluetoothFirmware_0038
92 |
93 | CFBundleIdentifier
94 | com.zxystd.IntelBluetoothFirmware
95 | IOClass
96 | IntelBluetoothFirmware
97 | IOMatchCategory
98 | IntelBluetoothFirmware
99 | IOProbeScore
100 | 4000
101 | IOProviderClass
102 | IOUSBHostDevice
103 | idProduct
104 | 56
105 | idVendor
106 | 32903
107 |
108 | IntelBluetoothFirmware_3165
109 |
110 | CFBundleIdentifier
111 | com.zxystd.IntelBluetoothFirmware
112 | IOClass
113 | IntelBluetoothFirmware
114 | IOMatchCategory
115 | IntelBluetoothFirmware
116 | IOProbeScore
117 | 4000
118 | IOProviderClass
119 | IOUSBHostDevice
120 | idProduct
121 | 2602
122 | idVendor
123 | 32903
124 |
125 | IntelBluetoothFirmware_3168
126 |
127 | CFBundleIdentifier
128 | com.zxystd.IntelBluetoothFirmware
129 | IOClass
130 | IntelBluetoothFirmware
131 | IOMatchCategory
132 | IntelBluetoothFirmware
133 | IOProbeScore
134 | 4000
135 | IOProviderClass
136 | IOUSBHostDevice
137 | idProduct
138 | 2727
139 | idVendor
140 | 32903
141 |
142 | IntelBluetoothFirmware_726x
143 |
144 | CFBundleIdentifier
145 | com.zxystd.IntelBluetoothFirmware
146 | IOClass
147 | IntelBluetoothFirmware
148 | IOMatchCategory
149 | IntelBluetoothFirmware
150 | IOProbeScore
151 | 4000
152 | IOProviderClass
153 | IOUSBHostDevice
154 | idProduct
155 | 2012
156 | idVendor
157 | 32903
158 |
159 | IntelBluetoothFirmware_8265
160 |
161 | CFBundleIdentifier
162 | com.zxystd.IntelBluetoothFirmware
163 | IOClass
164 | IntelBluetoothFirmware
165 | IOMatchCategory
166 | IntelBluetoothFirmware
167 | IOProbeScore
168 | 4000
169 | IOProviderClass
170 | IOUSBHostDevice
171 | idProduct
172 | 2603
173 | idVendor
174 | 32903
175 |
176 | IntelBluetoothFirmware_926x
177 |
178 | CFBundleIdentifier
179 | com.zxystd.IntelBluetoothFirmware
180 | IOClass
181 | IntelBluetoothFirmware
182 | IOMatchCategory
183 | IntelBluetoothFirmware
184 | IOProbeScore
185 | 4000
186 | IOProviderClass
187 | IOUSBHostDevice
188 | idProduct
189 | 37
190 | idVendor
191 | 32903
192 |
193 | IntelBluetoothFirmware_9560
194 |
195 | CFBundleIdentifier
196 | com.zxystd.IntelBluetoothFirmware
197 | IOClass
198 | IntelBluetoothFirmware
199 | IOMatchCategory
200 | IntelBluetoothFirmware
201 | IOProbeScore
202 | 4000
203 | IOProviderClass
204 | IOUSBHostDevice
205 | idProduct
206 | 2730
207 | idVendor
208 | 32903
209 |
210 | IntelBluetoothFirmware_ax200
211 |
212 | CFBundleIdentifier
213 | com.zxystd.IntelBluetoothFirmware
214 | IOClass
215 | IntelBluetoothFirmware
216 | IOMatchCategory
217 | IntelBluetoothFirmware
218 | IOProbeScore
219 | 4000
220 | IOProviderClass
221 | IOUSBHostDevice
222 | idProduct
223 | 41
224 | idVendor
225 | 32903
226 |
227 | IntelBluetoothFirmware_ax210
228 |
229 | CFBundleIdentifier
230 | com.zxystd.IntelBluetoothFirmware
231 | IOClass
232 | IntelBluetoothFirmware
233 | IOMatchCategory
234 | IntelBluetoothFirmware
235 | IOProbeScore
236 | 4000
237 | IOProviderClass
238 | IOUSBHostDevice
239 | idProduct
240 | 51
241 | idVendor
242 | 32903
243 |
244 |
245 | NSHumanReadableCopyright
246 | Copyright © 2019 钟先耀. All rights reserved.
247 | OSBundleLibraries
248 |
249 | com.apple.iokit.IOUSBHostFamily
250 | 1.2
251 | com.apple.kpi.iokit
252 | 16.7
253 | com.apple.kpi.libkern
254 | 16.7
255 | com.apple.kpi.mach
256 | 16.7
257 |
258 |
259 |
260 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothFirmware.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothFirmware.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by zxystd on 2019/11/17.
6 | // Copyright © 2019 zxystd. All rights reserved.
7 | //
8 |
9 | #include "BtIntel.h"
10 |
11 | #include "IntelBluetoothFirmware.hpp"
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include "Hci.h"
18 | #include "linux.h"
19 | #include "Log.h"
20 |
21 | #include "IntelBluetoothOpsGen1.hpp"
22 | #include "IntelBluetoothOpsGen2.hpp"
23 | #include "IntelBluetoothOpsGen3.hpp"
24 |
25 | #define super IOService
26 | OSDefineMetaClassAndStructors(IntelBluetoothFirmware, IOService)
27 |
28 | //com.apple.iokit.IOBluetoothHostControllerUSBTransport
29 |
30 | enum { kMyOffPowerState = 0, kMyOnPowerState = 1 };
31 |
32 | #define kIOPMPowerOff 0
33 |
34 | static IOPMPowerState myTwoStates[2] =
35 | {
36 | {1, kIOPMPowerOff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
37 | {1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
38 | };
39 |
40 | bool IntelBluetoothFirmware::init(OSDictionary *dictionary)
41 | {
42 | XYLog("Driver init()\n");
43 | return super::init(dictionary);
44 | }
45 |
46 | void IntelBluetoothFirmware::free() {
47 | XYLog("Driver free()\n");
48 | super::free();
49 | }
50 |
51 | bool IntelBluetoothFirmware::start(IOService *provider)
52 | {
53 | XYLog("Driver Start()\n");
54 | char fwName[64];
55 | m_pDevice = OSDynamicCast(IOUSBHostDevice, provider);
56 | if (m_pDevice == NULL) {
57 | XYLog("Driver Start fail, not usb device\n");
58 | return false;
59 | }
60 | PMinit();
61 | registerPowerDriver(this, myTwoStates, 2);
62 | provider->joinPMtree(this);
63 | makeUsable();
64 |
65 | if (!super::start(provider)) {
66 | return false;
67 | }
68 |
69 | if (!m_pDevice->open(this)) {
70 | XYLog("start fail, can not open device\n");
71 | cleanUp();
72 | stop(this);
73 | return false;
74 | }
75 | if (currentType == kTypeGen1) {
76 | m_pBTIntel = new IntelBluetoothOpsGen1();
77 | } else {
78 | m_pBTIntel = new IntelBluetoothOpsGen3();
79 | }
80 | if (!m_pBTIntel->initWithDevice(this, m_pDevice)) {
81 | XYLog("start fail, can not init device\n");
82 | cleanUp();
83 | stop(this);
84 | return false;
85 | }
86 | XYLog("BT init succeed\n");
87 | if (!m_pBTIntel->setup()) {
88 | cleanUp();
89 | stop(this);
90 | return false;
91 | }
92 | m_pBTIntel->getFirmwareName(fwName, sizeof(fwName));
93 | publishReg(true, fwName);
94 | cleanUp();
95 | return true;
96 | }
97 |
98 | void IntelBluetoothFirmware::publishReg(bool isSucceed, const char *fwName)
99 | {
100 | m_pDevice->setProperty("FirmwareLoaded", isSucceed);
101 | if (isSucceed)
102 | setProperty("fw_name", OSString::withCString(fwName));
103 | // Monterey+
104 | if (version_major >= 21)
105 | m_pDevice->setName("Bluetooth USB Host Controller");
106 | }
107 |
108 | void IntelBluetoothFirmware::cleanUp()
109 | {
110 | XYLog("Clean up...\n");
111 | OSSafeReleaseNULL(m_pBTIntel);
112 | if (m_pDevice) {
113 | if (m_pDevice->isOpen(this)) {
114 | m_pDevice->close(this);
115 | }
116 | m_pDevice = NULL;
117 | }
118 | }
119 |
120 | IOReturn IntelBluetoothFirmware::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice)
121 | {
122 | // XYLog("setPowerState powerStateOrdinal=%lu\n", powerStateOrdinal);
123 | return IOPMAckImplied;
124 | }
125 |
126 | void IntelBluetoothFirmware::stop(IOService *provider)
127 | {
128 | XYLog("Driver Stop()\n");
129 | PMstop();
130 | super::stop(provider);
131 | }
132 |
133 | IOService * IntelBluetoothFirmware::probe(IOService *provider, SInt32 *score)
134 | {
135 | XYLog("Driver Probe()\n");
136 | if (!super::probe(provider, score)) {
137 | XYLog("super probe failed\n");
138 | return NULL;
139 | }
140 | m_pDevice = OSDynamicCast(IOUSBHostDevice, provider);
141 | if (!m_pDevice) {
142 | XYLog("is not usb device\n");
143 | return NULL;
144 | }
145 | UInt16 vendorID = USBToHost16(m_pDevice->getDeviceDescriptor()->idVendor);
146 | UInt16 productID = USBToHost16(m_pDevice->getDeviceDescriptor()->idProduct);
147 | XYLog("name=%s, class=%s, vendorID=0x%04X, productID=0x%04X\n", m_pDevice->getName(), provider->metaClass->getClassName(), vendorID, productID);
148 | if (productID == 0x07dc || productID == 0x0a2a || productID == 0x0aa7) {
149 | currentType = kTypeGen1;
150 | } else if (productID == 0x0032 || productID == 0x0033 || productID == 0x0035
151 | || productID == 0x0036 || productID == 0x0038) {
152 | currentType = kTypeGen3;
153 | } else {
154 | currentType = kTypeGen2;
155 | }
156 | m_pDevice = NULL;
157 | return this;
158 | }
159 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothFirmware.hpp:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // IntelBluetoothFirmware.hpp
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/11/17.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #ifndef IntelBluetoothFirmware_H
15 | #define IntelBluetoothFirmware_H
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "BtIntel.h"
26 |
27 | enum BTType {
28 | kTypeGen1,
29 | kTypeGen2,
30 | kTypeGen3,
31 | } ;
32 |
33 | class IntelBluetoothFirmware : public IOService
34 | {
35 | OSDeclareDefaultStructors (IntelBluetoothFirmware)
36 |
37 | public:
38 |
39 | bool init(OSDictionary *dictionary = NULL) override;
40 |
41 | void free() override;
42 |
43 | bool start(IOService *provider) override;
44 |
45 | void stop(IOService *provider) override;
46 |
47 | IOService * probe(IOService *provider, SInt32 *score) override;
48 |
49 | IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) override;
50 |
51 | void cleanUp();
52 |
53 | void publishReg(bool isSucceed, const char *fwName);
54 |
55 | private:
56 | BTType currentType;
57 | BtIntel *m_pBTIntel;
58 | IOUSBHostDevice* m_pDevice;
59 | };
60 |
61 | #endif
62 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen1.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothGen1.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "IntelBluetoothOpsGen1.hpp"
10 | #include "Log.h"
11 | #include "Hci.h"
12 |
13 | OSDefineMetaClassAndStructors(IntelBluetoothOpsGen1, BtIntel)
14 |
15 | bool IntelBluetoothOpsGen1::
16 | setup()
17 | {
18 | const uint8_t *fw_ptr;
19 | bool disablePatch;
20 | IntelVersion ver;
21 | OSData *fwData = NULL;
22 | char fwname[64];
23 |
24 | /* The controller has a bug with the first HCI command sent to it
25 | * returning number of completed commands as zero. This would stall the
26 | * command processing in the Bluetooth core.
27 | *
28 | * As a workaround, send HCI Reset command first which will reset the
29 | * number of completed commands and allow normal command processing
30 | * from now on.
31 | */
32 | if (!hciReset()) {
33 | XYLog("sending initial HCI reset command failed\n");
34 | return false;
35 | }
36 |
37 | /* Read Intel specific controller version first to allow selection of
38 | * which firmware file to load.
39 | *
40 | * The returned information are hardware variant and revision plus
41 | * firmware variant, revision and build number.
42 | */
43 | if (!readVersion(&ver)) {
44 | XYLog("Read version failed: %d\n", __LINE__);
45 | return false;
46 | }
47 |
48 | XYLog("read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
49 | ver.hw_platform, ver.hw_variant, ver.hw_revision,
50 | ver.fw_variant, ver.fw_revision, ver.fw_build_num,
51 | ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);
52 |
53 | /* Opens the firmware patch file based on the firmware version read
54 | * from the controller. If it fails to open the matching firmware
55 | * patch file, it tries to open the default firmware patch file.
56 | * If no patch file is found, allow the device to operate without
57 | * a patch.
58 | */
59 | fwData = getFirmware(&ver, fwname, sizeof(fwname));
60 |
61 | strncpy(this->loadedFirmwareName, fwname, sizeof(this->loadedFirmwareName));
62 |
63 | /* fw_patch_num indicates the version of patch the device currently
64 | * have. If there is no patch data in the device, it is always 0x00.
65 | * So, if it is other than 0x00, no need to patch the device again.
66 | */
67 | if (ver.fw_patch_num) {
68 | XYLog("Intel device is already patched. patch num: %02x\n", ver.fw_patch_num);
69 | goto complete;
70 | }
71 |
72 | if (!fwData) {
73 | goto complete;
74 | }
75 |
76 | fw_ptr = (uint8_t *)fwData->getBytesNoCopy();
77 |
78 | /* Enable the manufacturer mode of the controller.
79 | * Only while this mode is enabled, the driver can download the
80 | * firmware patch data and configuration parameters.
81 | */
82 | if (!enterMfg()) {
83 | XYLog("Enter mfg failed: %d\n", __LINE__);
84 | OSSafeReleaseNULL(fwData);
85 | return false;
86 | }
87 |
88 | disablePatch = true;
89 |
90 | /* The firmware data file consists of list of Intel specific HCI
91 | * commands and its expected events. The first byte indicates the
92 | * type of the message, either HCI command or HCI event.
93 | *
94 | * It reads the command and its expected event from the firmware file,
95 | * and send to the controller. Once __hci_cmd_sync_ev() returns,
96 | * the returned event is compared with the event read from the firmware
97 | * file and it will continue until all the messages are downloaded to
98 | * the controller.
99 | *
100 | * Once the firmware patching is completed successfully,
101 | * the manufacturer mode is disabled with reset and activating the
102 | * downloaded patch.
103 | *
104 | * If the firmware patching fails, the manufacturer mode is
105 | * disabled with reset and deactivating the patch.
106 | *
107 | * If the default patch file is used, no reset is done when disabling
108 | * the manufacturer.
109 | */
110 | while (fwData->getLength() > fw_ptr - (uint8_t *)fwData->getBytesNoCopy()) {
111 | if (!patching(fwData, &fw_ptr, &disablePatch))
112 | goto exit_mfg_deactivate;
113 | }
114 |
115 | XYLog("Patch file download done\n");
116 |
117 | OSSafeReleaseNULL(fwData);
118 |
119 | if (disablePatch)
120 | goto exit_mfg_disable;
121 |
122 | /* Patching completed successfully and disable the manufacturer mode
123 | * with reset and activate the downloaded firmware patches.
124 | */
125 | if (!exitMfg(true, true)) {
126 | XYLog("Exit mfg failed: %d\n", __LINE__);
127 | return false;
128 | }
129 |
130 | /* Need build number for downloaded fw patches in
131 | * every power-on boot
132 | */
133 | if (!readVersion(&ver)) {
134 | XYLog("Read version failed: %d\n", __LINE__);
135 | return false;
136 | }
137 |
138 | XYLog("Intel BT fw patch 0x%02x completed & activated\n",
139 | ver.fw_patch_num);
140 |
141 | goto complete;
142 |
143 | exit_mfg_disable:
144 | /* Disable the manufacturer mode without reset */
145 | if (!exitMfg(false, false)) {
146 | XYLog("Exit mfg failed: %d\n", __LINE__);
147 | return false;
148 | }
149 |
150 | XYLog("Intel firmware patch completed\n");
151 | goto complete;
152 |
153 | exit_mfg_deactivate:
154 | /* Patching failed. Disable the manufacturer mode with reset and
155 | * deactivate the downloaded firmware patches.
156 | */
157 | if (!exitMfg(true, false)) {
158 | XYLog("Exit mfg failed %d\n", __LINE__);
159 | return false;
160 | }
161 | XYLog("Intel firmware patch completed and deactivated\n");
162 |
163 | complete:
164 | OSSafeReleaseNULL(fwData);
165 | /* Set the event mask for Intel specific vendor events. This enables
166 | * a few extra events that are useful during general operation.
167 | */
168 | setEventMaskMfg(false);
169 |
170 | return true;
171 | }
172 |
173 | bool IntelBluetoothOpsGen1::
174 | shutdown()
175 | {
176 | return true;
177 | }
178 |
179 | bool IntelBluetoothOpsGen1::
180 | getFirmwareName(char *fwname, size_t len)
181 | {
182 | strncpy(fwname, this->loadedFirmwareName, len - 1);
183 | fwname[len - 1] = '\0';
184 | return true;
185 | }
186 |
187 | bool IntelBluetoothOpsGen1::
188 | hciReset()
189 | {
190 | HciCommandHdr cmd = {
191 | .opcode = OSSwapHostToLittleInt16(HCI_OP_RESET),
192 | .len = 0,
193 | };
194 |
195 | return intelSendHCISync(&cmd, NULL, 0, NULL, HCI_INIT_TIMEOUT);
196 | }
197 |
198 | OSData *IntelBluetoothOpsGen1::
199 | getFirmware(IntelVersion *ver, char *fwname, size_t len)
200 | {
201 | OSData *fwData;
202 |
203 | snprintf(fwname, len,
204 | "ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq",
205 | ver->hw_platform, ver->hw_variant, ver->hw_revision,
206 | ver->fw_variant, ver->fw_revision, ver->fw_build_num,
207 | ver->fw_build_ww, ver->fw_build_yy);
208 | fwData = requestFirmwareData(fwname);
209 | if (!fwData) {
210 | XYLog("failed to open Intel firmware file: %s\n", fwname);
211 | /* If the correct firmware patch file is not found, use the
212 | * default firmware patch file instead
213 | */
214 | snprintf(fwname, len, "ibt-hw-%x.%x.bseq",
215 | ver->hw_platform, ver->hw_variant);
216 | fwData = requestFirmwareData(fwname);
217 | }
218 | XYLog("Intel Bluetooth firmware file: %s\n", fwname);
219 | return fwData;
220 | }
221 |
222 | bool IntelBluetoothOpsGen1::
223 | patching(OSData *fwData, const uint8_t **fw_ptr, bool *disablePatch)
224 | {
225 | const uint8_t *cmdParam;
226 | FWCommandHdr *cmd = NULL;
227 | const uint8_t *evtParam = NULL;
228 | HciEventHdr *evt = NULL;
229 | uint8_t sendBuf[CMD_BUF_MAX_SIZE];
230 | uint8_t respBuf[CMD_BUF_MAX_SIZE];
231 | HciCommandHdr *hciCmd = (HciCommandHdr *)sendBuf;
232 | HciResponse *resp = (HciResponse *)respBuf;
233 | uint32_t actRespLen = 0;
234 | int remain = (int)(fwData->getLength() - (*fw_ptr - (uint8_t *)fwData->getBytesNoCopy()));
235 |
236 | /* The first byte indicates the types of the patch command or event.
237 | * 0x01 means HCI command and 0x02 is HCI event. If the first bytes
238 | * in the current firmware buffer doesn't start with 0x01 or
239 | * the size of remain buffer is smaller than HCI command header,
240 | * the firmware file is corrupted and it should stop the patching
241 | * process.
242 | */
243 | if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) {
244 | XYLog("Intel fw corrupted: invalid cmd read\n");
245 | return false;
246 | }
247 | (*fw_ptr)++;
248 | remain--;
249 |
250 | cmd = (FWCommandHdr *)(*fw_ptr);
251 | *fw_ptr += sizeof(*cmd);
252 | remain -= sizeof(*cmd);
253 |
254 | /* Ensure that the remain firmware data is long enough than the length
255 | * of command parameter. If not, the firmware file is corrupted.
256 | */
257 | if (remain < cmd->len) {
258 | XYLog("Intel fw corrupted: invalid cmd len\n");
259 | return false;
260 | }
261 | /* If there is a command that loads a patch in the firmware
262 | * file, then enable the patch upon success, otherwise just
263 | * disable the manufacturer mode, for example patch activation
264 | * is not required when the default firmware patch file is used
265 | * because there are no patch data to load.
266 | */
267 | if (*disablePatch && OSSwapLittleToHostInt16(cmd->opcode) == 0xfc8e)
268 | *disablePatch = false;
269 |
270 | cmdParam = *fw_ptr;
271 | *fw_ptr += cmd->len;
272 | remain -= cmd->len;
273 |
274 | /* This reads the expected events when the above command is sent to the
275 | * device. Some vendor commands expects more than one events, for
276 | * example command status event followed by vendor specific event.
277 | * For this case, it only keeps the last expected event. so the command
278 | * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of
279 | * last expected event.
280 | */
281 | while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) {
282 | (*fw_ptr)++;
283 | remain--;
284 |
285 | evt = (HciEventHdr *)(*fw_ptr);
286 | *fw_ptr += sizeof(*evt);
287 | remain -= sizeof(*evt);
288 |
289 | if (remain < evt->len) {
290 | XYLog("Intel fw corrupted: invalid evt len\n");
291 | return false;
292 | }
293 |
294 | evtParam = *fw_ptr;
295 | *fw_ptr += evt->len;
296 | remain -= evt->len;
297 | }
298 |
299 | /* Every HCI commands in the firmware file has its correspond event.
300 | * If event is not found or remain is smaller than zero, the firmware
301 | * file is corrupted.
302 | */
303 | if (!evt || !evtParam || remain < 0) {
304 | XYLog("Intel fw corrupted: invalid evt read\n");
305 | return false;
306 | }
307 |
308 | memset(sendBuf, 0, sizeof(sendBuf));
309 | memset(respBuf, 0, sizeof(respBuf));
310 | hciCmd->opcode = OSSwapLittleToHostInt16(cmd->opcode);
311 | hciCmd->len = cmd->len;
312 | memcpy(hciCmd->data, cmdParam, hciCmd->len);
313 |
314 | if (!intelSendHCISyncEvent(hciCmd, resp, sizeof(respBuf), &actRespLen, evt->evt, HCI_INIT_TIMEOUT)) {
315 | XYLog("sending Intel patch command (0x%4.4x) failed\n", hciCmd->opcode);
316 | return false;
317 | }
318 |
319 | return true;
320 | }
321 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen1.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothGen1.hpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #ifndef IntelBluetoothOpsGen1_hpp
10 | #define IntelBluetoothOpsGen1_hpp
11 |
12 | #include "BtIntel.h"
13 |
14 | class IntelBluetoothOpsGen1 : public BtIntel {
15 | OSDeclareDefaultStructors(IntelBluetoothOpsGen1)
16 |
17 | public:
18 |
19 | virtual bool setup() override;
20 |
21 | virtual bool shutdown() override;
22 |
23 | virtual bool getFirmwareName(char *fwname, size_t len) override;
24 |
25 | private:
26 |
27 | bool patching(OSData *fwData, const uint8_t **fw_ptr, bool *disablePatch);
28 |
29 | bool hciReset();
30 |
31 | OSData *getFirmware(IntelVersion *ver, char *, size_t);
32 |
33 | private:
34 | char loadedFirmwareName[64];
35 |
36 | };
37 |
38 | #endif /* IntelBluetoothOpsGen1_hpp */
39 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen2.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothOpsGen2.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "IntelBluetoothOpsGen2.hpp"
10 | #include "Log.h"
11 |
12 | OSDefineMetaClassAndStructors(IntelBluetoothOpsGen2, BtIntel)
13 |
14 | bool IntelBluetoothOpsGen2::
15 | bootloaderSetup(IntelVersion *ver)
16 | {
17 | IntelVersion newVer;
18 | IntelBootParams params;
19 | uint32_t bootParams;
20 | char ddcname[64];
21 |
22 | /* Set the default boot parameter to 0x0 and it is updated to
23 | * SKU specific boot parameter after reading Intel_Write_Boot_Params
24 | * command while downloading the firmware.
25 | */
26 | bootParams = 0x00000000;
27 |
28 | if (!downloadFirmware(ver, ¶ms, &bootParams)) {
29 | return false;
30 | }
31 |
32 | /* controller is already having an operational firmware */
33 | if (ver->fw_variant == 0x23) {
34 | XYLog("Frimware is already running, finishing\n");
35 | goto finish;
36 | }
37 |
38 | if (!intelBoot(bootParams)) {
39 | XYLog("Boot failed\n");
40 | return false;
41 | }
42 |
43 | if (!getFirmware(ver, ¶ms, ddcname, sizeof(ddcname), "ddc")) {
44 | XYLog("Unsupported Intel firmware naming\n");
45 | } else {
46 | /* Once the device is running in operational mode, it needs to
47 | * apply the device configuration (DDC) parameters.
48 | *
49 | * The device can work without DDC parameters, so even if it
50 | * fails to load the file, no need to fail the setup.
51 | */
52 | loadDDCConfig(ddcname);
53 | }
54 |
55 | /* Read the Intel version information after loading the FW */
56 | if (!readVersion(&newVer)) {
57 | return false;
58 | }
59 |
60 | intelVersionInfo(&newVer);
61 |
62 | finish:
63 |
64 | /* Set the event mask for Intel specific vendor events. This enables
65 | * a few extra events that are useful during general operation. It
66 | * does not enable any debugging related events.
67 | *
68 | * The device will function correctly without these events enabled
69 | * and thus no need to fail the setup.
70 | */
71 | setEventMask(false);
72 |
73 | return true;
74 | }
75 |
76 | bool IntelBluetoothOpsGen2::
77 | setup()
78 | {
79 | IntelVersion ver;
80 |
81 | /* Read the Intel version information to determine if the device
82 | * is in bootloader mode or if it already has operational firmware
83 | * loaded.
84 | */
85 | if (!readVersion(&ver)) {
86 | XYLog("Intel Read version failed\n");
87 | resetToBootloader();
88 | return false;
89 | }
90 |
91 | if (!intelVersionInfo(&ver)) {
92 | return false;
93 | }
94 |
95 | return bootloaderSetup(&ver);
96 | }
97 |
98 | bool IntelBluetoothOpsGen2::
99 | downloadFirmware(IntelVersion *ver, IntelBootParams *params, uint32_t *bootParams)
100 | {
101 | OSData *fwData;
102 | char fwname[64];
103 | IOReturn ior;
104 | uint32_t actSize = 0;
105 | uint8_t buf[CMD_BUF_MAX_SIZE];
106 | HciResponse *resp = (HciResponse *)buf;
107 | bool firmwareMode = false;
108 | bool ret = true;
109 |
110 | if (!ver || !params) {
111 | return false;
112 | }
113 |
114 | /* The firmware variant determines if the device is in bootloader
115 | * mode or is running operational firmware. The value 0x06 identifies
116 | * the bootloader and the value 0x23 identifies the operational
117 | * firmware.
118 | *
119 | * When the operational firmware is already present, then only
120 | * the check for valid Bluetooth device address is needed. This
121 | * determines if the device will be added as configured or
122 | * unconfigured controller.
123 | *
124 | * It is not possible to use the Secure Boot Parameters in this
125 | * case since that command is only available in bootloader mode.
126 | */
127 | if (ver->fw_variant == 0x23) {
128 |
129 | firmwareMode = true;
130 |
131 | /* SfP and WsP don't seem to update the firmware version on file
132 | * so version checking is currently possible.
133 | */
134 | switch (ver->hw_variant) {
135 | case 0x0b: /* SfP */
136 | case 0x0c: /* WsP */
137 | return true;
138 | }
139 |
140 | /* Proceed to download to check if the version matches */
141 | goto download;
142 | }
143 |
144 | /* Read the secure boot parameters to identify the operating
145 | * details of the bootloader.
146 | */
147 | if (!readBootParams(params)) {
148 | return false;
149 | }
150 |
151 | /* It is required that every single firmware fragment is acknowledged
152 | * with a command complete event. If the boot parameters indicate
153 | * that this bootloader does not send them, then abort the setup.
154 | */
155 | if (params->limited_cce != 0x00) {
156 | XYLog("Unsupported Intel firmware loading method (%u)\n",
157 | params->limited_cce);
158 | return false;
159 | }
160 |
161 | download:
162 | /* With this Intel bootloader only the hardware variant and device
163 | * revision information are used to select the right firmware for SfP
164 | * and WsP.
165 | *
166 | * The firmware filename is ibt--.sfi.
167 | *
168 | * Currently the supported hardware variants are:
169 | * 11 (0x0b) for iBT3.0 (LnP/SfP)
170 | * 12 (0x0c) for iBT3.5 (WsP)
171 | *
172 | * For ThP/JfP and for future SKU's, the FW name varies based on HW
173 | * variant, HW revision and FW revision, as these are dependent on CNVi
174 | * and RF Combination.
175 | *
176 | * 17 (0x11) for iBT3.5 (JfP)
177 | * 18 (0x12) for iBT3.5 (ThP)
178 | *
179 | * The firmware file name for these will be
180 | * ibt---.sfi.
181 | *
182 | */
183 | if (!getFirmware(ver, params, fwname, sizeof(fwname), "sfi")) {
184 | if (firmwareMode) {
185 | /* Firmware has already been loaded */
186 | return true;
187 | }
188 | XYLog("Unsupported Intel firmware naming\n");
189 | return false;
190 | }
191 |
192 | strncpy(this->loadedFirmwareName, fwname, sizeof(this->loadedFirmwareName));
193 |
194 | fwData = requestFirmwareData(fwname, true);
195 | if (!fwData) {
196 | if (firmwareMode) {
197 | /* Firmware has already been loaded */
198 | return true;
199 | }
200 | XYLog("Failed to load Intel firmware file %s\n", fwname);
201 | return false;
202 | }
203 |
204 | if (fwData->getLength() < 644) {
205 | XYLog("Invalid size of firmware file (%zu)\n",
206 | (size_t)fwData->getLength());
207 | ret = false;
208 | goto done;
209 | }
210 |
211 | /* Start firmware downloading and get boot parameter */
212 | if ((ior = downloadFirmwareData(ver, fwData, bootParams)) != kIOReturnSuccess) {
213 | if (ior == -EALREADY) {
214 | /* Firmware has already been loaded */
215 | ret = true;
216 | goto done;
217 | }
218 |
219 | /* When FW download fails, send Intel Reset to retry
220 | * FW download.
221 | */
222 | resetToBootloader();
223 | goto done;
224 | }
225 |
226 | /* Before switching the device into operational mode and with that
227 | * booting the loaded firmware, wait for the bootloader notification
228 | * that all fragments have been successfully received.
229 | *
230 | * When the event processing receives the notification, then the
231 | * BTUSB_DOWNLOADING flag will be cleared.
232 | *
233 | * The firmware loading should not take longer than 5 seconds
234 | * and thus just timeout if that happens and fail the setup
235 | * of this device.
236 | */
237 | memset(buf, 0, sizeof(buf));
238 | ior = m_pUSBDeviceController->interruptPipeRead(resp, sizeof(buf), &actSize, 5000);
239 | if (ior != kIOReturnSuccess) {
240 | XYLog("waiting for firmware download done timeout\n");
241 | resetToBootloader();
242 | ret = false;
243 | goto done;
244 | }
245 |
246 | if (resp->evt.evt == 0xff && resp->numCommands == 0x06) {
247 | XYLog("Notify: Firmware download done\n");
248 | goto done;
249 | }
250 |
251 | ret = false;
252 |
253 | done:
254 | OSSafeReleaseNULL(fwData);
255 | return ret;
256 | }
257 |
258 | IOReturn IntelBluetoothOpsGen2::
259 | downloadFirmwareData(IntelVersion *ver, OSData *fwData, uint32_t *bootParams)
260 | {
261 | /* SfP and WsP don't seem to update the firmware version on file
262 | * so version checking is currently not possible.
263 | */
264 | switch (ver->hw_variant) {
265 | case 0x0b: /* SfP */
266 | case 0x0c: /* WsP */
267 | /* Skip version checking */
268 | break;
269 | default:
270 |
271 | /* Skip download if firmware has the same version */
272 | if (firmwareVersion(ver->fw_build_num,
273 | ver->fw_build_ww, ver->fw_build_yy,
274 | fwData, bootParams)) {
275 | XYLog("Firmware already loaded\n");
276 | /* Return -EALREADY to indicate that the firmware has
277 | * already been loaded.
278 | */
279 | return -EALREADY;
280 | }
281 | }
282 |
283 | /* The firmware variant determines if the device is in bootloader
284 | * mode or is running operational firmware. The value 0x06 identifies
285 | * the bootloader and the value 0x23 identifies the operational
286 | * firmware.
287 | *
288 | * If the firmware version has changed that means it needs to be reset
289 | * to bootloader when operational so the new firmware can be loaded.
290 | */
291 | if (ver->fw_variant == 0x23) {
292 | XYLog("Unsupported fw variant: %d\n", ver->fw_variant);
293 | return kIOReturnInvalid;
294 | }
295 |
296 | if (!rsaHeaderSecureSend(fwData)) {
297 | XYLog("Send RSA header failed\n");
298 | return kIOReturnError;
299 | }
300 |
301 | return downloadFirmwarePayload(fwData, RSA_HEADER_LEN) ? kIOReturnSuccess : kIOReturnError;
302 | }
303 |
304 | bool IntelBluetoothOpsGen2::
305 | getFirmware(IntelVersion *ver, IntelBootParams *params,
306 | char *name, size_t len, const char *suffix)
307 | {
308 | switch (ver->hw_variant) {
309 | case 0x0b: /* SfP */
310 | case 0x0c: /* WsP */
311 | snprintf(name, len, "ibt-%u-%u.%s",
312 | OSSwapLittleToHostInt16(ver->hw_variant),
313 | OSSwapLittleToHostInt16(params->dev_revid),
314 | suffix);
315 | break;
316 | case 0x11: /* JfP */
317 | case 0x12: /* ThP */
318 | case 0x13: /* HrP */
319 | case 0x14: /* CcP */
320 | snprintf(name, len, "ibt-%u-%u-%u.%s",
321 | OSSwapLittleToHostInt16(ver->hw_variant),
322 | OSSwapLittleToHostInt16(ver->hw_revision),
323 | OSSwapLittleToHostInt16(ver->fw_revision),
324 | suffix);
325 | break;
326 | default:
327 | return false;
328 | }
329 |
330 | return true;
331 | }
332 |
333 | bool IntelBluetoothOpsGen2::
334 | rsaHeaderSecureSend(OSData *fwData)
335 | {
336 | /* Start the firmware download transaction with the Init fragment
337 | * represented by the 128 bytes of CSS header.
338 | */
339 | XYLog("send firmware header\n");
340 | if (!securedSend(0x00, 128, (const uint8_t *)fwData->getBytesNoCopy())) {
341 | XYLog("Failed to send firmware header\n");
342 | return false;
343 | }
344 | XYLog("send firmware header done\n");
345 |
346 | /* Send the 256 bytes of public key information from the firmware
347 | * as the PKey fragment.
348 | */
349 | XYLog("send firmware pkey\n");
350 | if (!securedSend(0x03, 256, (const uint8_t *)fwData->getBytesNoCopy() + 128)) {
351 | XYLog("Failed to send firmware pkey\n");
352 | return false;
353 | }
354 | XYLog("send firmware pkey done\n");
355 |
356 | /* Send the 256 bytes of signature information from the firmware
357 | * as the Sign fragment.
358 | */
359 | XYLog("send firmware signature\n");
360 | if (!securedSend(0x02, 256, (const uint8_t *)fwData->getBytesNoCopy() + 388)) {
361 | XYLog("Failed to send firmware signature\n");
362 | return false;
363 | }
364 | XYLog("send firmware signature done\n");
365 |
366 | return true;
367 | }
368 |
369 | bool IntelBluetoothOpsGen2::
370 | downloadFirmwarePayload(OSData *fwData, size_t offset)
371 | {
372 | XYLog("send firmware payload\n");
373 | uint32_t frag_len;
374 | bool ret = true;
375 | const uint8_t *fw_ptr = (uint8_t *)fwData->getBytesNoCopy() + offset;
376 | frag_len = 0;
377 |
378 | while (fw_ptr - (uint8_t *)fwData->getBytesNoCopy() < fwData->getLength()) {
379 | HciCommandHdr *cmd = (HciCommandHdr *)(fw_ptr + frag_len);
380 |
381 | frag_len += sizeof(*cmd) + cmd->len;
382 |
383 | /* The parameter length of the secure send command requires
384 | * a 4 byte alignment. It happens so that the firmware file
385 | * contains proper Intel_NOP commands to align the fragments
386 | * as needed.
387 | *
388 | * Send set of commands with 4 byte alignment from the
389 | * firmware data buffer as a single Data fragement.
390 | */
391 | if (!(frag_len % 4)) {
392 | if (!securedSend(0x01, frag_len, fw_ptr)) {
393 | XYLog("Failed to send firmware data\n");
394 | ret = false;
395 | goto done;
396 | }
397 |
398 | fw_ptr += frag_len;
399 | frag_len = 0;
400 | }
401 | }
402 |
403 | done:
404 | XYLog("send firmware payload done\n");
405 | return ret;
406 | }
407 |
408 | bool IntelBluetoothOpsGen2::
409 | firmwareVersion(uint8_t num, uint8_t ww, uint8_t yy, OSData *fwData, uint32_t *bootAddr)
410 | {
411 | const uint8_t *fw_ptr = (const uint8_t *)fwData->getBytesNoCopy();
412 |
413 | while (fw_ptr - (uint8_t *)fwData->getBytesNoCopy() < fwData->getLength()) {
414 | FWCommandHdr *cmd = (FWCommandHdr *)(fw_ptr);
415 |
416 | /* Each SKU has a different reset parameter to use in the
417 | * HCI_Intel_Reset command and it is embedded in the firmware
418 | * data. So, instead of using static value per SKU, check
419 | * the firmware data and save it for later use.
420 | */
421 | if (OSSwapLittleToHostConstInt16(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) {
422 | struct cmd_write_boot_params *params;
423 |
424 | params = (struct cmd_write_boot_params *)(fw_ptr + sizeof(*cmd));
425 |
426 | *bootAddr = OSSwapLittleToHostConstInt32(params->boot_addr);
427 |
428 | XYLog("Boot Address: 0x%x\n", *bootAddr);
429 |
430 | XYLog("Firmware Version: %u-%u.%u\n",
431 | params->fw_build_num, params->fw_build_ww,
432 | params->fw_build_yy);
433 |
434 | return (num == params->fw_build_num &&
435 | ww == params->fw_build_ww &&
436 | yy == params->fw_build_yy);
437 | }
438 |
439 | fw_ptr += sizeof(*cmd) + cmd->len;
440 | }
441 |
442 | return false;
443 | }
444 |
445 | bool IntelBluetoothOpsGen2::
446 | shutdown()
447 | {
448 | return true;
449 | }
450 |
451 | bool IntelBluetoothOpsGen2::
452 | getFirmwareName(char *fwname, size_t len)
453 | {
454 | strncpy(fwname, this->loadedFirmwareName, len - 1);
455 | fwname[len - 1] = '\0';
456 | return true;
457 | }
458 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen2.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothOpsGen2.hpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #ifndef IntelBluetoothOpsGen2_hpp
10 | #define IntelBluetoothOpsGen2_hpp
11 |
12 | #include "BtIntel.h"
13 |
14 | #define CMD_WRITE_BOOT_PARAMS 0xfc0e
15 | struct cmd_write_boot_params {
16 | uint32_t boot_addr;
17 | uint8_t fw_build_num;
18 | uint8_t fw_build_ww;
19 | uint8_t fw_build_yy;
20 | } __attribute__((packed));
21 |
22 | class IntelBluetoothOpsGen2 : public BtIntel {
23 | OSDeclareDefaultStructors(IntelBluetoothOpsGen2)
24 |
25 | public:
26 |
27 | virtual bool setup() override;
28 |
29 | virtual bool shutdown() override;
30 |
31 | virtual bool getFirmwareName(char *fwname, size_t len) override;
32 |
33 | protected:
34 |
35 | bool downloadFirmwarePayload(OSData *fwData, size_t offset);
36 |
37 | bool rsaHeaderSecureSend(OSData *fwData);
38 |
39 | bool firmwareVersion(uint8_t num, uint8_t ww, uint8_t yy, OSData *fwData, uint32_t *bootAddr);
40 |
41 | bool bootloaderSetup(IntelVersion *ver);
42 |
43 | private:
44 |
45 | bool getFirmware(IntelVersion *ver, IntelBootParams *params, char *name, size_t len, const char *suffix);
46 |
47 | IOReturn downloadFirmwareData(IntelVersion *ver, OSData *fwData, uint32_t *bootParams);
48 |
49 | bool downloadFirmware(IntelVersion *ver, IntelBootParams *params, uint32_t *bootParams);
50 |
51 | private:
52 | char loadedFirmwareName[64];
53 |
54 | };
55 |
56 | #endif /* IntelBluetoothOpsGen2_hpp */
57 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen3.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothOpsGen3.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "IntelBluetoothOpsGen3.hpp"
10 | #include "Log.h"
11 | #include "linux.h"
12 |
13 | OSDefineMetaClassAndStructors(IntelBluetoothOpsGen3, IntelBluetoothOpsGen2)
14 |
15 | int IntelBluetoothOpsGen3::
16 | readVersionTyP(void *version)
17 | {
18 | uint8_t buf[CMD_BUF_MAX_SIZE], temp[CMD_BUF_MAX_SIZE];
19 | uint actLen = 0;
20 | HciCommandHdr *cmd = (HciCommandHdr *)buf;
21 | HciResponse *resp = (HciResponse *)temp;
22 |
23 | memset(temp, 0, sizeof(temp));
24 | cmd->opcode = OSSwapHostToLittleInt16(0xfc05);
25 | cmd->len = 1;
26 | cmd->data[0] = 0xFF;
27 | if (!intelSendHCISync(cmd, resp, sizeof(buf), &actLen, HCI_CMD_TIMEOUT)) {
28 | XYLog("Reading Intel version information failed\n");
29 | return 0;
30 | }
31 |
32 | if (actLen - 5 <= 0 || actLen - 5 > CMD_BUF_MAX_SIZE) {
33 | XYLog("Intel version size invalid (act: %d)\n", actLen);
34 | return 0;
35 | }
36 |
37 | memcpy(version, resp->data, actLen - 5);
38 |
39 | return actLen - 5;
40 | }
41 |
42 | bool IntelBluetoothOpsGen3::
43 | bootloaderSetupTLV(IntelVersionTLV *verTLV)
44 | {
45 | uint32_t bootParams;
46 | char ddcname[64];
47 | IntelVersionTLV newVerTLV;
48 |
49 | /* Set the default boot parameter to 0x0 and it is updated to
50 | * SKU specific boot parameter after reading Intel_Write_Boot_Params
51 | * command while downloading the firmware.
52 | */
53 | bootParams = 0x00000000;
54 |
55 | if (!downloadFirmware(verTLV, &bootParams)) {
56 | XYLog("Download firmware failed\n");
57 | return false;
58 | }
59 |
60 | /* check if controller is already having an operational firmware */
61 | if (verTLV->img_type == 0x03) {
62 | XYLog("Frimware is already running, finishing\n");
63 | goto finish;
64 | }
65 |
66 | if (!intelBoot(bootParams)) {
67 | XYLog("Boot failed\n");
68 | return false;
69 | }
70 |
71 | getFirmware(verTLV, ddcname, sizeof(ddcname), "ddc");
72 |
73 | /* Once the device is running in operational mode, it needs to
74 | * apply the device configuration (DDC) parameters.
75 | *
76 | * The device can work without DDC parameters, so even if it
77 | * fails to load the file, no need to fail the setup.
78 | */
79 | loadDDCConfig(ddcname);
80 |
81 | /* Read the Intel version information after loading the FW */
82 | if (!readVersionTLV(&newVerTLV)) {
83 | XYLog("Intel Read TLV version failed %d\n", __LINE__);
84 | return false;
85 | }
86 |
87 | versionInfoTLV(&newVerTLV);
88 |
89 | finish:
90 | /* Set the event mask for Intel specific vendor events. This enables
91 | * a few extra events that are useful during general operation. It
92 | * does not enable any debugging related events.
93 | *
94 | * The device will function correctly without these events enabled
95 | * and thus no need to fail the setup.
96 | */
97 | setEventMask(false);
98 |
99 | return true;
100 | }
101 |
102 | bool IntelBluetoothOpsGen3::
103 | setup()
104 | {
105 | uint8_t v[CMD_BUF_MAX_SIZE];
106 | IntelVersion *verPtr = reinterpret_cast(v);
107 | IntelVersionTLV verTLV;
108 |
109 | /* Starting from TyP device, the command parameter and response are
110 | * changed even though the OCF for HCI_Intel_Read_Version command
111 | * remains same. The legacy devices can handle even if the
112 | * command has a parameter and returns a correct version information.
113 | * So, it uses new format to support both legacy and new format.
114 | */
115 | int actLen = readVersionTyP(verPtr);
116 |
117 | if (actLen <= 0) {
118 | XYLog("Reading Intel version command failed\n");
119 | return false;
120 | }
121 |
122 | /* For Legacy device, check the HW platform value and size */
123 | if (actLen == sizeof(IntelVersion)) {
124 | XYLog("Read the legacy Intel version information\n");
125 |
126 | /* Display version information */
127 | intelVersionInfo(verPtr);
128 |
129 | /* Check for supported iBT hardware variants of this firmware
130 | * loading method.
131 | *
132 | * This check has been put in place to ensure correct forward
133 | * compatibility options when newer hardware variants come
134 | * along.
135 | */
136 |
137 | switch (verPtr->hw_variant) {
138 | case 0x0b: /* SfP */
139 | case 0x0c: /* WsP */
140 | case 0x11: /* JfP */
141 | case 0x12: /* ThP */
142 | case 0x13: /* HrP */
143 | case 0x14: /* CcP */
144 |
145 | if (!bootloaderSetup(verPtr)) {
146 | return false;
147 | }
148 | break;
149 |
150 | default:
151 | XYLog("Unsupported Intel hw variant (%u)\n", verPtr->hw_variant);
152 | return false;
153 | }
154 |
155 | return true;
156 | }
157 |
158 | /* memset ver_tlv to start with clean state as few fields are exclusive
159 | * to bootloader mode and are not populated in operational mode
160 | */
161 | memset(&verTLV, 0, sizeof(verTLV));
162 |
163 | if (!parseVersionTLV(&verTLV, v, actLen)) {
164 | XYLog("Failed to parse TLV version information\n");
165 | return false;
166 | }
167 |
168 | if (INTEL_HW_PLATFORM(verTLV.cnvi_bt) != 0x37) {
169 | XYLog("Unsupported Intel hardware platform (0x%2x)\n",
170 | INTEL_HW_PLATFORM(verTLV.cnvi_bt));
171 | // TODO: We found that the Gen 2 bluetooth may return different size with IntelVersion when in OPERATIONAL mode, then the code will go here, considering we will not attach the really unsupported device to this driver, so we fake it as firmware loaded done here.
172 | return true;
173 | }
174 |
175 | /* Check for supported iBT hardware variants of this firmware
176 | * loading method.
177 | *
178 | * This check has been put in place to ensure correct forward
179 | * compatibility options when newer hardware variants come
180 | * along.
181 | */
182 | switch (INTEL_HW_VARIANT(verTLV.cnvi_bt)) {
183 | case 0x11: /* JfP */
184 | case 0x12: /* ThP */
185 | case 0x13: /* HrP */
186 | case 0x14: /* CcP */
187 |
188 | XYLog("Legacy bootloader with new firmware\n");
189 |
190 | /* Some legacy bootloader devices starting from JfP,
191 | * the operational firmware supports both old and TLV based
192 | * HCI_Intel_Read_Version command based on the command
193 | * parameter.
194 | *
195 | * For upgrading firmware case, the TLV based version cannot
196 | * be used because the firmware filename for legacy bootloader
197 | * is based on the old format.
198 | *
199 | * Also, it is not easy to convert TLV based version from the
200 | * legacy version format.
201 | *
202 | * So, as a workaround for those devices, use the legacy
203 | * HCI_Intel_Read_Version to get the version information and
204 | * run the legacy bootloader setup.
205 | */
206 | if (!readVersion(verPtr)) {
207 | XYLog("Intel Read version failed\n");
208 | return false;
209 | }
210 |
211 | if (!bootloaderSetup(verPtr)) {
212 | return false;
213 | }
214 | break;
215 | case 0x17:
216 | case 0x18:
217 | case 0x19:
218 | case 0x1b:
219 | case 0x1c:
220 | /* Display version information of TLV type */
221 | versionInfoTLV(&verTLV);
222 |
223 | if (!bootloaderSetupTLV(&verTLV)) {
224 | return false;
225 | }
226 | break;
227 | default:
228 | XYLog("Unsupported Intel hw variant (%u)\n",
229 | INTEL_HW_VARIANT(verTLV.cnvi_bt));
230 | return false;
231 | }
232 |
233 | return true;
234 | }
235 |
236 | bool IntelBluetoothOpsGen3::
237 | downloadFirmware(IntelVersionTLV *ver, uint32_t *bootParams)
238 | {
239 | char fwname[64];
240 | OSData *fwData = NULL;
241 | IOReturn ior;
242 | uint32_t actSize = 0;
243 | uint8_t buf[CMD_BUF_MAX_SIZE];
244 | HciResponse *resp = (HciResponse *)buf;
245 | bool firmwareMode = false;
246 | bool ret = true;
247 |
248 | if (!ver || !bootParams) {
249 | return false;
250 | }
251 |
252 | /* The firmware variant determines if the device is in bootloader
253 | * mode or is running operational firmware. The value 0x03 identifies
254 | * the bootloader and the value 0x23 identifies the operational
255 | * firmware.
256 | *
257 | * When the operational firmware is already present, then only
258 | * the check for valid Bluetooth device address is needed. This
259 | * determines if the device will be added as configured or
260 | * unconfigured controller.
261 | *
262 | * It is not possible to use the Secure Boot Parameters in this
263 | * case since that command is only available in bootloader mode.
264 | */
265 | if (ver->img_type == 0x03) {
266 | firmwareMode = true;
267 | }
268 |
269 | getFirmware(ver, fwname, sizeof(fwname), "sfi");
270 |
271 | strncpy(this->loadedFirmwareName, fwname, sizeof(this->loadedFirmwareName));
272 |
273 | fwData = requestFirmwareData(fwname, true);
274 | if (!fwData) {
275 | if (firmwareMode) {
276 | /* Firmware has already been loaded */
277 | return true;
278 | }
279 | XYLog("Failed to load Intel firmware file %s\n", fwname);
280 | return false;
281 | }
282 |
283 | XYLog("Found device firmware: %s\n", fwname);
284 |
285 | if (fwData->getLength() < 644) {
286 | XYLog("Invalid size of firmware file (%zu)",
287 | (size_t)fwData->getLength());
288 | ret = false;
289 | goto done;
290 | }
291 |
292 | /* Start firmware downloading and get boot parameter */
293 | if ((ior = downloadFirmwareData(ver, fwData, bootParams,
294 | INTEL_HW_VARIANT(ver->cnvi_bt), ver->sbe_type)) != kIOReturnSuccess) {
295 | if (ior == -EALREADY) {
296 | /* Firmware has already been loaded */
297 | ret = true;
298 | goto done;
299 | }
300 |
301 | /* When FW download fails, send Intel Reset to retry
302 | * FW download.
303 | */
304 | resetToBootloader();
305 | goto done;
306 | }
307 |
308 | /* Before switching the device into operational mode and with that
309 | * booting the loaded firmware, wait for the bootloader notification
310 | * that all fragments have been successfully received.
311 | *
312 | * When the event processing receives the notification, then the
313 | * BTUSB_DOWNLOADING flag will be cleared.
314 | *
315 | * The firmware loading should not take longer than 5 seconds
316 | * and thus just timeout if that happens and fail the setup
317 | * of this device.
318 | */
319 | memset(buf, 0, sizeof(buf));
320 | ior = m_pUSBDeviceController->interruptPipeRead(resp, sizeof(buf), &actSize, 5000);
321 | if (ior != kIOReturnSuccess) {
322 | XYLog("waiting for firmware download done timeout\n");
323 | resetToBootloader();
324 | ret = false;
325 | goto done;
326 | }
327 |
328 | if (resp->evt.evt == 0xff && resp->numCommands == 0x06) {
329 | XYLog("Notify: Firmware download done\n");
330 | goto done;
331 | }
332 |
333 | ret = false;
334 |
335 | done:
336 | OSSafeReleaseNULL(fwData);
337 | return ret;
338 | }
339 |
340 | IOReturn IntelBluetoothOpsGen3::
341 | downloadFirmwareData(IntelVersionTLV *ver, OSData *fwData, uint32_t *bootParams, uint8_t hwVariant, uint8_t sbeType)
342 | {
343 | uint32_t cssHeaderVer;
344 |
345 | /* Skip download if firmware has the same version */
346 | if (firmwareVersion(ver->min_fw_build_nn,
347 | ver->min_fw_build_cw,
348 | ver->min_fw_build_yy,
349 | fwData, bootParams)) {
350 | XYLog("Firmware already loaded\n");
351 | /* Return -EALREADY to indicate that firmware has
352 | * already been loaded.
353 | */
354 | return -EALREADY;
355 | }
356 |
357 | /* The firmware variant determines if the device is in bootloader
358 | * mode or is running operational firmware. The value 0x01 identifies
359 | * the bootloader and the value 0x03 identifies the operational
360 | * firmware.
361 | *
362 | * If the firmware version has changed that means it needs to be reset
363 | * to bootloader when operational so the new firmware can be loaded.
364 | */
365 | if (ver->img_type == 0x03)
366 | return kIOReturnError;
367 |
368 | /* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support
369 | * only RSA secure boot engine. Hence, the corresponding sfi file will
370 | * have RSA header of 644 bytes followed by Command Buffer.
371 | *
372 | * iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA
373 | * secure boot engine. As a result, the corresponding sfi file will
374 | * have RSA header of 644, ECDSA header of 320 bytes followed by
375 | * Command Buffer.
376 | *
377 | * CSS Header byte positions 0x08 to 0x0B represent the CSS Header
378 | * version: RSA(0x00010000) , ECDSA (0x00020000)
379 | */
380 | cssHeaderVer = get_unaligned_le32((uint8_t *)fwData->getBytesNoCopy() + CSS_HEADER_OFFSET);
381 |
382 | if (cssHeaderVer != 0x00010000) {
383 | XYLog("Invalid CSS Header version: %d %d\n", cssHeaderVer, __LINE__);
384 | return kIOReturnError;
385 | }
386 |
387 | XYLog("%s hwVariant: %d sbeType: %d\n", __FUNCTION__, hwVariant, sbeType);
388 |
389 | if (hwVariant <= 0x14) {
390 | if (sbeType != 0x00) {
391 | XYLog("Invalid SBE type for hardware variant (%d)",
392 | hwVariant);
393 | return kIOReturnError;
394 | }
395 |
396 | if (!rsaHeaderSecureSend(fwData)) {
397 | XYLog("Send RSA header failed\n");
398 | return kIOReturnError;
399 | }
400 |
401 | if (!downloadFirmwarePayload(fwData, RSA_HEADER_LEN)) {
402 | return kIOReturnError;
403 | }
404 |
405 | } else if (hwVariant >= 0x17) {
406 | /* Check if CSS header for ECDSA follows the RSA header */
407 | if (((uint8_t *)fwData->getBytesNoCopy())[ECDSA_OFFSET] != 0x06)
408 | return -EINVAL;
409 |
410 | /* Check if the CSS Header version is ECDSA(0x00020000) */
411 | cssHeaderVer = get_unaligned_le32((uint8_t *)fwData->getBytesNoCopy() + ECDSA_OFFSET + CSS_HEADER_OFFSET);
412 | if (cssHeaderVer != 0x00020000) {
413 | XYLog("Invalid CSS Header version: %d %d\n", cssHeaderVer, __LINE__);
414 | return kIOReturnError;
415 | }
416 |
417 | if (sbeType == 0x00) {
418 | if (!rsaHeaderSecureSend(fwData)) {
419 | XYLog("Send RSA header failed\n");
420 | return kIOReturnError;
421 | }
422 |
423 | if (!downloadFirmwarePayload(fwData, RSA_HEADER_LEN + ECDSA_HEADER_LEN)) {
424 | return kIOReturnError;
425 | }
426 | } else if (sbeType == 0x01) {
427 | if (!ecdsaHeaderSecureSend(fwData)) {
428 | XYLog("Send ECDSA header failed\n");
429 | return kIOReturnError;
430 | }
431 |
432 | if (!downloadFirmwarePayload(fwData, RSA_HEADER_LEN + ECDSA_HEADER_LEN)) {
433 | return kIOReturnError;
434 | }
435 | }
436 | }
437 |
438 | return kIOReturnSuccess;
439 | }
440 |
441 | bool IntelBluetoothOpsGen3::
442 | ecdsaHeaderSecureSend(OSData *fwData)
443 | {
444 | /* Start the firmware download transaction with the Init fragment
445 | * represented by the 128 bytes of CSS header.
446 | */
447 | XYLog("send firmware header\n");
448 | if (!securedSend(0x00, 128, (const uint8_t *)fwData->getBytesNoCopy() + 644)) {
449 | XYLog("Failed to send firmware header\n");
450 | return false;
451 | }
452 | XYLog("send firmware header done\n");
453 |
454 | /* Send the 96 bytes of public key information from the firmware
455 | * as the PKey fragment.
456 | */
457 | XYLog("send firmware pkey\n");
458 | if (!securedSend(0x03, 96, (const uint8_t *)fwData->getBytesNoCopy() + 644 + 128)) {
459 | XYLog("Failed to send firmware pkey\n");
460 | return false;
461 | }
462 | XYLog("send firmware pkey done\n");
463 |
464 | /* Send the 96 bytes of signature information from the firmware
465 | * as the Sign fragment
466 | */
467 | XYLog("send firmware signature\n");
468 | if (!securedSend(0x02, 96, (const uint8_t *)fwData->getBytesNoCopy() + 644 + 224)) {
469 | XYLog("Failed to send firmware signature\n");
470 | return false;
471 | }
472 | XYLog("send firmware signature done\n");
473 |
474 | return true;
475 | }
476 |
477 | bool IntelBluetoothOpsGen3::
478 | parseVersionTLV(IntelVersionTLV *version, const uint8_t *versionDataPtr, int len)
479 | {
480 | IntelTLV *tlv;
481 |
482 | /* Consume Command Complete Status field */
483 | versionDataPtr++;
484 | len--;
485 |
486 | /* Event parameters contatin multiple TLVs. Read each of them
487 | * and only keep the required data. Also, it use existing legacy
488 | * version field like hw_platform, hw_variant, and fw_variant
489 | * to keep the existing setup flow
490 | */
491 | while (len > 0) {
492 | tlv = (IntelTLV *)versionDataPtr;
493 | switch (tlv->type) {
494 | case INTEL_TLV_CNVI_TOP:
495 | version->cnvi_top = get_unaligned_le32(tlv->val);
496 | break;
497 | case INTEL_TLV_CNVR_TOP:
498 | version->cnvr_top = get_unaligned_le32(tlv->val);
499 | break;
500 | case INTEL_TLV_CNVI_BT:
501 | version->cnvi_bt = get_unaligned_le32(tlv->val);
502 | break;
503 | case INTEL_TLV_CNVR_BT:
504 | version->cnvr_bt = get_unaligned_le32(tlv->val);
505 | break;
506 | case INTEL_TLV_DEV_REV_ID:
507 | version->dev_rev_id = get_unaligned_le16(tlv->val);
508 | break;
509 | case INTEL_TLV_IMAGE_TYPE:
510 | version->img_type = tlv->val[0];
511 | break;
512 | case INTEL_TLV_TIME_STAMP:
513 | /* If image type is Operational firmware (0x03), then
514 | * running FW Calendar Week and Year information can
515 | * be extracted from Timestamp information
516 | */
517 | version->min_fw_build_cw = tlv->val[0];
518 | version->min_fw_build_yy = tlv->val[1];
519 | version->timestamp = get_unaligned_le16(tlv->val);
520 | break;
521 | case INTEL_TLV_BUILD_TYPE:
522 | version->build_type = tlv->val[0];
523 | break;
524 | case INTEL_TLV_BUILD_NUM:
525 | /* If image type is Operational firmware (0x03), then
526 | * running FW build number can be extracted from the
527 | * Build information
528 | */
529 | version->min_fw_build_nn = tlv->val[0];
530 | version->build_num = get_unaligned_le32(tlv->val);
531 | break;
532 | case INTEL_TLV_SECURE_BOOT:
533 | version->secure_boot = tlv->val[0];
534 | break;
535 | case INTEL_TLV_OTP_LOCK:
536 | version->otp_lock = tlv->val[0];
537 | break;
538 | case INTEL_TLV_API_LOCK:
539 | version->api_lock = tlv->val[0];
540 | break;
541 | case INTEL_TLV_DEBUG_LOCK:
542 | version->debug_lock = tlv->val[0];
543 | break;
544 | case INTEL_TLV_MIN_FW:
545 | version->min_fw_build_nn = tlv->val[0];
546 | version->min_fw_build_cw = tlv->val[1];
547 | version->min_fw_build_yy = tlv->val[2];
548 | break;
549 | case INTEL_TLV_LIMITED_CCE:
550 | version->limited_cce = tlv->val[0];
551 | break;
552 | case INTEL_TLV_SBE_TYPE:
553 | version->sbe_type = tlv->val[0];
554 | break;
555 | case INTEL_TLV_OTP_BDADDR:
556 | memcpy(&version->otp_bd_addr, tlv->val, tlv->len);
557 | break;
558 | case INTEL_TLV_GIT_SHA1:
559 | version->git_sha1 = get_unaligned_le32(tlv->val);
560 | break;
561 | default:
562 | /* Ignore rest of information */
563 | break;
564 | }
565 |
566 | len -= (sizeof(IntelTLV) + tlv->len);
567 | versionDataPtr += (sizeof(IntelTLV) + tlv->len);
568 | }
569 |
570 | return true;
571 | }
572 |
573 | bool IntelBluetoothOpsGen3::
574 | readVersionTLV(IntelVersionTLV *version)
575 | {
576 | uint32_t actLen = 0;
577 | uint8_t sendBuf[CMD_BUF_MAX_SIZE];
578 | uint8_t respBuf[CMD_BUF_MAX_SIZE];
579 | HciResponse *resp = (HciResponse *)respBuf;
580 | HciCommandHdr *cmd = (HciCommandHdr *)sendBuf;
581 | const uint8_t *versionDataPtr;
582 | int len = 0;
583 |
584 | memset(sendBuf, 0, sizeof(sendBuf));
585 | cmd->opcode = OSSwapHostToLittleInt16(0xfc05);
586 | cmd->len = 1;
587 | cmd->data[0] = 0xFF;
588 |
589 | memset(respBuf, 0, sizeof(respBuf));
590 | if (!intelSendHCISync(cmd, resp, sizeof(respBuf), &actLen, HCI_CMD_TIMEOUT)) {
591 | XYLog("Reading Intel version information failed\n");
592 | return false;
593 | }
594 |
595 | if (actLen < 5) {
596 | XYLog("Invalid size %d\n", actLen);
597 | return false;
598 | }
599 |
600 | versionDataPtr = resp->data;
601 | len = actLen - 5;
602 |
603 | parseVersionTLV(version, versionDataPtr, len);
604 |
605 | return true;
606 | }
607 |
608 | bool IntelBluetoothOpsGen3::
609 | versionInfoTLV(IntelVersionTLV *version)
610 | {
611 | const char *variant;
612 |
613 | /* The hardware platform number has a fixed value of 0x37 and
614 | * for now only accept this single value.
615 | */
616 | if (INTEL_HW_PLATFORM(version->cnvi_bt) != 0x37) {
617 | XYLog("Unsupported Intel hardware platform (0x%2x)\n",
618 | INTEL_HW_PLATFORM(version->cnvi_bt));
619 | return false;
620 | }
621 |
622 | /* Check for supported iBT hardware variants of this firmware
623 | * loading method.
624 | *
625 | * This check has been put in place to ensure correct forward
626 | * compatibility options when newer hardware variants come along.
627 | */
628 | switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
629 | case 0x17: /* TyP */
630 | case 0x18: /* Slr */
631 | case 0x19: /* Slr-F */
632 | case 0x1b: /* Mgr */
633 | case 0x1c: /* Gale Peak (GaP) */
634 | break;
635 | default:
636 | XYLog("Unsupported Intel hardware variant (0x%x)\n",
637 | INTEL_HW_VARIANT(version->cnvi_bt));
638 | return false;
639 | }
640 |
641 | switch (version->img_type) {
642 | case 0x01:
643 | variant = "Bootloader";
644 | /* It is required that every single firmware fragment is acknowledged
645 | * with a command complete event. If the boot parameters indicate
646 | * that this bootloader does not send them, then abort the setup.
647 | */
648 | if (version->limited_cce != 0x00) {
649 | XYLog("Unsupported Intel firmware loading method (0x%x)\n",
650 | version->limited_cce);
651 | return false;
652 | }
653 |
654 | /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */
655 | if (version->sbe_type > 0x01) {
656 | XYLog("Unsupported Intel secure boot engine type (0x%x)\n",
657 | version->sbe_type);
658 | return false;
659 | }
660 |
661 | XYLog("Device revision is %u\n", version->dev_rev_id);
662 | XYLog("Secure boot is %s\n",
663 | version->secure_boot ? "enabled" : "disabled");
664 | XYLog("OTP lock is %s\n",
665 | version->otp_lock ? "enabled" : "disabled");
666 | XYLog("API lock is %s\n",
667 | version->api_lock ? "enabled" : "disabled");
668 | XYLog("Debug lock is %s\n",
669 | version->debug_lock ? "enabled" : "disabled");
670 | XYLog("Minimum firmware build %u week %u %u\n",
671 | version->min_fw_build_nn, version->min_fw_build_cw,
672 | 2000 + version->min_fw_build_yy);
673 | break;
674 | case 0x03:
675 | variant = "Firmware";
676 | break;
677 | default:
678 | XYLog("Unsupported image type(%02x)\n", version->img_type);
679 | return false;
680 | }
681 |
682 | XYLog("%s timestamp %u.%u buildtype %u build %u\n", variant,
683 | 2000 + (version->timestamp >> 8), version->timestamp & 0xff,
684 | version->build_type, version->build_num);
685 |
686 | if (version->img_type == 0x03)
687 | XYLog("Firmware SHA1: 0x%8.8x\n", version->git_sha1);
688 |
689 | return true;
690 | }
691 |
692 | bool IntelBluetoothOpsGen3::
693 | getFirmware(IntelVersionTLV *tlv, char *name, size_t len, const char *suffix)
694 | {
695 | /* The firmware file name for new generation controllers will be
696 | * ibt--
697 | */
698 | snprintf(name, len, "ibt-%04x-%04x.%s",
699 | INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(tlv->cnvi_top),
700 | INTEL_CNVX_TOP_STEP(tlv->cnvi_top)),
701 | INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(tlv->cnvr_top),
702 | INTEL_CNVX_TOP_STEP(tlv->cnvr_top)),
703 | suffix);
704 | return true;
705 | }
706 |
707 | bool IntelBluetoothOpsGen3::
708 | shutdown()
709 | {
710 | return true;
711 | }
712 |
713 | bool IntelBluetoothOpsGen3::
714 | getFirmwareName(char *fwname, size_t len)
715 | {
716 | strncpy(fwname, this->loadedFirmwareName, len - 1);
717 | fwname[len - 1] = '\0';
718 | return true;
719 | }
720 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/IntelBluetoothOpsGen3.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // IntelBluetoothOpsGen3.hpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/6/17.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #ifndef IntelBluetoothOpsGen3_hpp
10 | #define IntelBluetoothOpsGen3_hpp
11 |
12 | #include "IntelBluetoothOpsGen2.hpp"
13 |
14 | /* List of tlv type */
15 | enum {
16 | INTEL_TLV_CNVI_TOP = 0x10,
17 | INTEL_TLV_CNVR_TOP,
18 | INTEL_TLV_CNVI_BT,
19 | INTEL_TLV_CNVR_BT,
20 | INTEL_TLV_CNVI_OTP,
21 | INTEL_TLV_CNVR_OTP,
22 | INTEL_TLV_DEV_REV_ID,
23 | INTEL_TLV_USB_VENDOR_ID,
24 | INTEL_TLV_USB_PRODUCT_ID,
25 | INTEL_TLV_PCIE_VENDOR_ID,
26 | INTEL_TLV_PCIE_DEVICE_ID,
27 | INTEL_TLV_PCIE_SUBSYSTEM_ID,
28 | INTEL_TLV_IMAGE_TYPE,
29 | INTEL_TLV_TIME_STAMP,
30 | INTEL_TLV_BUILD_TYPE,
31 | INTEL_TLV_BUILD_NUM,
32 | INTEL_TLV_FW_BUILD_PRODUCT,
33 | INTEL_TLV_FW_BUILD_HW,
34 | INTEL_TLV_FW_STEP,
35 | INTEL_TLV_BT_SPEC,
36 | INTEL_TLV_MFG_NAME,
37 | INTEL_TLV_HCI_REV,
38 | INTEL_TLV_LMP_SUBVER,
39 | INTEL_TLV_OTP_PATCH_VER,
40 | INTEL_TLV_SECURE_BOOT,
41 | INTEL_TLV_KEY_FROM_HDR,
42 | INTEL_TLV_OTP_LOCK,
43 | INTEL_TLV_API_LOCK,
44 | INTEL_TLV_DEBUG_LOCK,
45 | INTEL_TLV_MIN_FW,
46 | INTEL_TLV_LIMITED_CCE,
47 | INTEL_TLV_SBE_TYPE,
48 | INTEL_TLV_OTP_BDADDR,
49 | INTEL_TLV_UNLOCKED_STATE,
50 | INTEL_TLV_GIT_SHA1
51 | };
52 |
53 | class IntelBluetoothOpsGen3 : public IntelBluetoothOpsGen2 {
54 | OSDeclareDefaultStructors(IntelBluetoothOpsGen3)
55 |
56 | public:
57 |
58 | virtual bool setup() override;
59 |
60 | virtual bool shutdown() override;
61 |
62 | virtual bool getFirmwareName(char *fwname, size_t len) override;
63 |
64 | protected:
65 |
66 | bool ecdsaHeaderSecureSend(OSData *fwData);
67 |
68 | bool bootloaderSetupTLV(IntelVersionTLV *ver);
69 |
70 | private:
71 |
72 | int readVersionTyP(void *version);
73 |
74 | bool versionInfoTLV(IntelVersionTLV *version);
75 |
76 | bool readVersionTLV(IntelVersionTLV *version);
77 |
78 | bool parseVersionTLV(IntelVersionTLV *version, const uint8_t *versionDataPtr, int len);
79 |
80 | bool getFirmware(IntelVersionTLV *tlv, char *name, size_t len, const char *suffix);
81 |
82 | bool downloadFirmware(IntelVersionTLV *ver, uint32_t *bootParams);
83 |
84 | IOReturn downloadFirmwareData(IntelVersionTLV *ver, OSData *fwData, uint32_t *bootParams, uint8_t hwVariant, uint8_t sbeType);
85 |
86 | private:
87 | char loadedFirmwareName[64];
88 | };
89 |
90 | #endif /* IntelBluetoothOpsGen3_hpp */
91 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/Log.h:
--------------------------------------------------------------------------------
1 | /** @file
2 | Copyright (c) 2020 zxystd. All rights reserved.
3 | SPDX-License-Identifier: GPL-3.0-only
4 | **/
5 |
6 | //
7 | // Log.h
8 | // IntelBluetoothFirmware
9 | //
10 | // Created by zxystd on 2019/12/3.
11 | // Copyright © 2019 zxystd. All rights reserved.
12 | //
13 |
14 | #ifndef Log_h
15 | #define Log_h
16 |
17 | #include
18 |
19 | #define XYLog(fmt, x...)\
20 | do\
21 | {\
22 | IOLog("%s: " fmt, "IntelFirmware", ##x);\
23 | }while(0)
24 |
25 | #endif /* Log_h */
26 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/USBDeviceController.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // USBHCIController.cpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/5/21.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #include "USBDeviceController.hpp"
10 | #include "Log.h"
11 | #include "Hci.h"
12 |
13 | #define super OSObject
14 | OSDefineMetaClassAndStructors(USBDeviceController, OSObject)
15 |
16 | #define kReadBufferSize 4096
17 |
18 | bool USBDeviceController::
19 | init(IOService *client, IOUSBHostDevice *dev)
20 | {
21 | XYLog("%s\n", __PRETTY_FUNCTION__);
22 | if (!super::init()) {
23 | return false;
24 | }
25 | _hciLock = IOLockAlloc();
26 | if (!_hciLock) {
27 | return false;
28 | }
29 | mReadBuffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
30 | , kIODirectionIn, kReadBufferSize);
31 | if (!mReadBuffer) {
32 | XYLog("Fail to alloc read buffer\n");
33 | return false;
34 | }
35 |
36 | mReadBuffer->prepare(kIODirectionIn);
37 | m_pDevice = dev;
38 | m_pClient = client;
39 | return true;
40 | }
41 |
42 | bool USBDeviceController::
43 | findInterface()
44 | {
45 | XYLog("%s\n", __PRETTY_FUNCTION__);
46 | OSIterator* iterator = m_pDevice->getChildIterator(gIOServicePlane);
47 | OSObject* candidate = NULL;
48 | if (iterator == NULL) {
49 | XYLog("can not create child iterator\n");
50 | return false;
51 | }
52 | while((candidate = iterator->getNextObject()) != NULL) {
53 | IOUSBHostInterface* interfaceCandidate = OSDynamicCast(IOUSBHostInterface, candidate);
54 | if(interfaceCandidate != NULL) {
55 | XYLog("Found interface!!!\n");
56 | m_pInterface = interfaceCandidate;
57 | break;
58 | }
59 | }
60 | OSSafeReleaseNULL(iterator);
61 | if (m_pInterface == NULL) {
62 | return false;
63 | }
64 | if (!m_pInterface->open(m_pClient)) {
65 | XYLog("can not open interface\n");
66 | return false;
67 | }
68 | return true;
69 | }
70 |
71 | void USBDeviceController::
72 | free()
73 | {
74 | XYLog("%s\n", __PRETTY_FUNCTION__);
75 | if (m_pBulkWritePipe) {
76 | m_pBulkWritePipe->abort();
77 | OSSafeReleaseNULL(m_pBulkWritePipe);
78 | }
79 | if (m_pBulkReadPipe) {
80 | m_pBulkReadPipe->abort();
81 | OSSafeReleaseNULL(m_pBulkReadPipe);
82 | }
83 | if (m_pInterruptReadPipe) {
84 | m_pInterruptReadPipe->abort();
85 | OSSafeReleaseNULL(m_pInterruptReadPipe);
86 | }
87 | if (mReadBuffer) {
88 | mReadBuffer->complete(kIODirectionIn);
89 | OSSafeReleaseNULL(mReadBuffer);
90 | }
91 | if (_hciLock) {
92 | IOLockFree(_hciLock);
93 | _hciLock = NULL;
94 | }
95 | if (m_pInterface) {
96 | if (m_pClient && m_pInterface->isOpen(m_pClient)) {
97 | m_pInterface->close(m_pClient);
98 | m_pClient = NULL;
99 | }
100 | m_pInterface = NULL;
101 | }
102 | m_pDevice = NULL;
103 | super::free();
104 | }
105 |
106 | bool USBDeviceController::
107 | initConfiguration()
108 | {
109 | XYLog("%s\n", __PRETTY_FUNCTION__);
110 | uint8_t configIndex = 0;
111 | uint8_t configNum = m_pDevice->getDeviceDescriptor()->bNumConfigurations;
112 | if (configNum < configIndex + configNum) {
113 | XYLog("config num error (num: %d)\n", configNum);
114 | return false;
115 | }
116 | const StandardUSB::ConfigurationDescriptor *configDescriptor = m_pDevice->getConfigurationDescriptor(configIndex);
117 | if (!configDescriptor) {
118 | XYLog("getConfigurationDescriptor(%d) failed\n", configIndex);
119 | return false;
120 | }
121 | XYLog("set configuration to %d\n", configDescriptor->bConfigurationValue);
122 | IOReturn ret = m_pDevice->setConfiguration(configDescriptor->bConfigurationValue);
123 | if (ret != kIOReturnSuccess) {
124 | XYLog("set device configuration to %d failed\n", configDescriptor->bConfigurationValue);
125 | return false;
126 | }
127 | return true;
128 | }
129 |
130 | bool USBDeviceController::
131 | findPipes()
132 | {
133 | XYLog("%s\n", __PRETTY_FUNCTION__);
134 | const StandardUSB::ConfigurationDescriptor *configDescriptor;
135 | const StandardUSB::InterfaceDescriptor *interfaceDescriptor;
136 | const EndpointDescriptor *endpointDescriptor;
137 | uint8_t epDirection, epType;
138 |
139 | configDescriptor = m_pInterface->getConfigurationDescriptor();
140 | interfaceDescriptor = m_pInterface->getInterfaceDescriptor();
141 | if (configDescriptor == NULL || interfaceDescriptor == NULL) {
142 | XYLog("Find descriptor NULL\n");
143 | return false;
144 | }
145 | endpointDescriptor = NULL;
146 | while ((endpointDescriptor = StandardUSB::getNextEndpointDescriptor(configDescriptor, interfaceDescriptor, endpointDescriptor))) {
147 | epDirection = StandardUSB::getEndpointDirection(endpointDescriptor);
148 | epType = StandardUSB::getEndpointType(endpointDescriptor);
149 | if (epDirection == kUSBIn && epType == kUSBInterrupt) {
150 | XYLog("Found Interrupt endpoint!\n");
151 | m_pInterruptReadPipe = m_pInterface->copyPipe(StandardUSB::getEndpointAddress(endpointDescriptor));
152 | if (m_pInterruptReadPipe == NULL) {
153 | XYLog("Copy InterruptReadPipe pipe fail\n");
154 | return false;
155 | }
156 | m_pInterruptReadPipe->retain();
157 | m_pInterruptReadPipe->release();
158 | } else {
159 | if (epDirection == kUSBOut && epType == kUSBBulk) {
160 | XYLog("Found Bulk out endpoint!\n");
161 | m_pBulkWritePipe = m_pInterface->copyPipe(StandardUSB::getEndpointAddress(endpointDescriptor));
162 | if (m_pBulkWritePipe == NULL) {
163 | XYLog("Copy Bulk pipe fail\n");
164 | return false;
165 | }
166 | m_pBulkWritePipe->retain();
167 | m_pBulkWritePipe->release();
168 | } else {
169 | if (epDirection == kUSBIn && epType == kUSBBulk) {
170 | XYLog("Found Bulk in endpoint!\n");
171 | m_pBulkReadPipe = m_pInterface->copyPipe(StandardUSB::getEndpointAddress(endpointDescriptor));
172 | if (m_pBulkReadPipe == NULL) {
173 | XYLog("Copy Bulk pipe fail\n");
174 | return false;
175 | }
176 | m_pBulkReadPipe->retain();
177 | m_pBulkReadPipe->release();
178 | }
179 | }
180 | }
181 | }
182 | return (m_pInterruptReadPipe != NULL && m_pBulkWritePipe != NULL && m_pBulkReadPipe != NULL);
183 | }
184 |
185 | IOReturn USBDeviceController::
186 | bulkPipeRead(void *buf, uint32_t buf_size, uint32_t *size, uint32_t timeout)
187 | {
188 | uint32_t actualLength = 0;
189 | IOReturn ret = m_pBulkReadPipe->io(mReadBuffer, (uint32_t)mReadBuffer->getLength(), actualLength, timeout);
190 | if (ret == kIOUSBPipeStalled) {
191 | m_pBulkReadPipe->clearStall(true);
192 | ret = m_pBulkReadPipe->io(mReadBuffer, (uint32_t)mReadBuffer->getLength(), actualLength, timeout);
193 | }
194 | if (ret == kIOReturnSuccess) {
195 | if (buf && actualLength > buf_size) {
196 | XYLog("%s buf size too small. buflen: %d act: %d\n", __FUNCTION__, buf_size, actualLength);
197 | }
198 | if (buf) {
199 | memcpy(buf, mReadBuffer->getBytesNoCopy(), min(actualLength, buf_size));
200 | }
201 | if (size) {
202 | *size = min(actualLength, buf_size);
203 | }
204 | } else {
205 | XYLog("%s failed: %s %d\n", __FUNCTION__, stringFromReturn(ret), ret);
206 | }
207 | return ret;
208 | }
209 |
210 | void USBDeviceController::
211 | interruptHandler(void *owner, void *parameter, IOReturn status, uint32_t bytesTransferred)
212 | {
213 | USBDeviceController *controller = OSDynamicCast(USBDeviceController, (OSObject *)owner);
214 | if (!controller || !parameter) {
215 | return;
216 | }
217 | switch (status) {
218 | case kIOReturnSuccess:
219 | break;
220 | case kIOReturnNotResponding:
221 | controller->m_pInterruptReadPipe->clearStall(false);
222 | default:
223 | XYLog("%s status: %s (%d) len: %d\n", __FUNCTION__, controller->stringFromReturn(status), status, bytesTransferred);
224 | break;
225 | }
226 |
227 | InterruptResp *resp = (InterruptResp *)parameter;
228 | resp->status = status;
229 | resp->dataLen = bytesTransferred;
230 | IOLockWakeup(controller->_hciLock, controller, true);
231 | }
232 |
233 | IOReturn USBDeviceController::
234 | interruptPipeRead(void *buf, uint32_t buf_size, uint32_t *size, uint32_t timeout)
235 | {
236 | AbsoluteTime deadline;
237 | IOUSBHostCompletion comple;
238 | InterruptResp interrupResp;
239 |
240 | clock_interval_to_deadline(timeout, kMillisecondScale, reinterpret_cast (&deadline));
241 | memset(&interrupResp, 0, sizeof(interrupResp));
242 | comple.action = interruptHandler;
243 | comple.owner = this;
244 | comple.parameter = &interrupResp;
245 |
246 | IOReturn ret = m_pInterruptReadPipe->io(mReadBuffer, (uint32_t)mReadBuffer->getLength(), &comple, 0);
247 | if (ret == kIOUSBPipeStalled) {
248 | m_pInterruptReadPipe->clearStall(true);
249 | ret = m_pInterruptReadPipe->io(mReadBuffer, (uint32_t)mReadBuffer->getLength(), &comple, 0);
250 | }
251 |
252 | if (ret == kIOReturnSuccess) {
253 | IOLockLock(_hciLock);
254 | if (IOLockSleepDeadline(_hciLock, this, deadline, THREAD_INTERRUPTIBLE) != THREAD_AWAKENED) {
255 | IOLockUnlock(_hciLock);
256 | m_pInterruptReadPipe->abort();
257 | XYLog("%s Timeout\n", __FUNCTION__);
258 | return kIOReturnTimeout;
259 | }
260 | if (interrupResp.dataLen <= 0) {
261 | IOLockUnlock(_hciLock);
262 | XYLog("%s invalid response size: %d\n", __FUNCTION__, interrupResp.dataLen);
263 | return kIOReturnError;
264 | }
265 | if (buf && interrupResp.dataLen > buf_size) {
266 | XYLog("%s buf size too small. buflen: %d act: %d\n", __FUNCTION__, buf_size, interrupResp.dataLen);
267 | }
268 | if (buf) {
269 | memcpy(buf, mReadBuffer->getBytesNoCopy(), min(interrupResp.dataLen, buf_size));
270 | }
271 | if (size) {
272 | *size = min(interrupResp.dataLen, buf_size);
273 | }
274 | IOLockUnlock(_hciLock);
275 | } else {
276 | XYLog("%s failed: %s %d\n", __FUNCTION__, stringFromReturn(ret), ret);
277 | }
278 | return ret;
279 | }
280 |
281 | IOReturn USBDeviceController::
282 | sendHCIRequest(HciCommandHdr *cmd, uint32_t timeout)
283 | {
284 | uint32_t actualLength;
285 | StandardUSB::DeviceRequest request =
286 | {
287 | .bmRequestType = makeDeviceRequestbmRequestType(kRequestDirectionOut, kRequestTypeClass, kRequestRecipientDevice),
288 | .bRequest = 0,
289 | .wValue = 0,
290 | .wIndex = 0,
291 | .wLength = (uint16_t)(HCI_COMMAND_HDR_SIZE + cmd->len)
292 | };
293 |
294 | return m_pInterface->deviceRequest(request, cmd, actualLength, timeout);
295 | }
296 |
297 | IOReturn USBDeviceController::
298 | bulkWrite(const void *data, uint32_t length, uint32_t timeout)
299 | {
300 | IOMemoryDescriptor* buffer = IOMemoryDescriptor::withAddress((void *)data, length, kIODirectionOut);
301 | if (!buffer) {
302 | XYLog("Unable to allocate bulk write buffer.\n");
303 | return kIOReturnNoMemory;
304 | }
305 | IOReturn ret;
306 | uint32_t actLen = 0;
307 | if ((ret = buffer->prepare(kIODirectionOut)) != kIOReturnSuccess) {
308 | XYLog("Failed to prepare bulk write memory buffer (error %d).\n", ret);
309 | buffer->release();
310 | return ret;
311 | }
312 | if ((ret = m_pBulkWritePipe->io(buffer, (uint32_t)buffer->getLength(), actLen, timeout)) != kIOReturnSuccess) {
313 | XYLog("Failed to write to bulk pipe (error %d)\n", ret);
314 | buffer->complete();
315 | buffer->release();
316 | return ret;
317 | }
318 | if ((ret = buffer->complete(kIODirectionOut)) != kIOReturnSuccess) {
319 | XYLog("Failed to complete bulk write memory buffer (error %d)\n", ret);
320 | buffer->release();
321 | return ret;
322 | }
323 | return ret;
324 | }
325 |
326 | const char* USBDeviceController::
327 | stringFromReturn(IOReturn code)
328 | {
329 | return m_pDevice->stringFromReturn(code);
330 | }
331 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/USBDeviceController.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // USBHCIController.hpp
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/5/21.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #ifndef USBDeviceController_hpp
10 | #define USBDeviceController_hpp
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "Hci.h"
21 |
22 | typedef struct {
23 | int status;
24 | uint32_t dataLen;
25 | } InterruptResp;
26 |
27 | class USBDeviceController : public OSObject {
28 | OSDeclareDefaultStructors(USBDeviceController)
29 |
30 | public:
31 |
32 | virtual bool init(IOService *client, IOUSBHostDevice *dev);
33 |
34 | virtual void free() override;
35 |
36 | virtual bool initConfiguration();
37 |
38 | virtual bool findInterface();
39 |
40 | virtual bool findPipes();
41 |
42 | IOReturn bulkPipeRead(void *buf, uint32_t buf_size, uint32_t *size, uint32_t timeout);
43 |
44 | IOReturn interruptPipeRead(void *buf, uint32_t buf_size, uint32_t *size, uint32_t timeout);
45 |
46 | IOReturn sendHCIRequest(HciCommandHdr *cmd, uint32_t timeout);
47 |
48 | IOReturn bulkWrite(const void *data, uint32_t length, uint32_t timeout);
49 |
50 | const char* stringFromReturn(IOReturn code);
51 |
52 | static void interruptHandler(void *owner, void *parameter, IOReturn status, uint32_t bytesTransferred);
53 |
54 | private:
55 | IOUSBHostDevice* m_pDevice;
56 | IOService* m_pClient;
57 | IOUSBHostInterface* m_pInterface;
58 |
59 | IOUSBHostPipe* m_pInterruptReadPipe;
60 | IOUSBHostPipe* m_pBulkWritePipe;
61 | IOUSBHostPipe* m_pBulkReadPipe;
62 |
63 | IOLock *_hciLock;
64 | IOBufferMemoryDescriptor* mReadBuffer;
65 | };
66 |
67 | #endif /* USBDeviceController_hpp */
68 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-0041.ddc:
--------------------------------------------------------------------------------
1 | () 0
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-0041.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0040-0041.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-1020.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-1020.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0040-1020.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-1050.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-1050.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0040-1050.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-2120.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-2120.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0040-2120.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-4150.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0040-4150.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0040-4150.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0041-0041.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0041-0041.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0041-0041.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-0041.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-0041.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0180-0041.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-1050.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-1050.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0180-1050.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-4150.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0180-4150.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0180-4150.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0291-0291.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0291-0291.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-0291-0291.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-0291-0291.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-0041.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-0041.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-1040-0041.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-1020.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-1020.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-1040-1020.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-1050.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-1050.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-1040-1050.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-2120.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-2120.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-1040-2120.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-4150.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-1040-4150.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-1040-4150.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-11-5.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-11-5.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-11-5.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-11-5.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-12-16.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-12-16.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-12-16.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-12-16.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-0-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-0-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-0-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-0-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-16-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-16-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-16-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-16-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-2.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-2.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-17-2.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-17-2.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-0-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-0-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-0-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-0-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-16-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-16-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-16-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-16-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-2.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-2.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-18-2.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-18-2.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-0.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-0.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-0.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-0.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-3.ddc:
--------------------------------------------------------------------------------
1 | ()
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-3.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-3.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-4.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-4.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-0-4.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-0-4.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-16-4.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-16-4.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-16-4.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-16-4.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-240-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-240-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-240-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-240-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-240-4.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-240-4.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-240-4.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-240-4.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-0.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-0.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-0.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-0.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-1.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-1.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-1.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-1.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-4.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-4.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-19-32-4.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-19-32-4.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-0-3.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-0-3.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-0-3.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-0-3.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-1-3.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-1-3.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-1-3.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-1-3.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-1-4.ddc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-1-4.ddc
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-20-1-4.sfi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-20-1-4.sfi
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.0.1.2d.d.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.0.1.2d.d.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.0.2.3.d.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.0.2.3.d.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.80.1.2d.d.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.80.1.2d.d.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.80.2.3.d.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.7.10-fw-1.80.2.3.d.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.7.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.7.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-1.10.2.27.d.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-1.10.2.27.d.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-1.10.3.11.e.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-1.10.3.11.e.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-22.50.19.14.f.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.8.10-fw-22.50.19.14.f.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/fw/ibt-hw-37.8.bseq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIntelWireless/IntelBluetoothFirmware/01cc1806d71f5cc64c464851b9f4811a3e7b4791/IntelBluetoothFirmware/fw/ibt-hw-37.8.bseq
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/linux.h:
--------------------------------------------------------------------------------
1 | //
2 | // linux.h
3 | // IntelBluetoothFirmware
4 | //
5 | // Created by qcwap on 2021/5/21.
6 | // Copyright © 2021 zxystd. All rights reserved.
7 | //
8 |
9 | #ifndef linux_h
10 | #define linux_h
11 |
12 | #include
13 | #include
14 |
15 | typedef UInt8 u8;
16 | typedef UInt16 u16;
17 | typedef UInt32 u32;
18 | typedef UInt64 u64;
19 |
20 | typedef u8 __u8;
21 | typedef u16 __u16;
22 | typedef u32 __u32;
23 | typedef u64 __u64;
24 |
25 | typedef __u16 __le16;
26 | typedef __u32 __le32;
27 | typedef __u64 __le64;
28 |
29 | typedef SInt8 s8;
30 | typedef SInt16 s16;
31 | typedef SInt32 s32;
32 | typedef SInt64 s64;
33 |
34 | typedef s8 __s8;
35 | typedef s16 __s16;
36 | typedef s32 __s32;
37 | typedef s64 __s64;
38 |
39 | #define __force
40 |
41 | static inline __u32 __le32_to_cpup(const __le32 *p)
42 | {
43 | return (__force __u32)*p;
44 | }
45 |
46 | static inline __u16 __le16_to_cpup(const __le16 *p)
47 | {
48 | return (__force __u16)*p;
49 | }
50 |
51 | #define le32_to_cpup __le32_to_cpup
52 | #define le16_to_cpup __le16_to_cpup
53 |
54 | static inline u32 get_unaligned_le32(const void *p)
55 | {
56 | return le32_to_cpup((__le32 *)p);
57 | }
58 |
59 | static inline u32 get_unaligned_le16(const void *p)
60 | {
61 | return le16_to_cpup((__le16 *)p);
62 | }
63 |
64 | #endif /* linux_h */
65 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/zutil.c:
--------------------------------------------------------------------------------
1 | //
2 | // zutil.c
3 | // itlwm
4 | //
5 | // Created by qcwap on 2020/9/4.
6 | // Copyright © 2020 钟先耀. All rights reserved.
7 | //
8 |
9 | #include
10 | extern "C" {
11 | typedef struct z_mem
12 | {
13 | UInt32 alloc_size;
14 | UInt8 data[0];
15 | } z_mem;
16 |
17 | void *zcalloc(void *opaque, uint items, uint size)
18 | {
19 | void* result = NULL;
20 | z_mem* zmem = NULL;
21 | UInt32 allocSize = items * size + sizeof(zmem);
22 |
23 | zmem = (z_mem*)IOMalloc(allocSize);
24 |
25 | if (zmem)
26 | {
27 | zmem->alloc_size = allocSize;
28 | result = (void*)&(zmem->data);
29 | }
30 |
31 | return result;
32 | }
33 |
34 | void zcfree(void *opaque, void *ptr)
35 | {
36 | UInt32* skipper = (UInt32 *)ptr - 1;
37 | z_mem* zmem = (z_mem*)skipper;
38 | IOFree((void*)zmem, zmem->alloc_size);
39 | }
40 | }
41 |
42 | int _stop(struct kmod_info*, void*) {
43 | IOLog("_stop(struct kmod_info*, void*) has been invoked\n");
44 | return 0;
45 | };
46 | int _start(struct kmod_info*, void*) {
47 | IOLog("_start(struct kmod_info*, void*) has been invoked\n");
48 | return 0;
49 | };
50 |
--------------------------------------------------------------------------------
/IntelBluetoothFirmware/zutil.h:
--------------------------------------------------------------------------------
1 | //
2 | // zutil.h
3 | // itlwm
4 | //
5 | // Created by qcwap on 2020/9/4.
6 | // Copyright © 2020 钟先耀. All rights reserved.
7 | //
8 |
9 | #ifndef zutil_h
10 | #define zutil_h
11 |
12 | #include
13 | #include
14 |
15 | extern "C" {
16 | void *zcalloc(void *opaque, uint items, uint size);
17 |
18 | void zcfree(void *opaque, void *ptr);
19 | }
20 |
21 | #endif /* zutil_h */
22 |
--------------------------------------------------------------------------------
/IntelBluetoothInjector/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleIdentifier
8 | $(PRODUCT_BUNDLE_IDENTIFIER)
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundleName
12 | $(PRODUCT_NAME)
13 | CFBundlePackageType
14 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
15 | CFBundleShortVersionString
16 | $(MODULE_VERSION)
17 | CFBundleVersion
18 | $(MODULE_VERSION)
19 | IOKitPersonalities
20 |
21 | 0026
22 |
23 | CFBundleIdentifier
24 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
25 | IOClass
26 | BroadcomBluetoothHostControllerUSBTransport
27 | IOProbeScore
28 | 3000
29 | IOProviderClass
30 | IOUSBHostDevice
31 | idProduct
32 | 38
33 | idVendor
34 | 32903
35 |
36 | 0032
37 |
38 | CFBundleIdentifier
39 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
40 | IOClass
41 | BroadcomBluetoothHostControllerUSBTransport
42 | IOProbeScore
43 | 3000
44 | IOProviderClass
45 | IOUSBHostDevice
46 | idProduct
47 | 50
48 | idVendor
49 | 32903
50 |
51 | 0035
52 |
53 | CFBundleIdentifier
54 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
55 | IOClass
56 | BroadcomBluetoothHostControllerUSBTransport
57 | IOProbeScore
58 | 3000
59 | IOProviderClass
60 | IOUSBHostDevice
61 | idProduct
62 | 53
63 | idVendor
64 | 32903
65 |
66 | 0036
67 |
68 | CFBundleIdentifier
69 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
70 | IOClass
71 | BroadcomBluetoothHostControllerUSBTransport
72 | IOProbeScore
73 | 3000
74 | IOProviderClass
75 | IOUSBHostDevice
76 | idProduct
77 | 54
78 | idVendor
79 | 32903
80 |
81 | 0038
82 |
83 | CFBundleIdentifier
84 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
85 | IOClass
86 | BroadcomBluetoothHostControllerUSBTransport
87 | IOProbeScore
88 | 3000
89 | IOProviderClass
90 | IOUSBHostDevice
91 | idProduct
92 | 56
93 | idVendor
94 | 32903
95 |
96 | 3165ac
97 |
98 | CFBundleIdentifier
99 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
100 | IOClass
101 | BroadcomBluetoothHostControllerUSBTransport
102 | IOProbeScore
103 | 3000
104 | IOProviderClass
105 | IOUSBHostDevice
106 | idProduct
107 | 2602
108 | idVendor
109 | 32903
110 |
111 | 3168
112 |
113 | CFBundleIdentifier
114 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
115 | IOClass
116 | BroadcomBluetoothHostControllerUSBTransport
117 | IOProbeScore
118 | 3000
119 | IOProviderClass
120 | IOUSBHostDevice
121 | idProduct
122 | 2727
123 | idVendor
124 | 32903
125 |
126 | 726x
127 |
128 | CFBundleIdentifier
129 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
130 | IOClass
131 | BroadcomBluetoothHostControllerUSBTransport
132 | IOProbeScore
133 | 3000
134 | IOProviderClass
135 | IOUSBHostDevice
136 | idProduct
137 | 2012
138 | idVendor
139 | 32903
140 |
141 | 8265
142 |
143 | CFBundleIdentifier
144 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
145 | IOClass
146 | BroadcomBluetoothHostControllerUSBTransport
147 | IOProbeScore
148 | 3000
149 | IOProviderClass
150 | IOUSBHostDevice
151 | idProduct
152 | 2603
153 | idVendor
154 | 32903
155 |
156 | 926x
157 |
158 | CFBundleIdentifier
159 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
160 | IOClass
161 | BroadcomBluetoothHostControllerUSBTransport
162 | IOProbeScore
163 | 3000
164 | IOProviderClass
165 | IOUSBHostDevice
166 | idProduct
167 | 37
168 | idVendor
169 | 32903
170 |
171 | 9560
172 |
173 | CFBundleIdentifier
174 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
175 | IOClass
176 | BroadcomBluetoothHostControllerUSBTransport
177 | IOProbeScore
178 | 3000
179 | IOProviderClass
180 | IOUSBHostDevice
181 | idProduct
182 | 2730
183 | idVendor
184 | 32903
185 |
186 | ax200
187 |
188 | CFBundleIdentifier
189 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
190 | IOClass
191 | BroadcomBluetoothHostControllerUSBTransport
192 | IOProbeScore
193 | 3000
194 | IOProviderClass
195 | IOUSBHostDevice
196 | idProduct
197 | 41
198 | idVendor
199 | 32903
200 |
201 | ax210
202 |
203 | CFBundleIdentifier
204 | com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
205 | IOClass
206 | BroadcomBluetoothHostControllerUSBTransport
207 | IOProbeScore
208 | 3000
209 | IOProviderClass
210 | IOUSBHostDevice
211 | idProduct
212 | 51
213 | idVendor
214 | 32903
215 |
216 | csr
217 |
218 | CFBundleIdentifier
219 | com.apple.iokit.CSRBluetoothHostControllerUSBTransport
220 | IOClass
221 | CSRBluetoothHostControllerUSBTransport
222 | IOProbeScore
223 | 3000
224 | IOProviderClass
225 | IOUSBHostDevice
226 | idProduct
227 | 2010
228 | idVendor
229 | 32903
230 |
231 |
232 | NSHumanReadableCopyright
233 | Copyright © 2020 钟先耀. All rights reserved.
234 | OSBundleRequired
235 | Root
236 |
237 |
238 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IntelBluetoothFirmware
2 |
3 | 
4 |
5 | - **English**
6 | - [简体中文](/.github/README-zh_Hans.md)
7 |
8 | ## Intro
9 |
10 | IntelBluetoothFirmware is a Kernel Extension that uploads Intel Wireless Bluetooth Firmware to provide native Bluetooth in macOS.
11 | The firmware binary files are from the Linux Open Source Project.
12 |
13 | After several months of public testing, it appears that the Kext is working well and stable.
14 |
15 | [](https://gitter.im/OpenIntelWireless/IntelBluetoothFirmware?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
16 |
17 | ## Documentation
18 |
19 | **Please read the docs carefully before using the Kernel Extensions or submitting an Issue Report!**
20 |
21 | - [Supported Devices](https://openintelwireless.github.io/IntelBluetoothFirmware/Compat.html)
22 | - [Installation](https://openintelwireless.github.io/IntelBluetoothFirmware/Installation.html)
23 | - [Frequently Asked Questions](https://openintelwireless.github.io/IntelBluetoothFirmware/FAQ.html)
24 | - [Troubleshooting](https://openintelwireless.github.io/IntelBluetoothFirmware/Troubleshooting.html)
25 |
26 | ## Credits
27 |
28 | - [torvalds/linux](https://github.com/torvalds/linux)
29 | - [acidanthera/BrcmPatchRAM](https://github.com/acidanthera/BrcmPatchRAM)
30 |
--------------------------------------------------------------------------------
/iwlwifi-firmware-license:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019, Intel Corporation.
2 | All rights reserved.
3 |
4 | Redistribution. Redistribution and use in binary form, without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions must reproduce the above copyright notice and the
9 | following disclaimer in the documentation and/or other materials
10 | provided with the distribution.
11 | * Neither the name of Intel Corporation nor the names of its suppliers
12 | may be used to endorse or promote products derived from this software
13 | without specific prior written permission.
14 | * No reverse engineering, decompilation, or disassembly of this software
15 | is permitted.
16 |
17 | Limited patent license. Intel Corporation grants a world-wide,
18 | royalty-free, non-exclusive license under patents it now or hereafter
19 | owns or controls to make, have made, use, import, offer to sell and
20 | sell ("Utilize") this software, but solely to the extent that any
21 | such patent is necessary to Utilize the software alone, or in
22 | combination with an operating system licensed under an approved Open
23 | Source license as listed by the Open Source Initiative at
24 | http://opensource.org/licenses. The patent license shall not apply to
25 | any other combinations which include this software. No hardware per
26 | se is licensed hereunder.
27 |
28 | DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
30 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
35 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39 | DAMAGE.
40 |
--------------------------------------------------------------------------------
/scripts/fw_gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # fw_gen.sh
4 | # itlwm
5 | #
6 | # Created by qcwap on 2020/3/10.
7 | # Copyright © 2020 钟先耀. All rights reserved.
8 | target_file="${PROJECT_DIR}/include/FwBinary.cpp"
9 | if [ -f "$target_file" ]; then
10 | exit 0
11 | fi
12 | while [ $# -gt 0 ];
13 | do
14 | case $1 in
15 | -P) fw_files=$2
16 | shift
17 | ;;
18 |
19 | esac
20 | shift
21 | done
22 |
23 | script_file="${PROJECT_DIR}/scripts/"
24 | python3 -c 'import sys;sys.path.append("'$script_file'");from zlib_compress_fw import *;process_files("'${target_file}'", "'$fw_files'")'
25 |
--------------------------------------------------------------------------------
/scripts/zlib_compress_fw.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- coding: utf-8 -*-
3 | # zlib_compress_fw.py
4 | #
5 | # Created by qcwap on 2020/9/3.
6 | # Copyright © 2020 钟先耀. All rights reserved.
7 |
8 | import zlib
9 | import os
10 | import struct
11 | import hashlib
12 |
13 | copyright = '''
14 | // itlwm
15 | //
16 | // Copyright © 2020 钟先耀. All rights reserved.
17 | #include "FwData.h"
18 | '''
19 |
20 | def compress(data):
21 | return zlib.compress(data)
22 |
23 | def hash(data):
24 | sha1sum = hashlib.sha1()
25 | sha1sum.update(data)
26 | return sha1sum.hexdigest()
27 |
28 | def format_file_name(file_name):
29 | return file_name.replace(".", "_").replace("-", "_")
30 |
31 | def format_var_name(hash):
32 | return "firmware_" + hash
33 |
34 | def write_single_file(target_file, path, file, file_hash):
35 | src_file = open(path, "rb")
36 | src_data = src_file.read()
37 | src_hash = hash(src_data)
38 | fw_var_name = format_file_name(file)
39 | data_var_name = format_var_name(src_hash)
40 |
41 | if src_hash not in file_hash:
42 | file_hash.append(src_hash)
43 | src_data = compress(src_data)
44 | src_len = len(src_data)
45 | target_file.write("\nconst unsigned char ")
46 | target_file.write(data_var_name)
47 | target_file.write("[] = {")
48 | index = 0;
49 | block = []
50 | while True:
51 | if index + 16 >= src_len:
52 | block = src_data[index:]
53 | else:
54 | block = src_data[index:index + 16]
55 | index += 16;
56 | if len(block) < 16:
57 | if len(block):
58 | for b in block:
59 | if type(b) is str:
60 | b = ord(b)
61 | target_file.write("0x{:02X}, ".format(b))
62 | target_file.write("\n")
63 | break
64 | target_file.write("0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, "
65 | "0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, "
66 | "0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, "
67 | "0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X},\n"
68 | .format(*struct.unpack("BBBBBBBBBBBBBBBB", block)))
69 | target_file.write("};\n")
70 |
71 | target_file.write("\nconst unsigned char *")
72 | target_file.write(fw_var_name)
73 | target_file.write(" = ")
74 | target_file.write(data_var_name)
75 | target_file.write(";\n")
76 | target_file.write("const long int ")
77 | target_file.write(fw_var_name)
78 | target_file.write("_size = sizeof(")
79 | target_file.write(data_var_name)
80 | target_file.write(");\n")
81 | src_file.close()
82 |
83 |
84 | def process_files(target_file, dir):
85 | if not os.path.exists(target_file):
86 | if not os.path.exists(os.path.dirname(target_file)):
87 | os.mkdirs(os.path.dirname(target_file))
88 | target_file_handle = open(target_file, "w")
89 | target_file_handle.write(copyright)
90 | for root, dirs, files in os.walk(dir):
91 | file_hash=[]
92 | for file in files:
93 | path = os.path.join(root, file)
94 | write_single_file(target_file_handle, path, file, file_hash)
95 |
96 | target_file_handle.write("\n")
97 | target_file_handle.write("const struct FwDesc fwList[] = {")
98 |
99 | for file in files:
100 | target_file_handle.write('{IBT_FW("')
101 | target_file_handle.write(file)
102 | target_file_handle.write('", ')
103 | fw_var_name = format_file_name(file)
104 | target_file_handle.write(fw_var_name)
105 | target_file_handle.write(", ")
106 | target_file_handle.write(fw_var_name)
107 | target_file_handle.write("_size)},\n")
108 |
109 | target_file_handle.write("};\n")
110 | target_file_handle.write("const int fwNumber = ")
111 | target_file_handle.write(str(len(files)))
112 | target_file_handle.write(";\n")
113 |
114 | target_file_handle.close()
115 |
116 | if __name__ == '__main__':
117 | print(compress("test"));
118 |
--------------------------------------------------------------------------------