dummy numbers sent
This commit is contained in:
parent
f68036fbf4
commit
e7d811bd51
9
lib/ArduinoBLE/.codespellrc
Normal file
9
lib/ArduinoBLE/.codespellrc
Normal file
@ -0,0 +1,9 @@
|
||||
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc
|
||||
# See: https://github.com/codespell-project/codespell#using-a-config-file
|
||||
[codespell]
|
||||
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
|
||||
ignore-words-list = ,
|
||||
skip = ./.git,./.licenses,__pycache__,node_modules,./go.mod,./go.sum,./package-lock.json,./poetry.lock,./yarn.lock,./extras/test
|
||||
builtin = clear,informal,en-GB_to_en-US
|
||||
check-filenames =
|
||||
check-hidden =
|
13
lib/ArduinoBLE/.github/dependabot.yml
vendored
Normal file
13
lib/ArduinoBLE/.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# See: https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates#about-the-dependabotyml-file
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
# Configure check for outdated GitHub Actions actions in workflows.
|
||||
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/dependabot/README.md
|
||||
# See: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-actions-up-to-date-with-dependabot
|
||||
- package-ecosystem: github-actions
|
||||
directory: / # Check the repository's workflows under /.github/workflows/
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
- "topic: infrastructure"
|
115
lib/ArduinoBLE/.github/workflows/compile-examples.yml
vendored
Normal file
115
lib/ArduinoBLE/.github/workflows/compile-examples.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
name: Compile Examples
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/compile-examples.yml"
|
||||
- "examples/**"
|
||||
- "src/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/compile-examples.yml"
|
||||
- "examples/**"
|
||||
- "src/**"
|
||||
schedule:
|
||||
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
|
||||
- cron: "0 8 * * TUE"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.board.fqbn }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
SKETCHES_REPORTS_PATH: sketches-reports
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
board:
|
||||
- fqbn: arduino:samd:mkrwifi1010
|
||||
platforms: |
|
||||
- name: arduino:samd
|
||||
artifact-name-suffix: arduino-samd-mkrwifi1010
|
||||
- fqbn: arduino:samd:nano_33_iot
|
||||
platforms: |
|
||||
- name: arduino:samd
|
||||
artifact-name-suffix: arduino-samd-nano_33_iot
|
||||
- fqbn: arduino:megaavr:uno2018:mode=on
|
||||
platforms: |
|
||||
- name: arduino:megaavr
|
||||
artifact-name-suffix: arduino-megaavr-uno2018
|
||||
- fqbn: arduino:mbed_nano:nano33ble
|
||||
platforms: |
|
||||
- name: arduino:mbed_nano
|
||||
artifact-name-suffix: arduino-mbed_nano-nano33ble
|
||||
- fqbn: arduino:mbed_nano:nanorp2040connect
|
||||
platforms: |
|
||||
- name: arduino:mbed_nano
|
||||
artifact-name-suffix: arduino-mbed_nano-nanorp2040connect
|
||||
- fqbn: arduino:renesas_uno:unor4wifi
|
||||
platforms: |
|
||||
- name: arduino:renesas_uno
|
||||
artifact-name-suffix: arduino-renesas_uno-unor4wifi
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Compile examples
|
||||
uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fqbn: ${{ matrix.board.fqbn }}
|
||||
platforms: ${{ matrix.board.platforms }}
|
||||
libraries: |
|
||||
# Install the library from the local path.
|
||||
- source-path: ./
|
||||
sketch-paths: |
|
||||
- examples
|
||||
enable-deltas-report: true
|
||||
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
|
||||
- name: Save sketches report as workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
name: sketches-report-${{ matrix.board.artifact-name-suffix }}
|
||||
|
||||
build-for-esp32:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
fqbn:
|
||||
- esp32:esp32:esp32
|
||||
- esp32:esp32:esp32s3
|
||||
- esp32:esp32:esp32c3
|
||||
- esp32:esp32:esp32c6
|
||||
- esp32:esp32:esp32h2
|
||||
# Not supported out of the box by ESP32 Arduino core
|
||||
#- esp32:esp32:esp32c2
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fqbn: ${{ matrix.fqbn }}
|
||||
platforms: |
|
||||
- name: esp32:esp32
|
||||
source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
sketch-paths: |
|
||||
- examples/Central/Scan
|
||||
- examples/Central/PeripheralExplorer
|
||||
- examples/Central/ScanCallback
|
||||
- examples/Central/SensorTagButton
|
||||
- examples/Peripheral/Advertising/EnhancedAdvertising
|
||||
- examples/Peripheral/Advertising/RawDataAdvertising
|
||||
cli-compile-flags: |
|
||||
- --warnings="none"
|
24
lib/ArduinoBLE/.github/workflows/report-size-deltas.yml
vendored
Normal file
24
lib/ArduinoBLE/.github/workflows/report-size-deltas.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Report Size Deltas
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/report-size-deltas.yml"
|
||||
schedule:
|
||||
# Run at the minimum interval allowed by GitHub Actions.
|
||||
# Note: GitHub Actions periodically has outages which result in workflow failures.
|
||||
# In this event, the workflows will start passing again once the service recovers.
|
||||
- cron: "*/5 * * * *"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
report:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment size deltas reports to PRs
|
||||
uses: arduino/report-size-deltas@v1
|
||||
with:
|
||||
# Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow
|
||||
sketches-reports-source: ^sketches-report-.+
|
25
lib/ArduinoBLE/.github/workflows/spell-check.yml
vendored
Normal file
25
lib/ArduinoBLE/.github/workflows/spell-check.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Source: https://github.com/per1234/.github/blob/main/workflow-templates/spell-check.md
|
||||
name: Spell Check
|
||||
|
||||
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
# Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates.
|
||||
- cron: "0 8 * * TUE"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spell check
|
||||
uses: codespell-project/actions-codespell@v2
|
138
lib/ArduinoBLE/.github/workflows/sync-labels.yml
vendored
Normal file
138
lib/ArduinoBLE/.github/workflows/sync-labels.yml
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
|
||||
name: Sync Labels
|
||||
|
||||
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/sync-labels.ya?ml"
|
||||
- ".github/label-configuration-files/*.ya?ml"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/sync-labels.ya?ml"
|
||||
- ".github/label-configuration-files/*.ya?ml"
|
||||
schedule:
|
||||
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
env:
|
||||
CONFIGURATIONS_FOLDER: .github/label-configuration-files
|
||||
CONFIGURATIONS_ARTIFACT: label-configuration-files
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download JSON schema for labels configuration file
|
||||
id: download-schema
|
||||
uses: carlosperate/download-file-action@v2
|
||||
with:
|
||||
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
|
||||
location: ${{ runner.temp }}/label-configuration-schema
|
||||
|
||||
- name: Install JSON schema validator
|
||||
run: |
|
||||
sudo npm install \
|
||||
--global \
|
||||
ajv-cli \
|
||||
ajv-formats
|
||||
|
||||
- name: Validate local labels configuration
|
||||
run: |
|
||||
# See: https://github.com/ajv-validator/ajv-cli#readme
|
||||
ajv validate \
|
||||
--all-errors \
|
||||
-c ajv-formats \
|
||||
-s "${{ steps.download-schema.outputs.file-path }}" \
|
||||
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
|
||||
|
||||
download:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
filename:
|
||||
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
|
||||
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
|
||||
- universal.yml
|
||||
|
||||
steps:
|
||||
- name: Download
|
||||
uses: carlosperate/download-file-action@v2
|
||||
with:
|
||||
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
|
||||
|
||||
- name: Pass configuration files to next job via workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: |
|
||||
*.yaml
|
||||
*.yml
|
||||
if-no-files-found: error
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
|
||||
sync:
|
||||
needs: download
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set environment variables
|
||||
run: |
|
||||
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
|
||||
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Determine whether to dry run
|
||||
id: dry-run
|
||||
if: >
|
||||
github.event_name == 'pull_request' ||
|
||||
(
|
||||
(
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
) &&
|
||||
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
|
||||
)
|
||||
run: |
|
||||
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
|
||||
# configuration.
|
||||
echo "::set-output name=flag::--dry-run"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download configuration files artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
path: ${{ env.CONFIGURATIONS_FOLDER }}
|
||||
|
||||
- name: Remove unneeded artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
|
||||
- name: Merge label configuration files
|
||||
run: |
|
||||
# Merge all configuration files
|
||||
shopt -s extglob
|
||||
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
|
||||
|
||||
- name: Install github-label-sync
|
||||
run: sudo npm install --global github-label-sync
|
||||
|
||||
- name: Sync labels
|
||||
env:
|
||||
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# See: https://github.com/Financial-Times/github-label-sync
|
||||
github-label-sync \
|
||||
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
|
||||
${{ steps.dry-run.outputs.flag }} \
|
||||
${{ github.repository }}
|
58
lib/ArduinoBLE/.github/workflows/unit-tests.yml
vendored
Normal file
58
lib/ArduinoBLE/.github/workflows/unit-tests.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
name: Unit Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/unit-tests.yml"
|
||||
- 'extras/test/**'
|
||||
- 'src/**'
|
||||
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/unit-tests.yml"
|
||||
- 'extras/test/**'
|
||||
- 'src/**'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Run unit tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
COVERAGE_DATA_PATH: extras/coverage-data/coverage.info
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: arduino/cpp-test-action@main
|
||||
with:
|
||||
runtime-paths: |
|
||||
- extras/test/build/bin/TEST_TARGET_UUID
|
||||
- extras/test/build/bin/TEST_TARGET_DISC_DEVICE
|
||||
- extras/test/build/bin/TEST_TARGET_ADVERTISING_DATA
|
||||
coverage-exclude-paths: |
|
||||
- '*/extras/test/*'
|
||||
- '/usr/*'
|
||||
coverage-data-path: ${{ env.COVERAGE_DATA_PATH }}
|
||||
|
||||
# A token is used to avoid intermittent spurious job failures caused by rate limiting.
|
||||
- name: Set up Codecov upload token
|
||||
run: |
|
||||
if [[ "${{ github.repository }}" == "arduino-libraries/ArduinoBLE" ]]; then
|
||||
# In order to avoid uploads of data from forks, only use the token for runs in the parent repo.
|
||||
# Token is intentionally exposed.
|
||||
# See: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954
|
||||
CODECOV_TOKEN="8118de48-b2af-48b4-a66a-26026847bfc5"
|
||||
else
|
||||
# codecov/codecov-action does unauthenticated upload if empty string is passed via the `token` input.
|
||||
CODECOV_TOKEN=""
|
||||
fi
|
||||
echo "CODECOV_TOKEN=$CODECOV_TOKEN" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: "${{ env.COVERAGE_DATA_PATH }}"
|
||||
fail_ci_if_error: true
|
||||
token: ${{ env.CODECOV_TOKEN }}
|
2
lib/ArduinoBLE/.gitignore
vendored
Normal file
2
lib/ArduinoBLE/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
.DS_Store
|
1
lib/ArduinoBLE/.piopm
Normal file
1
lib/ArduinoBLE/.piopm
Normal file
@ -0,0 +1 @@
|
||||
{"type": "library", "name": "ArduinoBLE", "version": "1.4.1", "spec": {"owner": "arduino-libraries", "id": 5878, "name": "ArduinoBLE", "requirements": null, "uri": null}}
|
26
lib/ArduinoBLE/CHANGELOG
Normal file
26
lib/ArduinoBLE/CHANGELOG
Normal file
@ -0,0 +1,26 @@
|
||||
ArduinoBLE ?.?.? - ????.??.??
|
||||
|
||||
ArduinoBLE 1.1.2 - 2019.11.12
|
||||
|
||||
* cordio: switch to lower power when polling with timeout
|
||||
* Fixed issue with wrong types for disconnection event handling. Thanks @cparata
|
||||
|
||||
ArduinoBLE 1.1.1 - 2019.09.05
|
||||
|
||||
* [Cordio] Fixed crashing when BLE.begin() is not called
|
||||
* Fixed ACL RX packet fragmentation, affected devices that supported large MTUs
|
||||
* Fixed BLECharacteristic::readValue(...) triggering a read request after a notification/indication was received
|
||||
* Added support for case insensitive comparison of UUID or address string inputs
|
||||
* Added (optional) company ID argument to BLE.setManufacturerData(...). Thanks @konikoni428
|
||||
|
||||
ArduinoBLE 1.1.0 - 2019.08.27
|
||||
|
||||
* Added BLE Central support
|
||||
|
||||
ArduinoBLE 1.0.0 - 2019.07.31
|
||||
|
||||
* Added support for Arduino Nano 33 BLE boards
|
||||
|
||||
ArduinoBLE 0.1.2 and older
|
||||
|
||||
* Changes not recorded
|
504
lib/ArduinoBLE/LICENSE
Normal file
504
lib/ArduinoBLE/LICENSE
Normal file
@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
(This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.)
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random
|
||||
Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
35
lib/ArduinoBLE/README.md
Normal file
35
lib/ArduinoBLE/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# ArduinoBLE
|
||||
|
||||
[](https://github.com/arduino-libraries/ArduinoBLE/actions?workflow=Compile+Examples) [](https://github.com/arduino-libraries/ArduinoBLE/actions?workflow=Spell+Check)
|
||||
|
||||
Enables Bluetooth® Low Energy connectivity on the Arduino MKR WiFi 1010, Arduino UNO WiFi Rev2, Arduino Nano 33 IoT, Arduino Nano 33 BLE, Arduino Portenta H7, Arduino Giga R1 and Arduino UNO R4 WiFi.
|
||||
|
||||
This library supports creating a Bluetooth® Low Energy peripheral & central mode.
|
||||
|
||||
For the Arduino MKR WiFi 1010, Arduino UNO WiFi Rev2, and Arduino Nano 33 IoT boards, it requires the NINA module to be running [Arduino NINA-W102 firmware](https://github.com/arduino/nina-fw) v1.2.0 or later.
|
||||
|
||||
For the Arduino UNO R4 WiFi, it requires the ESP32-S3 module to be running [firmware](https://github.com/arduino/uno-r4-wifi-usb-bridge) v0.2.0 or later.
|
||||
|
||||
|
||||
For more information about this library please visit us at:
|
||||
https://www.arduino.cc/en/Reference/ArduinoBLE
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
```
|
128
lib/ArduinoBLE/examples/Central/LedControl/LedControl.ino
Normal file
128
lib/ArduinoBLE/examples/Central/LedControl/LedControl.ino
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
LED Control
|
||||
|
||||
This example scans for Bluetooth® Low Energy peripherals until one with the advertised service
|
||||
"19b10000-e8f2-537e-4f6c-d104768a1214" UUID is found. Once discovered and connected,
|
||||
it will remotely control the Bluetooth® Low Energy peripheral's LED, when the button is pressed or released.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
- Button with pull-up resistor connected to pin 2.
|
||||
|
||||
You can use it with another board that is compatible with this library and the
|
||||
Peripherals -> LED example.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
// variables for button
|
||||
const int buttonPin = 2;
|
||||
int oldButtonState = LOW;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// configure the button pin as input
|
||||
pinMode(buttonPin, INPUT);
|
||||
|
||||
// initialize the Bluetooth® Low Energy hardware
|
||||
BLE.begin();
|
||||
|
||||
Serial.println("Bluetooth® Low Energy Central - LED control");
|
||||
|
||||
// start scanning for peripherals
|
||||
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if a peripheral has been discovered
|
||||
BLEDevice peripheral = BLE.available();
|
||||
|
||||
if (peripheral) {
|
||||
// discovered a peripheral, print out address, local name, and advertised service
|
||||
Serial.print("Found ");
|
||||
Serial.print(peripheral.address());
|
||||
Serial.print(" '");
|
||||
Serial.print(peripheral.localName());
|
||||
Serial.print("' ");
|
||||
Serial.print(peripheral.advertisedServiceUuid());
|
||||
Serial.println();
|
||||
|
||||
if (peripheral.localName() != "LED") {
|
||||
return;
|
||||
}
|
||||
|
||||
// stop scanning
|
||||
BLE.stopScan();
|
||||
|
||||
controlLed(peripheral);
|
||||
|
||||
// peripheral disconnected, start scanning again
|
||||
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
|
||||
}
|
||||
}
|
||||
|
||||
void controlLed(BLEDevice peripheral) {
|
||||
// connect to the peripheral
|
||||
Serial.println("Connecting ...");
|
||||
|
||||
if (peripheral.connect()) {
|
||||
Serial.println("Connected");
|
||||
} else {
|
||||
Serial.println("Failed to connect!");
|
||||
return;
|
||||
}
|
||||
|
||||
// discover peripheral attributes
|
||||
Serial.println("Discovering attributes ...");
|
||||
if (peripheral.discoverAttributes()) {
|
||||
Serial.println("Attributes discovered");
|
||||
} else {
|
||||
Serial.println("Attribute discovery failed!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve the LED characteristic
|
||||
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
|
||||
|
||||
if (!ledCharacteristic) {
|
||||
Serial.println("Peripheral does not have LED characteristic!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
} else if (!ledCharacteristic.canWrite()) {
|
||||
Serial.println("Peripheral does not have a writable LED characteristic!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
while (peripheral.connected()) {
|
||||
// while the peripheral is connected
|
||||
|
||||
// read the button pin
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
|
||||
if (oldButtonState != buttonState) {
|
||||
// button changed
|
||||
oldButtonState = buttonState;
|
||||
|
||||
if (buttonState) {
|
||||
Serial.println("button pressed");
|
||||
|
||||
// button is pressed, write 0x01 to turn the LED on
|
||||
ledCharacteristic.writeValue((byte)0x01);
|
||||
} else {
|
||||
Serial.println("button released");
|
||||
|
||||
// button is released, write 0x00 to turn the LED off
|
||||
ledCharacteristic.writeValue((byte)0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Peripheral disconnected");
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
Peripheral Explorer
|
||||
|
||||
This example scans for Bluetooth® Low Energy peripherals until one with a particular name ("LED")
|
||||
is found. Then connects, and discovers + prints all the peripheral's attributes.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
You can use it with another board that is compatible with this library and the
|
||||
Peripherals -> LED example.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println("Bluetooth® Low Energy Central - Peripheral Explorer");
|
||||
|
||||
// start scanning for peripherals
|
||||
BLE.scan();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if a peripheral has been discovered
|
||||
BLEDevice peripheral = BLE.available();
|
||||
|
||||
if (peripheral) {
|
||||
// discovered a peripheral, print out address, local name, and advertised service
|
||||
Serial.print("Found ");
|
||||
Serial.print(peripheral.address());
|
||||
Serial.print(" '");
|
||||
Serial.print(peripheral.localName());
|
||||
Serial.print("' ");
|
||||
Serial.print(peripheral.advertisedServiceUuid());
|
||||
Serial.println();
|
||||
|
||||
// see if peripheral is a LED
|
||||
if (peripheral.localName() == "LED") {
|
||||
// stop scanning
|
||||
BLE.stopScan();
|
||||
|
||||
explorerPeripheral(peripheral);
|
||||
|
||||
// peripheral disconnected, we are done
|
||||
while (1) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void explorerPeripheral(BLEDevice peripheral) {
|
||||
// connect to the peripheral
|
||||
Serial.println("Connecting ...");
|
||||
|
||||
if (peripheral.connect()) {
|
||||
Serial.println("Connected");
|
||||
} else {
|
||||
Serial.println("Failed to connect!");
|
||||
return;
|
||||
}
|
||||
|
||||
// discover peripheral attributes
|
||||
Serial.println("Discovering attributes ...");
|
||||
if (peripheral.discoverAttributes()) {
|
||||
Serial.println("Attributes discovered");
|
||||
} else {
|
||||
Serial.println("Attribute discovery failed!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// read and print device name of peripheral
|
||||
Serial.println();
|
||||
Serial.print("Device name: ");
|
||||
Serial.println(peripheral.deviceName());
|
||||
Serial.print("Appearance: 0x");
|
||||
Serial.println(peripheral.appearance(), HEX);
|
||||
Serial.println();
|
||||
|
||||
// loop the services of the peripheral and explore each
|
||||
for (int i = 0; i < peripheral.serviceCount(); i++) {
|
||||
BLEService service = peripheral.service(i);
|
||||
|
||||
exploreService(service);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
// we are done exploring, disconnect
|
||||
Serial.println("Disconnecting ...");
|
||||
peripheral.disconnect();
|
||||
Serial.println("Disconnected");
|
||||
}
|
||||
|
||||
void exploreService(BLEService service) {
|
||||
// print the UUID of the service
|
||||
Serial.print("Service ");
|
||||
Serial.println(service.uuid());
|
||||
|
||||
// loop the characteristics of the service and explore each
|
||||
for (int i = 0; i < service.characteristicCount(); i++) {
|
||||
BLECharacteristic characteristic = service.characteristic(i);
|
||||
|
||||
exploreCharacteristic(characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
void exploreCharacteristic(BLECharacteristic characteristic) {
|
||||
// print the UUID and properties of the characteristic
|
||||
Serial.print("\tCharacteristic ");
|
||||
Serial.print(characteristic.uuid());
|
||||
Serial.print(", properties 0x");
|
||||
Serial.print(characteristic.properties(), HEX);
|
||||
|
||||
// check if the characteristic is readable
|
||||
if (characteristic.canRead()) {
|
||||
// read the characteristic value
|
||||
characteristic.read();
|
||||
|
||||
if (characteristic.valueLength() > 0) {
|
||||
// print out the value of the characteristic
|
||||
Serial.print(", value 0x");
|
||||
printData(characteristic.value(), characteristic.valueLength());
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// loop the descriptors of the characteristic and explore each
|
||||
for (int i = 0; i < characteristic.descriptorCount(); i++) {
|
||||
BLEDescriptor descriptor = characteristic.descriptor(i);
|
||||
|
||||
exploreDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
void exploreDescriptor(BLEDescriptor descriptor) {
|
||||
// print the UUID of the descriptor
|
||||
Serial.print("\t\tDescriptor ");
|
||||
Serial.print(descriptor.uuid());
|
||||
|
||||
// read the descriptor value
|
||||
descriptor.read();
|
||||
|
||||
// print out the value of the descriptor
|
||||
Serial.print(", value 0x");
|
||||
printData(descriptor.value(), descriptor.valueLength());
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printData(const unsigned char data[], int length) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
unsigned char b = data[i];
|
||||
|
||||
if (b < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
|
||||
Serial.print(b, HEX);
|
||||
}
|
||||
}
|
68
lib/ArduinoBLE/examples/Central/Scan/Scan.ino
Normal file
68
lib/ArduinoBLE/examples/Central/Scan/Scan.ino
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Scan
|
||||
|
||||
This example scans for Bluetooth® Low Energy peripherals and prints out their advertising details:
|
||||
address, local name, advertised service UUID's.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println("Bluetooth® Low Energy Central scan");
|
||||
|
||||
// start scanning for peripheral
|
||||
BLE.scan();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if a peripheral has been discovered
|
||||
BLEDevice peripheral = BLE.available();
|
||||
|
||||
if (peripheral) {
|
||||
// discovered a peripheral
|
||||
Serial.println("Discovered a peripheral");
|
||||
Serial.println("-----------------------");
|
||||
|
||||
// print address
|
||||
Serial.print("Address: ");
|
||||
Serial.println(peripheral.address());
|
||||
|
||||
// print the local name, if present
|
||||
if (peripheral.hasLocalName()) {
|
||||
Serial.print("Local Name: ");
|
||||
Serial.println(peripheral.localName());
|
||||
}
|
||||
|
||||
// print the advertised service UUIDs, if present
|
||||
if (peripheral.hasAdvertisedServiceUuid()) {
|
||||
Serial.print("Service UUIDs: ");
|
||||
for (int i = 0; i < peripheral.advertisedServiceUuidCount(); i++) {
|
||||
Serial.print(peripheral.advertisedServiceUuid(i));
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// print the RSSI
|
||||
Serial.print("RSSI: ");
|
||||
Serial.println(peripheral.rssi());
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Scan Callback
|
||||
|
||||
This example scans for Bluetooth® Low Energy peripherals and prints out their advertising details:
|
||||
address, local name, advertised service UUIDs. Unlike the Scan example, it uses
|
||||
the callback style APIs and disables filtering so the peripheral discovery is
|
||||
reported for every single advertisement it makes.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println("Bluetooth® Low Energy Central scan callback");
|
||||
|
||||
// set the discovered event handle
|
||||
BLE.setEventHandler(BLEDiscovered, bleCentralDiscoverHandler);
|
||||
|
||||
// start scanning for peripherals with duplicates
|
||||
BLE.scan(true);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// poll the central for events
|
||||
BLE.poll();
|
||||
}
|
||||
|
||||
void bleCentralDiscoverHandler(BLEDevice peripheral) {
|
||||
// discovered a peripheral
|
||||
Serial.println("Discovered a peripheral");
|
||||
Serial.println("-----------------------");
|
||||
|
||||
// print address
|
||||
Serial.print("Address: ");
|
||||
Serial.println(peripheral.address());
|
||||
|
||||
// print the local name, if present
|
||||
if (peripheral.hasLocalName()) {
|
||||
Serial.print("Local Name: ");
|
||||
Serial.println(peripheral.localName());
|
||||
}
|
||||
|
||||
// print the advertised service UUIDs, if present
|
||||
if (peripheral.hasAdvertisedServiceUuid()) {
|
||||
Serial.print("Service UUIDs: ");
|
||||
for (int i = 0; i < peripheral.advertisedServiceUuidCount(); i++) {
|
||||
Serial.print(peripheral.advertisedServiceUuid(i));
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// print the RSSI
|
||||
Serial.print("RSSI: ");
|
||||
Serial.println(peripheral.rssi());
|
||||
|
||||
Serial.println();
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
SensorTag Button
|
||||
|
||||
This example scans for Bluetooth® Low Energy peripherals until a TI SensorTag is discovered.
|
||||
It then connects to it, discovers the attributes of the 0xffe0 service,
|
||||
subscribes to the Simple Key Characteristic (UUID 0xffe1). When a button is
|
||||
pressed on the SensorTag a notification is received and the button state is
|
||||
outputted to the Serial Monitor when one is pressed.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
- TI SensorTag
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println("Bluetooth® Low Energy Central - SensorTag button");
|
||||
Serial.println("Make sure to turn on the device.");
|
||||
|
||||
// start scanning for peripheral
|
||||
BLE.scan();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if a peripheral has been discovered
|
||||
BLEDevice peripheral = BLE.available();
|
||||
|
||||
if (peripheral) {
|
||||
// discovered a peripheral, print out address, local name, and advertised service
|
||||
Serial.print("Found ");
|
||||
Serial.print(peripheral.address());
|
||||
Serial.print(" '");
|
||||
Serial.print(peripheral.localName());
|
||||
Serial.print("' ");
|
||||
Serial.print(peripheral.advertisedServiceUuid());
|
||||
Serial.println();
|
||||
|
||||
// Check if the peripheral is a SensorTag, the local name will be:
|
||||
// "CC2650 SensorTag"
|
||||
if (peripheral.localName() == "CC2650 SensorTag") {
|
||||
// stop scanning
|
||||
BLE.stopScan();
|
||||
|
||||
monitorSensorTagButtons(peripheral);
|
||||
|
||||
// peripheral disconnected, start scanning again
|
||||
BLE.scan();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void monitorSensorTagButtons(BLEDevice peripheral) {
|
||||
// connect to the peripheral
|
||||
Serial.println("Connecting ...");
|
||||
if (peripheral.connect()) {
|
||||
Serial.println("Connected");
|
||||
} else {
|
||||
Serial.println("Failed to connect!");
|
||||
return;
|
||||
}
|
||||
|
||||
// discover peripheral attributes
|
||||
Serial.println("Discovering service 0xffe0 ...");
|
||||
if (peripheral.discoverService("ffe0")) {
|
||||
Serial.println("Service discovered");
|
||||
} else {
|
||||
Serial.println("Attribute discovery failed.");
|
||||
peripheral.disconnect();
|
||||
|
||||
while (1);
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve the simple key characteristic
|
||||
BLECharacteristic simpleKeyCharacteristic = peripheral.characteristic("ffe1");
|
||||
|
||||
// subscribe to the simple key characteristic
|
||||
Serial.println("Subscribing to simple key characteristic ...");
|
||||
if (!simpleKeyCharacteristic) {
|
||||
Serial.println("no simple key characteristic found!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
} else if (!simpleKeyCharacteristic.canSubscribe()) {
|
||||
Serial.println("simple key characteristic is not subscribable!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
} else if (!simpleKeyCharacteristic.subscribe()) {
|
||||
Serial.println("subscription failed!");
|
||||
peripheral.disconnect();
|
||||
return;
|
||||
} else {
|
||||
Serial.println("Subscribed");
|
||||
Serial.println("Press the right and left buttons on your SensorTag.");
|
||||
}
|
||||
|
||||
while (peripheral.connected()) {
|
||||
// while the peripheral is connected
|
||||
|
||||
// check if the value of the simple key characteristic has been updated
|
||||
if (simpleKeyCharacteristic.valueUpdated()) {
|
||||
// yes, get the value, characteristic is 1 byte so use byte value
|
||||
byte value = 0;
|
||||
|
||||
simpleKeyCharacteristic.readValue(value);
|
||||
|
||||
if (value & 0x01) {
|
||||
// first bit corresponds to the right button
|
||||
Serial.println("Right button pressed");
|
||||
}
|
||||
|
||||
if (value & 0x02) {
|
||||
// second bit corresponds to the left button
|
||||
Serial.println("Left button pressed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("SensorTag disconnected!");
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
BLEService myService("fff0");
|
||||
BLEIntCharacteristic myCharacteristic("fff1", BLERead | BLEBroadcast);
|
||||
|
||||
// Advertising parameters should have a global scope. Do NOT define them in 'setup' or in 'loop'
|
||||
const uint8_t manufactData[4] = {0x01, 0x02, 0x03, 0x04};
|
||||
const uint8_t serviceData[3] = {0x00, 0x01, 0x02};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("failed to initialize BLE!");
|
||||
while (1);
|
||||
}
|
||||
|
||||
myService.addCharacteristic(myCharacteristic);
|
||||
BLE.addService(myService);
|
||||
|
||||
// Build scan response data packet
|
||||
BLEAdvertisingData scanData;
|
||||
// Set parameters for scan response packet
|
||||
scanData.setLocalName("Test enhanced advertising");
|
||||
// Copy set parameters in the actual scan response packet
|
||||
BLE.setScanResponseData(scanData);
|
||||
|
||||
// Build advertising data packet
|
||||
BLEAdvertisingData advData;
|
||||
// Set parameters for advertising packet
|
||||
advData.setManufacturerData(0x004C, manufactData, sizeof(manufactData));
|
||||
advData.setAdvertisedService(myService);
|
||||
advData.setAdvertisedServiceData(0xfff0, serviceData, sizeof(serviceData));
|
||||
// Copy set parameters in the actual advertising packet
|
||||
BLE.setAdvertisingData(advData);
|
||||
|
||||
BLE.advertise();
|
||||
Serial.println("advertising ...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
BLE.poll();
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
BLEService myService("fff0");
|
||||
BLEIntCharacteristic myCharacteristic("fff1", BLERead | BLEBroadcast);
|
||||
|
||||
// Advertising parameters should have a global scope. Do NOT define them in 'setup' or in 'loop'
|
||||
const uint8_t completeRawAdvertisingData[] = {0x02,0x01,0x06,0x09,0xff,0x01,0x01,0x00,0x01,0x02,0x03,0x04,0x05};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("failed to initialize BLE!");
|
||||
while (1);
|
||||
}
|
||||
|
||||
myService.addCharacteristic(myCharacteristic);
|
||||
BLE.addService(myService);
|
||||
|
||||
// Build advertising data packet
|
||||
BLEAdvertisingData advData;
|
||||
// If a packet has a raw data parameter, then all the other parameters of the packet will be ignored
|
||||
advData.setRawData(completeRawAdvertisingData, sizeof(completeRawAdvertisingData));
|
||||
// Copy set parameters in the actual advertising packet
|
||||
BLE.setAdvertisingData(advData);
|
||||
|
||||
// Build scan response data packet
|
||||
BLEAdvertisingData scanData;
|
||||
scanData.setLocalName("Test advertising raw data");
|
||||
// Copy set parameters in the actual scan response packet
|
||||
BLE.setScanResponseData(scanData);
|
||||
|
||||
BLE.advertise();
|
||||
|
||||
Serial.println("advertising ...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
BLE.poll();
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Battery Monitor
|
||||
|
||||
This example creates a Bluetooth® Low Energy peripheral with the standard battery service and
|
||||
level characteristic. The A0 pin is used to calculate the battery level.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
|
||||
nRF Connect (Android), to interact with the services and characteristics
|
||||
created in this sketch.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
// Bluetooth® Low Energy Battery Service
|
||||
BLEService batteryService("180F");
|
||||
|
||||
// Bluetooth® Low Energy Battery Level Characteristic
|
||||
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID
|
||||
BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
|
||||
|
||||
int oldBatteryLevel = 0; // last battery level reading from analog input
|
||||
long previousMillis = 0; // last time the battery level was checked, in ms
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600); // initialize serial communication
|
||||
while (!Serial);
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting BLE failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Set a local name for the Bluetooth® Low Energy device
|
||||
This name will appear in advertising packets
|
||||
and can be used by remote devices to identify this Bluetooth® Low Energy device
|
||||
The name can be changed but maybe be truncated based on space left in advertisement packet
|
||||
*/
|
||||
BLE.setLocalName("BatteryMonitor");
|
||||
BLE.setAdvertisedService(batteryService); // add the service UUID
|
||||
batteryService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
|
||||
BLE.addService(batteryService); // Add the battery service
|
||||
batteryLevelChar.writeValue(oldBatteryLevel); // set initial value for this characteristic
|
||||
|
||||
/* Start advertising Bluetooth® Low Energy. It will start continuously transmitting Bluetooth® Low Energy
|
||||
advertising packets and will be visible to remote Bluetooth® Low Energy central devices
|
||||
until it receives a new connection */
|
||||
|
||||
// start advertising
|
||||
BLE.advertise();
|
||||
|
||||
Serial.println("Bluetooth® device active, waiting for connections...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// wait for a Bluetooth® Low Energy central
|
||||
BLEDevice central = BLE.central();
|
||||
|
||||
// if a central is connected to the peripheral:
|
||||
if (central) {
|
||||
Serial.print("Connected to central: ");
|
||||
// print the central's BT address:
|
||||
Serial.println(central.address());
|
||||
// turn on the LED to indicate the connection:
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
||||
// check the battery level every 200 ms
|
||||
// while the central is connected:
|
||||
while (central.connected()) {
|
||||
long currentMillis = millis();
|
||||
// if 200 ms have passed, check the battery level:
|
||||
if (currentMillis - previousMillis >= 200) {
|
||||
previousMillis = currentMillis;
|
||||
updateBatteryLevel();
|
||||
}
|
||||
}
|
||||
// when the central disconnects, turn off the LED:
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
Serial.print("Disconnected from central: ");
|
||||
Serial.println(central.address());
|
||||
}
|
||||
}
|
||||
|
||||
void updateBatteryLevel() {
|
||||
/* Read the current voltage level on the A0 analog input pin.
|
||||
This is used here to simulate the charge level of a battery.
|
||||
*/
|
||||
int battery = analogRead(A0);
|
||||
int batteryLevel = map(battery, 0, 1023, 0, 100);
|
||||
|
||||
if (batteryLevel != oldBatteryLevel) { // if the battery level has changed
|
||||
Serial.print("Battery Level % is now: "); // print it
|
||||
Serial.println(batteryLevel);
|
||||
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
|
||||
oldBatteryLevel = batteryLevel; // save the level for next comparison
|
||||
}
|
||||
}
|
93
lib/ArduinoBLE/examples/Peripheral/ButtonLED/ButtonLED.ino
Normal file
93
lib/ArduinoBLE/examples/Peripheral/ButtonLED/ButtonLED.ino
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Button LED
|
||||
|
||||
This example creates a Bluetooth® Low Energy peripheral with service that contains a
|
||||
characteristic to control an LED and another characteristic that
|
||||
represents the state of the button.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
- Button connected to pin 4
|
||||
|
||||
You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
|
||||
nRF Connect (Android), to interact with the services and characteristics
|
||||
created in this sketch.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
const int ledPin = LED_BUILTIN; // set ledPin to on-board LED
|
||||
const int buttonPin = 4; // set buttonPin to digital pin 4
|
||||
|
||||
BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service
|
||||
|
||||
// create switch characteristic and allow remote device to read and write
|
||||
BLEByteCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
|
||||
// create button characteristic and allow remote device to get notifications
|
||||
BLEByteCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
pinMode(ledPin, OUTPUT); // use the LED as an output
|
||||
pinMode(buttonPin, INPUT); // use button pin as an input
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
// set the local name peripheral advertises
|
||||
BLE.setLocalName("ButtonLED");
|
||||
// set the UUID for the service this peripheral advertises:
|
||||
BLE.setAdvertisedService(ledService);
|
||||
|
||||
// add the characteristics to the service
|
||||
ledService.addCharacteristic(ledCharacteristic);
|
||||
ledService.addCharacteristic(buttonCharacteristic);
|
||||
|
||||
// add the service
|
||||
BLE.addService(ledService);
|
||||
|
||||
ledCharacteristic.writeValue(0);
|
||||
buttonCharacteristic.writeValue(0);
|
||||
|
||||
// start advertising
|
||||
BLE.advertise();
|
||||
|
||||
Serial.println("Bluetooth® device active, waiting for connections...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// poll for Bluetooth® Low Energy events
|
||||
BLE.poll();
|
||||
|
||||
// read the current button pin state
|
||||
char buttonValue = digitalRead(buttonPin);
|
||||
|
||||
// has the value changed since the last read
|
||||
bool buttonChanged = (buttonCharacteristic.value() != buttonValue);
|
||||
|
||||
if (buttonChanged) {
|
||||
// button state changed, update characteristics
|
||||
ledCharacteristic.writeValue(buttonValue);
|
||||
buttonCharacteristic.writeValue(buttonValue);
|
||||
}
|
||||
|
||||
if (ledCharacteristic.written() || buttonChanged) {
|
||||
// update LED, either central has written to characteristic or button state has changed
|
||||
if (ledCharacteristic.value()) {
|
||||
Serial.println("LED on");
|
||||
digitalWrite(ledPin, HIGH);
|
||||
} else {
|
||||
Serial.println("LED off");
|
||||
digitalWrite(ledPin, LOW);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Callback LED
|
||||
|
||||
This example creates a Bluetooth® Low Energy peripheral with service that contains a
|
||||
characteristic to control an LED. The callback features of the
|
||||
library are used.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
|
||||
nRF Connect (Android), to interact with the services and characteristics
|
||||
created in this sketch.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service
|
||||
|
||||
// create switch characteristic and allow remote device to read and write
|
||||
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
|
||||
|
||||
const int ledPin = LED_BUILTIN; // pin to use for the LED
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
pinMode(ledPin, OUTPUT); // use the LED pin as an output
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
// set the local name peripheral advertises
|
||||
BLE.setLocalName("LEDCallback");
|
||||
// set the UUID for the service this peripheral advertises
|
||||
BLE.setAdvertisedService(ledService);
|
||||
|
||||
// add the characteristic to the service
|
||||
ledService.addCharacteristic(switchCharacteristic);
|
||||
|
||||
// add service
|
||||
BLE.addService(ledService);
|
||||
|
||||
// assign event handlers for connected, disconnected to peripheral
|
||||
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
|
||||
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
|
||||
|
||||
// assign event handlers for characteristic
|
||||
switchCharacteristic.setEventHandler(BLEWritten, switchCharacteristicWritten);
|
||||
// set an initial value for the characteristic
|
||||
switchCharacteristic.setValue(0);
|
||||
|
||||
// start advertising
|
||||
BLE.advertise();
|
||||
|
||||
Serial.println(("Bluetooth® device active, waiting for connections..."));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// poll for Bluetooth® Low Energy events
|
||||
BLE.poll();
|
||||
}
|
||||
|
||||
void blePeripheralConnectHandler(BLEDevice central) {
|
||||
// central connected event handler
|
||||
Serial.print("Connected event, central: ");
|
||||
Serial.println(central.address());
|
||||
}
|
||||
|
||||
void blePeripheralDisconnectHandler(BLEDevice central) {
|
||||
// central disconnected event handler
|
||||
Serial.print("Disconnected event, central: ");
|
||||
Serial.println(central.address());
|
||||
}
|
||||
|
||||
void switchCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
|
||||
// central wrote new value to characteristic, update LED
|
||||
Serial.print("Characteristic event, written: ");
|
||||
|
||||
if (switchCharacteristic.value()) {
|
||||
Serial.println("LED on");
|
||||
digitalWrite(ledPin, HIGH);
|
||||
} else {
|
||||
Serial.println("LED off");
|
||||
digitalWrite(ledPin, LOW);
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
/*
|
||||
Battery Monitor
|
||||
|
||||
This example creates a BLE peripheral with the standard battery service and
|
||||
level characteristic. The A0 pin is used to calculate the battery level.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
You can use a generic BLE central app, like LightBlue (iOS and Android) or
|
||||
nRF Connect (Android), to interact with the services and characteristics
|
||||
created in this sketch.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
|
||||
#define PAIR_BUTTON 3 // button for pairing
|
||||
#define PAIR_LED 24 // LED used to signal pairing
|
||||
#define PAIR_LED_ON LOW // Blue LED on Nano BLE has inverted logic
|
||||
#define PAIR_INTERVAL 30000 // interval for pairing after button press in ms
|
||||
|
||||
#define CTRL_LED LED_BUILTIN
|
||||
|
||||
|
||||
// BLE Battery Service
|
||||
BLEService batteryService("180F");
|
||||
|
||||
// BLE Battery Level Characteristic
|
||||
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID
|
||||
BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
|
||||
BLEStringCharacteristic stringcharacteristic("183E", BLERead | BLEWrite, 31);
|
||||
|
||||
|
||||
// Add BLEEncryption tag to require pairing. This controls the LED.
|
||||
BLEUnsignedCharCharacteristic secretValue("2a3F", BLERead | BLEWrite | BLEEncryption);
|
||||
|
||||
int oldBatteryLevel = 0; // last battery level reading from analog input
|
||||
unsigned long previousMillis = 0; // last time the battery level was checked, in ms
|
||||
unsigned long pairingStarted = 0; // pairing start time when button is pressed
|
||||
bool wasConnected = 0;
|
||||
bool acceptOrReject = true;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600); // initialize serial communication
|
||||
while (!Serial);
|
||||
|
||||
pinMode(CTRL_LED, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
|
||||
pinMode(PAIR_LED, OUTPUT);
|
||||
pinMode(PAIR_BUTTON, INPUT_PULLUP);
|
||||
|
||||
|
||||
Serial.println("Serial connected");
|
||||
|
||||
// Callback function with confirmation code when new device is pairing.
|
||||
BLE.setDisplayCode([](uint32_t confirmCode){
|
||||
Serial.println("New device pairing request.");
|
||||
Serial.print("Confirm code matches pairing device: ");
|
||||
char code[6];
|
||||
sprintf(code, "%06d", confirmCode);
|
||||
Serial.println(code);
|
||||
});
|
||||
|
||||
// Callback to allow accepting or rejecting pairing
|
||||
BLE.setBinaryConfirmPairing([&acceptOrReject](){
|
||||
Serial.print("Should we confirm pairing? ");
|
||||
delay(5000);
|
||||
if(acceptOrReject){
|
||||
acceptOrReject = false;
|
||||
Serial.println("yes");
|
||||
return true;
|
||||
}else{
|
||||
acceptOrReject = true;
|
||||
Serial.println("no");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// IRKs are keys that identify the true owner of a random mac address.
|
||||
// Add IRKs of devices you are bonded with.
|
||||
BLE.setGetIRKs([](uint8_t* nIRKs, uint8_t** BDaddrTypes, uint8_t*** BDAddrs, uint8_t*** IRKs){
|
||||
// Set to number of devices
|
||||
*nIRKs = 2;
|
||||
|
||||
*BDAddrs = new uint8_t*[*nIRKs];
|
||||
*IRKs = new uint8_t*[*nIRKs];
|
||||
*BDaddrTypes = new uint8_t[*nIRKs];
|
||||
|
||||
// Set these to the mac and IRK for your bonded devices as printed in the serial console after bonding.
|
||||
uint8_t device1Mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t device1IRK[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t device2Mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t device2IRK[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
(*BDaddrTypes)[0] = 0; // Type 0 is for pubc address, type 1 is for static random
|
||||
(*BDAddrs)[0] = new uint8_t[6];
|
||||
(*IRKs)[0] = new uint8_t[16];
|
||||
memcpy((*IRKs)[0] , device1IRK,16);
|
||||
memcpy((*BDAddrs)[0], device1Mac, 6);
|
||||
|
||||
|
||||
(*BDaddrTypes)[1] = 0;
|
||||
(*BDAddrs)[1] = new uint8_t[6];
|
||||
(*IRKs)[1] = new uint8_t[16];
|
||||
memcpy((*IRKs)[1] , device2IRK,16);
|
||||
memcpy((*BDAddrs)[1], device2Mac, 6);
|
||||
|
||||
|
||||
return 1;
|
||||
});
|
||||
// The LTK is the secret key which is used to encrypt bluetooth traffic
|
||||
BLE.setGetLTK([](uint8_t* address, uint8_t* LTK){
|
||||
// address is input
|
||||
Serial.print("Received request for address: ");
|
||||
btct.printBytes(address,6);
|
||||
|
||||
// Set these to the MAC and LTK of your devices after bonding.
|
||||
uint8_t device1Mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t device1LTK[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t device2Mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t device2LTK[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
if(memcmp(device1Mac, address, 6) == 0) {
|
||||
memcpy(LTK, device1LTK, 16);
|
||||
return 1;
|
||||
}else if(memcmp(device2Mac, address, 6) == 0) {
|
||||
memcpy(LTK, device2LTK, 16);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
BLE.setStoreIRK([](uint8_t* address, uint8_t* IRK){
|
||||
Serial.print(F("New device with MAC : "));
|
||||
btct.printBytes(address,6);
|
||||
Serial.print(F("Need to store IRK : "));
|
||||
btct.printBytes(IRK,16);
|
||||
return 1;
|
||||
});
|
||||
BLE.setStoreLTK([](uint8_t* address, uint8_t* LTK){
|
||||
Serial.print(F("New device with MAC : "));
|
||||
btct.printBytes(address,6);
|
||||
Serial.print(F("Need to store LTK : "));
|
||||
btct.printBytes(LTK,16);
|
||||
return 1;
|
||||
});
|
||||
|
||||
while(1){
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting BLE failed!");
|
||||
delay(200);
|
||||
continue;
|
||||
}
|
||||
Serial.println("BT init");
|
||||
delay(200);
|
||||
|
||||
/* Set a local name for the BLE device
|
||||
This name will appear in advertising packets
|
||||
and can be used by remote devices to identify this BLE device
|
||||
The name can be changed but maybe be truncated based on space left in advertisement packet
|
||||
*/
|
||||
|
||||
BLE.setDeviceName("Arduino");
|
||||
BLE.setLocalName("BatteryMonitor");
|
||||
|
||||
BLE.setAdvertisedService(batteryService); // add the service UUID
|
||||
batteryService.addCharacteristic(batteryLevelChar); // add the battery level characteristic
|
||||
batteryService.addCharacteristic(stringcharacteristic);
|
||||
batteryService.addCharacteristic(secretValue);
|
||||
|
||||
BLE.addService(batteryService); // Add the battery service
|
||||
batteryLevelChar.writeValue(oldBatteryLevel); // set initial value for this characteristic
|
||||
char* stringCharValue = new char[32];
|
||||
stringCharValue = "string";
|
||||
stringcharacteristic.writeValue(stringCharValue);
|
||||
secretValue.writeValue(0);
|
||||
|
||||
delay(1000);
|
||||
|
||||
// prevent pairing until button is pressed (will show a pairing rejected message)
|
||||
BLE.setPairable(false);
|
||||
|
||||
/* Start advertising BLE. It will start continuously transmitting BLE
|
||||
advertising packets and will be visible to remote BLE central devices
|
||||
until it receives a new connection */
|
||||
|
||||
// start advertising
|
||||
if(!BLE.advertise()){
|
||||
Serial.println("failed to advertise bluetooth.");
|
||||
BLE.stopAdvertise();
|
||||
delay(500);
|
||||
}else{
|
||||
Serial.println("advertising...");
|
||||
break;
|
||||
}
|
||||
BLE.end();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
// wait for a BLE central
|
||||
BLEDevice central = BLE.central();
|
||||
|
||||
|
||||
// If button is pressed, allow pairing for 30 sec
|
||||
if (!BLE.pairable() && digitalRead(PAIR_BUTTON) == LOW){
|
||||
pairingStarted = millis();
|
||||
BLE.setPairable(Pairable::ONCE);
|
||||
Serial.println("Accepting pairing for 30 s");
|
||||
} else if (BLE.pairable() && millis() > pairingStarted + PAIR_INTERVAL){
|
||||
BLE.setPairable(false);
|
||||
Serial.println("No longer accepting pairing");
|
||||
}
|
||||
// Make LED blink while pairing is allowed
|
||||
digitalWrite(PAIR_LED, (BLE.pairable() ? (millis()%400)<200 : BLE.paired()) ? PAIR_LED_ON : !PAIR_LED_ON);
|
||||
|
||||
|
||||
// if a central is connected to the peripheral:
|
||||
if (central && central.connected()) {
|
||||
if (!wasConnected){
|
||||
wasConnected = true;
|
||||
Serial.print("Connected to central: ");
|
||||
// print the central's BT address:
|
||||
Serial.println(central.address());
|
||||
}
|
||||
|
||||
// check the battery level every 200ms
|
||||
// while the central is connected:
|
||||
long currentMillis = millis();
|
||||
// if 200ms have passed, check the battery level:
|
||||
if (currentMillis - previousMillis >= 1000) {
|
||||
previousMillis = currentMillis;
|
||||
updateBatteryLevel();
|
||||
digitalWrite(CTRL_LED, secretValue.value()>0 ? HIGH : LOW);
|
||||
}
|
||||
} else if (wasConnected){
|
||||
wasConnected = false;
|
||||
Serial.print("Disconnected from central: ");
|
||||
Serial.println(central.address());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void updateBatteryLevel() {
|
||||
/* Read the current voltage level on the A0 analog input pin.
|
||||
This is used here to simulate the charge level of a battery.
|
||||
*/
|
||||
int battery = analogRead(A0);
|
||||
int batteryLevel = map(battery, 0, 1023, 0, 100);
|
||||
|
||||
if (batteryLevel != oldBatteryLevel) { // if the battery level has changed
|
||||
// Serial.print("Battery Level % is now: "); // print it
|
||||
// Serial.println(batteryLevel);
|
||||
batteryLevelChar.writeValue(batteryLevel); // and update the battery level characteristic
|
||||
oldBatteryLevel = batteryLevel; // save the level for next comparison
|
||||
}
|
||||
}
|
89
lib/ArduinoBLE/examples/Peripheral/LED/LED.ino
Normal file
89
lib/ArduinoBLE/examples/Peripheral/LED/LED.ino
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
LED
|
||||
|
||||
This example creates a Bluetooth® Low Energy peripheral with service that contains a
|
||||
characteristic to control an LED.
|
||||
|
||||
The circuit:
|
||||
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
|
||||
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
|
||||
|
||||
You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
|
||||
nRF Connect (Android), to interact with the services and characteristics
|
||||
created in this sketch.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // Bluetooth® Low Energy LED Service
|
||||
|
||||
// Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
|
||||
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
|
||||
|
||||
const int ledPin = LED_BUILTIN; // pin to use for the LED
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// set LED pin to output mode
|
||||
pinMode(ledPin, OUTPUT);
|
||||
|
||||
// begin initialization
|
||||
if (!BLE.begin()) {
|
||||
Serial.println("starting Bluetooth® Low Energy module failed!");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
// set advertised local name and service UUID:
|
||||
BLE.setLocalName("LED");
|
||||
BLE.setAdvertisedService(ledService);
|
||||
|
||||
// add the characteristic to the service
|
||||
ledService.addCharacteristic(switchCharacteristic);
|
||||
|
||||
// add service
|
||||
BLE.addService(ledService);
|
||||
|
||||
// set the initial value for the characteristic:
|
||||
switchCharacteristic.writeValue(0);
|
||||
|
||||
// start advertising
|
||||
BLE.advertise();
|
||||
|
||||
Serial.println("BLE LED Peripheral");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// listen for Bluetooth® Low Energy peripherals to connect:
|
||||
BLEDevice central = BLE.central();
|
||||
|
||||
// if a central is connected to peripheral:
|
||||
if (central) {
|
||||
Serial.print("Connected to central: ");
|
||||
// print the central's MAC address:
|
||||
Serial.println(central.address());
|
||||
|
||||
// while the central is still connected to peripheral:
|
||||
while (central.connected()) {
|
||||
// if the remote device wrote to the characteristic,
|
||||
// use the value to control the LED:
|
||||
if (switchCharacteristic.written()) {
|
||||
if (switchCharacteristic.value()) { // any value other than 0
|
||||
Serial.println("LED on");
|
||||
digitalWrite(ledPin, HIGH); // will turn the LED on
|
||||
} else { // a 0 value
|
||||
Serial.println(F("LED off"));
|
||||
digitalWrite(ledPin, LOW); // will turn the LED off
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// when the central disconnects, print it out:
|
||||
Serial.print(F("Disconnected from central: "));
|
||||
Serial.println(central.address());
|
||||
}
|
||||
}
|
138
lib/ArduinoBLE/keywords.txt
Normal file
138
lib/ArduinoBLE/keywords.txt
Normal file
@ -0,0 +1,138 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For ArduinoBLE
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ArduinoBLE KEYWORD1
|
||||
BLE KEYWORD1
|
||||
|
||||
BLEDevice KEYWORD1
|
||||
BLECharacteristic KEYWORD1
|
||||
BLEDescriptor KEYWORD1
|
||||
BLEService KEYWORD1
|
||||
|
||||
BLEBoolCharacteristic KEYWORD1
|
||||
BLEBooleanCharacteristic KEYWORD1
|
||||
BLECharCharacteristic KEYWORD1
|
||||
BLEUnsignedCharCharacteristic KEYWORD1
|
||||
BLEByteCharacteristic KEYWORD1
|
||||
BLEShortCharacteristic KEYWORD1
|
||||
BLEUnsignedShortCharacteristic KEYWORD1
|
||||
BLEWordCharacteristic KEYWORD1
|
||||
BLEIntCharacteristic KEYWORD1
|
||||
BLEUnsignedIntCharacteristic KEYWORD1
|
||||
BLELongCharacteristic KEYWORD1
|
||||
BLEUnsignedLongCharacteristic KEYWORD1
|
||||
BLEFloatCharacteristic KEYWORD1
|
||||
BLEDoubleCharacteristic KEYWORD1
|
||||
BLEStringCharacteristic KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
poll KEYWORD2
|
||||
end KEYWORD2
|
||||
|
||||
connected KEYWORD2
|
||||
disconnect KEYWORD2
|
||||
address KEYWORD2
|
||||
hasLocalName KEYWORD2
|
||||
hasAdvertisedServiceUuid KEYWORD2
|
||||
advertisedServiceUuidCount KEYWORD2
|
||||
localName KEYWORD2
|
||||
advertisedServiceUuid KEYWORD2
|
||||
rssi KEYWORD2
|
||||
connect KEYWORD2
|
||||
discoverAttributes KEYWORD2
|
||||
discoverService KEYWORD2
|
||||
deviceName KEYWORD2
|
||||
appearance KEYWORD2
|
||||
serviceCount KEYWORD2
|
||||
hasService KEYWORD2
|
||||
service KEYWORD2
|
||||
characteristicCount KEYWORD2
|
||||
characteristic KEYWORD2
|
||||
|
||||
setAdvertisedServiceUuid KEYWORD2
|
||||
setManufacturerData KEYWORD2
|
||||
setLocalName KEYWORD2
|
||||
setDeviceName KEYWORD2
|
||||
setAppearance KEYWORD2
|
||||
addService KEYWORD2
|
||||
advertise KEYWORD2
|
||||
stopAdvertise KEYWORD2
|
||||
scan KEYWORD2
|
||||
scanForName KEYWORD2
|
||||
scanForUuid KEYWORD2
|
||||
scanForAddress KEYWORD2
|
||||
stopScan KEYWORD2
|
||||
central KEYWORD2
|
||||
available KEYWORD2
|
||||
setEventHandler KEYWORD2
|
||||
setAdvertisingInterval KEYWORD2
|
||||
setConnectionInterval KEYWORD2
|
||||
setConnectable KEYWORD2
|
||||
setPairable KEYWORD2
|
||||
setTimeout KEYWORD2
|
||||
debug KEYWORD2
|
||||
noDebug KEYWORD2
|
||||
pairable KEYWORD2
|
||||
paired KEYWORD2
|
||||
|
||||
properties KEYWORD2
|
||||
valueSize KEYWORD2
|
||||
value KEYWORD2
|
||||
valueLength KEYWORD2
|
||||
readValue KEYWORD2
|
||||
writeValue KEYWORD2
|
||||
setValue KEYWORD2
|
||||
broadcast KEYWORD2
|
||||
written KEYWORD2
|
||||
subscribed KEYWORD2
|
||||
valueUpdated KEYWORD2
|
||||
addDescriptor KEYWORD2
|
||||
descriptorCount KEYWORD2
|
||||
hasDescriptor KEYWORD2
|
||||
descriptor KEYWORD2
|
||||
canRead KEYWORD2
|
||||
read KEYWORD2
|
||||
canWrite KEYWORD2
|
||||
canSubscribe KEYWORD2
|
||||
subscribe KEYWORD2
|
||||
canUnsubscribe KEYWORD2
|
||||
unsubscribe KEYWORD2
|
||||
writeValueLE KEYWORD2
|
||||
setValueLE KEYWORD2
|
||||
valueLE KEYWORD2
|
||||
writeValueBE KEYWORD2
|
||||
setValueBE KEYWORD2
|
||||
valueBE KEYWORD2
|
||||
|
||||
uuid KEYWORD2
|
||||
addCharacteristic KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
BLEConnected LITERAL1
|
||||
BLEDisconnected LITERAL1
|
||||
BLEDiscovered LITERAL1
|
||||
|
||||
BLEBroadcast LITERAL1
|
||||
BLERead LITERAL1
|
||||
BLEWriteWithoutResponse LITERAL1
|
||||
BLEWrite LITERAL1
|
||||
BLENotify LITERAL1
|
||||
BLEIndicate LITERAL1
|
||||
|
||||
BLESubscribed LITERAL1
|
||||
BLEUnsubscribed LITERAL1
|
||||
BLEWritten LITERAL1
|
||||
BLEUpdated LITERAL1
|
||||
|
10
lib/ArduinoBLE/library.properties
Normal file
10
lib/ArduinoBLE/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=ArduinoBLE
|
||||
version=1.4.1
|
||||
author=Arduino
|
||||
maintainer=Arduino <info@arduino.cc>
|
||||
sentence=Enables Bluetooth® Low Energy connectivity on the Arduino MKR WiFi 1010, Arduino UNO WiFi Rev2, Arduino Nano 33 IoT, Arduino Nano 33 BLE, Nicla Sense ME and UNO R4 WiFi.
|
||||
paragraph=This library supports creating a Bluetooth® Low Energy peripheral & central mode.
|
||||
category=Communication
|
||||
url=https://www.arduino.cc/en/Reference/ArduinoBLE
|
||||
architectures=samd,megaavr,mbed,apollo3,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_giga,renesas,renesas_portenta,mbed_opta,renesas_uno,silabs
|
||||
includes=ArduinoBLE.h
|
29
lib/ArduinoBLE/src/ArduinoBLE.h
Normal file
29
lib/ArduinoBLE/src/ArduinoBLE.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ARDUINO_BLE_H_
|
||||
#define _ARDUINO_BLE_H_
|
||||
|
||||
#include "local/BLELocalDevice.h"
|
||||
#include "BLEProperty.h"
|
||||
#include "BLEStringCharacteristic.h"
|
||||
#include "BLETypedCharacteristics.h"
|
||||
#include "utility/btct.h"
|
||||
|
||||
#endif
|
352
lib/ArduinoBLE/src/BLEAdvertisingData.cpp
Normal file
352
lib/ArduinoBLE/src/BLEAdvertisingData.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLEAdvertisingData.h"
|
||||
|
||||
#define AD_FIELD_OVERHEAD (2)
|
||||
|
||||
BLEAdvertisingData::BLEAdvertisingData() :
|
||||
_dataLength(0),
|
||||
_remainingLength(MAX_AD_DATA_LENGTH),
|
||||
_rawData(NULL),
|
||||
_rawDataLength(0),
|
||||
_flags(0),
|
||||
_hasFlags(false),
|
||||
_localName(NULL),
|
||||
_manufacturerData(NULL),
|
||||
_manufacturerDataLength(0),
|
||||
_manufacturerCompanyId(0),
|
||||
_hasManufacturerCompanyId(false),
|
||||
_advertisedServiceUuid(NULL),
|
||||
_advertisedServiceUuidLength(0),
|
||||
_serviceData(NULL),
|
||||
_serviceDataLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLEAdvertisingData::~BLEAdvertisingData()
|
||||
{
|
||||
}
|
||||
|
||||
inline bool BLEAdvertisingData::updateRemainingLength(int oldFieldLength, int newFieldLength)
|
||||
{
|
||||
int updatedRemaining = _remainingLength + (oldFieldLength - newFieldLength);
|
||||
if (updatedRemaining >= 0) {
|
||||
_remainingLength = updatedRemaining;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int BLEAdvertisingData::remainingLength() const
|
||||
{
|
||||
return _remainingLength;
|
||||
}
|
||||
|
||||
int BLEAdvertisingData::availableForWrite()
|
||||
{
|
||||
int available = (_remainingLength - AD_FIELD_OVERHEAD);
|
||||
if (available < 0) available = 0;
|
||||
return available;
|
||||
}
|
||||
|
||||
void BLEAdvertisingData::clear()
|
||||
{
|
||||
_remainingLength = MAX_AD_DATA_LENGTH;
|
||||
_rawData = NULL;
|
||||
_rawDataLength = 0;
|
||||
_hasFlags = false;
|
||||
_localName = NULL;
|
||||
_manufacturerData = NULL;
|
||||
_manufacturerDataLength = 0;
|
||||
_hasManufacturerCompanyId = false;
|
||||
_advertisedServiceUuid = NULL;
|
||||
_advertisedServiceUuidLength = 0;
|
||||
_serviceData = NULL;
|
||||
_serviceDataLength = 0;
|
||||
}
|
||||
|
||||
void BLEAdvertisingData::copy(const BLEAdvertisingData& adv)
|
||||
{
|
||||
_remainingLength = adv._remainingLength;
|
||||
_rawData = adv._rawData;
|
||||
_rawDataLength = adv._rawDataLength;
|
||||
_flags = adv._flags;
|
||||
_hasFlags = adv._hasFlags;
|
||||
_localName = adv._localName;
|
||||
_manufacturerData = adv._manufacturerData;
|
||||
_manufacturerDataLength = adv._manufacturerDataLength;
|
||||
_manufacturerCompanyId = adv._manufacturerCompanyId;
|
||||
_hasManufacturerCompanyId = adv._hasManufacturerCompanyId;
|
||||
_advertisedServiceUuid = adv._advertisedServiceUuid;
|
||||
_advertisedServiceUuidLength = adv._advertisedServiceUuidLength;
|
||||
_serviceDataUuid = adv._serviceDataUuid;
|
||||
_serviceData = adv._serviceData;
|
||||
_serviceDataLength = adv._serviceDataLength;
|
||||
}
|
||||
|
||||
BLEAdvertisingData& BLEAdvertisingData::operator=(const BLEAdvertisingData &other)
|
||||
{
|
||||
copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setAdvertisedServiceUuid(const char* advertisedServiceUuid)
|
||||
{
|
||||
BLEUuid uuid(advertisedServiceUuid);
|
||||
int previousLength = (_advertisedServiceUuidLength > 0) ? (_advertisedServiceUuidLength + AD_FIELD_OVERHEAD) : 0;
|
||||
bool success = updateRemainingLength(previousLength, (uuid.length() + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_advertisedServiceUuid = advertisedServiceUuid;
|
||||
_advertisedServiceUuidLength = uuid.length();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setAdvertisedService(const BLEService& service)
|
||||
{
|
||||
return setAdvertisedServiceUuid(service.uuid());
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
int previousLength = 0;
|
||||
if (_manufacturerDataLength) {
|
||||
previousLength = _manufacturerDataLength + AD_FIELD_OVERHEAD;
|
||||
if (_hasManufacturerCompanyId) {
|
||||
previousLength += sizeof(_manufacturerCompanyId);
|
||||
}
|
||||
}
|
||||
bool success = updateRemainingLength(previousLength, (manufacturerDataLength + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_manufacturerData = manufacturerData;
|
||||
_manufacturerDataLength = manufacturerDataLength;
|
||||
_hasManufacturerCompanyId = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
int previousLength = 0;
|
||||
if (_manufacturerDataLength) {
|
||||
previousLength = _manufacturerDataLength + AD_FIELD_OVERHEAD;
|
||||
if (_hasManufacturerCompanyId) {
|
||||
previousLength += sizeof(_manufacturerCompanyId);
|
||||
}
|
||||
}
|
||||
bool success = updateRemainingLength(previousLength, (manufacturerDataLength + sizeof(companyId) + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_manufacturerData = manufacturerData;
|
||||
_manufacturerDataLength = manufacturerDataLength;
|
||||
_manufacturerCompanyId = companyId;
|
||||
_hasManufacturerCompanyId = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length)
|
||||
{
|
||||
int previousLength = (_serviceDataLength > 0) ? (_serviceDataLength + sizeof(uuid) + AD_FIELD_OVERHEAD) : 0;
|
||||
bool success = updateRemainingLength(previousLength, (length + sizeof(uuid) + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_serviceDataUuid = uuid;
|
||||
_serviceData = data;
|
||||
_serviceDataLength = length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setLocalName(const char *localName)
|
||||
{
|
||||
int previousLength = (_localName && strlen(_localName) > 0) ? (strlen(_localName) + AD_FIELD_OVERHEAD) : 0;
|
||||
bool success = updateRemainingLength(previousLength, (strlen(localName) + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_localName = localName;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setRawData(const uint8_t* data, int length)
|
||||
{
|
||||
if (length > MAX_AD_DATA_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
_rawData = data;
|
||||
_rawDataLength = length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setRawData(const BLEAdvertisingRawData& rawData)
|
||||
{
|
||||
if (rawData.length > MAX_AD_DATA_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
_rawData = rawData.data;
|
||||
_rawDataLength = rawData.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::setFlags(uint8_t flags)
|
||||
{
|
||||
int previousLength = (_hasFlags) ? (sizeof(_flags) + AD_FIELD_OVERHEAD) : 0;
|
||||
bool success = updateRemainingLength(previousLength, (sizeof(flags) + AD_FIELD_OVERHEAD));
|
||||
if (success) {
|
||||
_hasFlags = true;
|
||||
_flags = flags;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::updateData()
|
||||
{
|
||||
// Success indicates whether all the fields have been inserted
|
||||
bool success = true;
|
||||
// Reset data
|
||||
_dataLength = 0;
|
||||
// If rawData is present, then only rawData is inserted in the advertising packet
|
||||
if (_rawData && _rawDataLength) {
|
||||
return addRawData(_rawData, _rawDataLength);
|
||||
}
|
||||
// Try to add flags into the current advertising packet
|
||||
if (_hasFlags) {
|
||||
success &= addFlags(_flags);
|
||||
}
|
||||
// Try to add Advertised service uuid into the current advertising packet
|
||||
if (_advertisedServiceUuid) {
|
||||
success &= addAdvertisedServiceUuid(_advertisedServiceUuid);
|
||||
}
|
||||
// Try to add Manufacturer data into the current advertising packet
|
||||
if (_manufacturerData && _manufacturerDataLength) {
|
||||
if (_hasManufacturerCompanyId) {
|
||||
success &= addManufacturerData(_manufacturerCompanyId, _manufacturerData, _manufacturerDataLength);
|
||||
} else {
|
||||
success &= addManufacturerData(_manufacturerData, _manufacturerDataLength);
|
||||
}
|
||||
}
|
||||
// Try to add Service data into the current advertising packet
|
||||
if (_serviceData && _serviceDataLength) {
|
||||
success &= addAdvertisedServiceData(_serviceDataUuid, _serviceData, _serviceDataLength);
|
||||
}
|
||||
// Try to add Local name into the current advertising packet
|
||||
if (_localName) {
|
||||
success &= addLocalName(_localName);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
uint8_t* BLEAdvertisingData::data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
int BLEAdvertisingData::dataLength() const
|
||||
{
|
||||
return _dataLength;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::hasFlags() const
|
||||
{
|
||||
return _hasFlags;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addLocalName(const char *localName)
|
||||
{
|
||||
bool success = false;
|
||||
if (strlen(localName) > (MAX_AD_DATA_LENGTH - AD_FIELD_OVERHEAD)) {
|
||||
success = addField(BLEFieldShortLocalName, (uint8_t*)localName, (MAX_AD_DATA_LENGTH - AD_FIELD_OVERHEAD));
|
||||
} else {
|
||||
success = addField(BLEFieldCompleteLocalName, localName);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addAdvertisedServiceUuid(const char* advertisedServiceUuid)
|
||||
{
|
||||
BLEUuid uuid(advertisedServiceUuid);
|
||||
int uuidLen = uuid.length();
|
||||
BLEAdField advField;
|
||||
if (uuidLen > 2) {
|
||||
advField = BLEFieldIncompleteAdvertisedService128;
|
||||
} else {
|
||||
advField = BLEFieldIncompleteAdvertisedService16;
|
||||
}
|
||||
return addField(advField, uuid.data(), uuidLen);
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
return addField(BLEFieldManufacturerData, manufacturerData, manufacturerDataLength);
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
int tempDataLength = manufacturerDataLength + sizeof(companyId);
|
||||
uint8_t tempData[MAX_AD_DATA_LENGTH];
|
||||
memcpy(tempData, &companyId, sizeof(companyId));
|
||||
memcpy(&tempData[sizeof(companyId)], manufacturerData, manufacturerDataLength);
|
||||
return addField(BLEFieldManufacturerData, tempData, tempDataLength);
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length)
|
||||
{
|
||||
int tempDataLength = length + sizeof(uuid);
|
||||
uint8_t tempData[MAX_AD_DATA_LENGTH];
|
||||
memcpy(tempData, &uuid, sizeof(uuid));
|
||||
memcpy(&tempData[sizeof(uuid)], data, length);
|
||||
return addField(BLEFieldServiceData, tempData, tempDataLength);
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addRawData(const uint8_t* data, int length)
|
||||
{
|
||||
// Bypass addField to add the integral raw data
|
||||
if (length > (MAX_AD_DATA_LENGTH - _dataLength)) {
|
||||
// Not enough space
|
||||
return false;
|
||||
}
|
||||
memcpy(&_data[_dataLength], data, length);
|
||||
_dataLength += length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addFlags(uint8_t flags)
|
||||
{
|
||||
return addField(BLEFieldFlags, &flags, sizeof(flags));
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addField(BLEAdField field, const char* data)
|
||||
{
|
||||
int dataLength = strlen(data);
|
||||
return addField(field, (uint8_t *)data, dataLength);
|
||||
}
|
||||
|
||||
bool BLEAdvertisingData::addField(BLEAdField field, const uint8_t* data, int length)
|
||||
{
|
||||
int fieldLength = length + AD_FIELD_OVERHEAD; // Considering data TYPE and LENGTH fields
|
||||
if (fieldLength > (MAX_AD_DATA_LENGTH - _dataLength)) {
|
||||
// Not enough space for storing this field
|
||||
return false;
|
||||
}
|
||||
// Insert field into advertising data of the instance
|
||||
_data[_dataLength++] = length + 1;
|
||||
_data[_dataLength++] = field;
|
||||
memcpy(&_data[_dataLength], data, length);
|
||||
_dataLength += length;
|
||||
return true;
|
||||
}
|
120
lib/ArduinoBLE/src/BLEAdvertisingData.h
Normal file
120
lib/ArduinoBLE/src/BLEAdvertisingData.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_ADVERTISING_DATA_H_
|
||||
#define _BLE_ADVERTISING_DATA_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "utility/BLEUuid.h"
|
||||
#include "BLEService.h"
|
||||
|
||||
#define MAX_AD_DATA_LENGTH (31)
|
||||
|
||||
enum BLEFlags {
|
||||
BLEFlagsLimitedDiscoverable = 0x01,
|
||||
BLEFlagsGeneralDiscoverable = 0x02,
|
||||
BLEFlagsBREDRNotSupported = 0x04
|
||||
};
|
||||
|
||||
enum BLEAdField {
|
||||
BLEFieldFlags = 0x01,
|
||||
BLEFieldIncompleteAdvertisedService16 = 0x02,
|
||||
BLEFieldCompleteAdvertisedService16 = 0x03,
|
||||
BLEFieldIncompleteAdvertisedService128 = 0x06,
|
||||
BLEFieldCompleteAdvertisedService128 = 0x07,
|
||||
BLEFieldShortLocalName = 0x08,
|
||||
BLEFieldCompleteLocalName = 0x09,
|
||||
BLEFieldServiceData = 0x16,
|
||||
BLEFieldManufacturerData = 0xFF,
|
||||
|
||||
BLEAdFieldLast
|
||||
};
|
||||
|
||||
struct BLEAdvertisingRawData {
|
||||
uint8_t data[MAX_AD_DATA_LENGTH];
|
||||
int length;
|
||||
};
|
||||
|
||||
class BLEAdvertisingData {
|
||||
public:
|
||||
BLEAdvertisingData();
|
||||
virtual ~BLEAdvertisingData();
|
||||
|
||||
int availableForWrite();
|
||||
void clear();
|
||||
void copy(const BLEAdvertisingData& adv);
|
||||
BLEAdvertisingData& operator=(const BLEAdvertisingData &other);
|
||||
|
||||
bool setAdvertisedService(const BLEService& service);
|
||||
bool setAdvertisedServiceUuid(const char* advertisedServiceUuid);
|
||||
bool setManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
bool setManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
bool setLocalName(const char *localName);
|
||||
bool setAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length);
|
||||
bool setRawData(const uint8_t* data, int length);
|
||||
bool setRawData(const BLEAdvertisingRawData& data);
|
||||
bool setFlags(uint8_t flags);
|
||||
|
||||
protected:
|
||||
friend class BLELocalDevice;
|
||||
bool updateData();
|
||||
uint8_t* data();
|
||||
int dataLength() const;
|
||||
int remainingLength() const;
|
||||
bool hasFlags() const;
|
||||
|
||||
private:
|
||||
bool updateRemainingLength(int oldFieldLength, int newFieldLength);
|
||||
|
||||
bool addAdvertisedServiceUuid(const char* advertisedServiceUuid);
|
||||
bool addManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
bool addManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
bool addLocalName(const char *localName);
|
||||
bool addAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length);
|
||||
bool addRawData(const uint8_t* data, int length);
|
||||
bool addFlags(uint8_t flags);
|
||||
|
||||
bool addField(BLEAdField field, const char* data);
|
||||
bool addField(BLEAdField field, const uint8_t* data, int length);
|
||||
|
||||
uint8_t _data[MAX_AD_DATA_LENGTH];
|
||||
int _dataLength;
|
||||
|
||||
int _remainingLength;
|
||||
|
||||
const uint8_t* _rawData;
|
||||
int _rawDataLength;
|
||||
|
||||
uint8_t _flags;
|
||||
bool _hasFlags;
|
||||
const char* _localName;
|
||||
|
||||
const uint8_t* _manufacturerData;
|
||||
int _manufacturerDataLength;
|
||||
uint16_t _manufacturerCompanyId;
|
||||
bool _hasManufacturerCompanyId;
|
||||
|
||||
const char* _advertisedServiceUuid;
|
||||
int _advertisedServiceUuidLength;
|
||||
uint16_t _serviceDataUuid;
|
||||
const uint8_t* _serviceData;
|
||||
int _serviceDataLength;
|
||||
};
|
||||
|
||||
#endif
|
493
lib/ArduinoBLE/src/BLECharacteristic.cpp
Normal file
493
lib/ArduinoBLE/src/BLECharacteristic.cpp
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLEProperty.h"
|
||||
|
||||
#include "local/BLELocalCharacteristic.h"
|
||||
#include "remote/BLERemoteCharacteristic.h"
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
extern "C" int strcasecmp(char const *a, char const *b);
|
||||
|
||||
BLECharacteristic::BLECharacteristic() :
|
||||
BLECharacteristic((BLELocalCharacteristic*)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(BLELocalCharacteristic* local) :
|
||||
_local(local),
|
||||
_remote(NULL)
|
||||
{
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(BLERemoteCharacteristic* remote) :
|
||||
_local(NULL),
|
||||
_remote(remote)
|
||||
{
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(const char* uuid, uint16_t permissions, int valueSize, bool fixedLength) :
|
||||
BLECharacteristic(new BLELocalCharacteristic(uuid, permissions, valueSize, fixedLength))
|
||||
{
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(const char* uuid, uint16_t permissions, const char* value) :
|
||||
BLECharacteristic(new BLELocalCharacteristic(uuid, permissions, value))
|
||||
{
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(const BLECharacteristic& other)
|
||||
{
|
||||
_local = other._local;
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
|
||||
_remote = other._remote;
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLECharacteristic::~BLECharacteristic()
|
||||
{
|
||||
if (_local && _local->release() == 0) {
|
||||
delete _local;
|
||||
}
|
||||
|
||||
if (_remote && _remote->release() == 0) {
|
||||
delete _remote;
|
||||
}
|
||||
}
|
||||
|
||||
const char* BLECharacteristic::uuid() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->uuid();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->uuid();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
uint8_t BLECharacteristic::properties() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->properties();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->properties();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLECharacteristic::valueSize() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->valueSize();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->valueLength();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t* BLECharacteristic::value() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->value();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->value();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BLECharacteristic::valueLength() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->valueLength();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->valueLength();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t BLECharacteristic::operator[] (int offset) const
|
||||
{
|
||||
if (_local) {
|
||||
return (*_local)[offset];
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return (*_remote)[offset];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(uint8_t value[], int length)
|
||||
{
|
||||
int bytesRead = 0;
|
||||
|
||||
if (_local) {
|
||||
bytesRead = min(length, _local->valueLength());
|
||||
|
||||
memcpy(value, _local->value(), bytesRead);
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
// trigger a read if the updated value (notification/indication)
|
||||
// has already been read and the characteristic is readable
|
||||
if (_remote->updatedValueRead() && canRead()) {
|
||||
if (!read()) {
|
||||
// read failed
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytesRead = min(length, _remote->valueLength());
|
||||
|
||||
memcpy(value, _remote->value(), bytesRead);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(void* value, int length)
|
||||
{
|
||||
return readValue((uint8_t*)value, length);
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(uint8_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(int8_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(uint16_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(int16_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(uint32_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::readValue(int32_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(const uint8_t value[], int length, bool withResponse)
|
||||
{
|
||||
if (_local) {
|
||||
return _local->writeValue(value, length);
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->writeValue(value, length, withResponse);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(const void* value, int length, bool withResponse)
|
||||
{
|
||||
return writeValue((const uint8_t*)value, length, withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(const char* value, bool withResponse)
|
||||
{
|
||||
if (_local) {
|
||||
return _local->writeValue(value);
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->writeValue(value, withResponse);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(uint8_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(int8_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(uint16_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(int16_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(uint32_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::writeValue(int32_t value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)&value, sizeof(value), withResponse);
|
||||
}
|
||||
|
||||
int BLECharacteristic::broadcast()
|
||||
{
|
||||
if (_local) {
|
||||
return _local->broadcast();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::written()
|
||||
{
|
||||
if (_local) {
|
||||
return _local->written();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::subscribed()
|
||||
{
|
||||
if (_local) {
|
||||
return _local->subscribed();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::valueUpdated()
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->valueUpdated();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BLECharacteristic::addDescriptor(BLEDescriptor& descriptor)
|
||||
{
|
||||
if (_local) {
|
||||
return _local->addDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
BLECharacteristic::operator bool() const
|
||||
{
|
||||
return (_local != NULL) || (_remote != NULL);
|
||||
}
|
||||
|
||||
BLELocalCharacteristic* BLECharacteristic::local()
|
||||
{
|
||||
return _local;
|
||||
}
|
||||
|
||||
void BLECharacteristic::setEventHandler(int event, BLECharacteristicEventHandler eventHandler)
|
||||
{
|
||||
if (_local) {
|
||||
_local->setEventHandler((BLECharacteristicEvent)event, eventHandler);
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
_remote->setEventHandler((BLECharacteristicEvent)event, eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
int BLECharacteristic::descriptorCount() const
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->descriptorCount();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::hasDescriptor(const char* uuid) const
|
||||
{
|
||||
return hasDescriptor(uuid, 0);
|
||||
}
|
||||
|
||||
bool BLECharacteristic::hasDescriptor(const char* uuid, int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
int count = 0;
|
||||
int numDescriptors = _remote->descriptorCount();
|
||||
|
||||
for (int i = 0; i < numDescriptors; i++) {
|
||||
BLERemoteDescriptor* d = _remote->descriptor(i);
|
||||
|
||||
if (strcasecmp(uuid, d->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLEDescriptor BLECharacteristic::descriptor(int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
return BLEDescriptor(_remote->descriptor(index));
|
||||
}
|
||||
|
||||
return BLEDescriptor();
|
||||
}
|
||||
|
||||
BLEDescriptor BLECharacteristic::descriptor(const char * uuid) const
|
||||
{
|
||||
return descriptor(uuid, 0);
|
||||
}
|
||||
|
||||
BLEDescriptor BLECharacteristic::descriptor(const char * uuid, int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
int count = 0;
|
||||
int numDescriptors = _remote->descriptorCount();
|
||||
|
||||
for (int i = 0; i < numDescriptors; i++) {
|
||||
BLERemoteDescriptor* d = _remote->descriptor(i);
|
||||
|
||||
if (strcasecmp(uuid, d->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return BLEDescriptor(d);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLEDescriptor();
|
||||
}
|
||||
|
||||
bool BLECharacteristic::canRead()
|
||||
{
|
||||
if (_remote) {
|
||||
return (properties() & BLERead) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::read()
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->read();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::canWrite()
|
||||
{
|
||||
if (_remote) {
|
||||
return (properties() & (BLEWrite | BLEWriteWithoutResponse)) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::canSubscribe()
|
||||
{
|
||||
if (_remote) {
|
||||
return (properties() & (BLENotify | BLEIndicate)) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::subscribe()
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->writeCccd((properties() & BLEIndicate) ? 0x0002 : 0x0001);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::canUnsubscribe()
|
||||
{
|
||||
return canSubscribe();
|
||||
}
|
||||
|
||||
bool BLECharacteristic::unsubscribe()
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->writeCccd(0x0000);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
132
lib/ArduinoBLE/src/BLECharacteristic.h
Normal file
132
lib/ArduinoBLE/src/BLECharacteristic.h
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_CHARACTERISTIC_H_
|
||||
#define _BLE_CHARACTERISTIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "BLEDescriptor.h"
|
||||
|
||||
enum BLECharacteristicEvent {
|
||||
BLESubscribed = 0,
|
||||
BLEUnsubscribed = 1,
|
||||
//BLERead = 2, // defined in BLEProperties.h
|
||||
BLEWritten = 3,
|
||||
BLEUpdated = BLEWritten, // alias
|
||||
|
||||
BLECharacteristicEventLast
|
||||
};
|
||||
|
||||
class BLECharacteristic;
|
||||
class BLEDevice;
|
||||
|
||||
typedef void (*BLECharacteristicEventHandler)(BLEDevice device, BLECharacteristic characteristic);
|
||||
|
||||
class BLELocalCharacteristic;
|
||||
class BLERemoteCharacteristic;
|
||||
|
||||
class BLECharacteristic {
|
||||
public:
|
||||
BLECharacteristic();
|
||||
BLECharacteristic(const char* uuid, uint16_t permissions, int valueSize, bool fixedLength = false);
|
||||
BLECharacteristic(const char* uuid, uint16_t permissions, const char* value);
|
||||
BLECharacteristic(const BLECharacteristic& other);
|
||||
virtual ~BLECharacteristic();
|
||||
|
||||
const char* uuid() const;
|
||||
|
||||
uint8_t properties() const;
|
||||
|
||||
int valueSize() const;
|
||||
const uint8_t* value() const;
|
||||
int valueLength() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
int readValue(uint8_t value[], int length);
|
||||
int readValue(void* value, int length);
|
||||
int readValue(uint8_t& value);
|
||||
int readValue(int8_t& value);
|
||||
int readValue(uint16_t& value);
|
||||
int readValue(int16_t& value);
|
||||
int readValue(uint32_t& value);
|
||||
int readValue(int32_t& value);
|
||||
|
||||
int writeValue(const uint8_t value[], int length, bool withResponse = true);
|
||||
int writeValue(const void* value, int length, bool withResponse = true);
|
||||
int writeValue(const char* value, bool withResponse = true);
|
||||
int writeValue(uint8_t value, bool withResponse = true);
|
||||
int writeValue(int8_t value, bool withResponse = true);
|
||||
int writeValue(uint16_t value, bool withResponse = true);
|
||||
int writeValue(int16_t value, bool withResponse = true);
|
||||
int writeValue(uint32_t value, bool withResponse = true);
|
||||
int writeValue(int32_t value, bool withResponse = true);
|
||||
|
||||
// deprecated, use writeValue(...)
|
||||
int setValue(const uint8_t value[], int length) { return writeValue(value, length); }
|
||||
int setValue(const char* value) { return writeValue(value); }
|
||||
|
||||
int broadcast();
|
||||
|
||||
bool written();
|
||||
bool subscribed();
|
||||
bool valueUpdated();
|
||||
|
||||
void addDescriptor(BLEDescriptor& descriptor);
|
||||
|
||||
operator bool() const;
|
||||
|
||||
void setEventHandler(int event, BLECharacteristicEventHandler eventHandler);
|
||||
|
||||
int descriptorCount() const;
|
||||
bool hasDescriptor(const char* uuid) const;
|
||||
bool hasDescriptor(const char* uuid, int index) const;
|
||||
BLEDescriptor descriptor(int index) const;
|
||||
BLEDescriptor descriptor(const char * uuid) const;
|
||||
BLEDescriptor descriptor(const char * uuid, int index) const;
|
||||
|
||||
bool canRead();
|
||||
bool read();
|
||||
bool canWrite();
|
||||
bool canSubscribe();
|
||||
bool subscribe();
|
||||
bool canUnsubscribe();
|
||||
bool unsubscribe();
|
||||
|
||||
protected:
|
||||
friend class BLELocalCharacteristic;
|
||||
friend class BLELocalService;
|
||||
|
||||
BLECharacteristic(BLELocalCharacteristic* local);
|
||||
|
||||
BLELocalCharacteristic* local();
|
||||
|
||||
protected:
|
||||
friend class BLEDevice;
|
||||
friend class BLEService;
|
||||
friend class BLERemoteCharacteristic;
|
||||
|
||||
BLECharacteristic(BLERemoteCharacteristic* remote);
|
||||
|
||||
private:
|
||||
BLELocalCharacteristic* _local;
|
||||
BLERemoteCharacteristic* _remote;
|
||||
};
|
||||
|
||||
#endif
|
229
lib/ArduinoBLE/src/BLEDescriptor.cpp
Normal file
229
lib/ArduinoBLE/src/BLEDescriptor.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "local/BLELocalDescriptor.h"
|
||||
#include "remote/BLERemoteDescriptor.h"
|
||||
|
||||
#include "BLEDescriptor.h"
|
||||
|
||||
BLEDescriptor::BLEDescriptor() :
|
||||
BLEDescriptor((BLELocalDescriptor*)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BLEDescriptor::BLEDescriptor(BLELocalDescriptor* local) :
|
||||
_local(local),
|
||||
_remote(NULL)
|
||||
{
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLEDescriptor::BLEDescriptor(BLERemoteDescriptor* remote) :
|
||||
_local(NULL),
|
||||
_remote(remote)
|
||||
{
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLEDescriptor::BLEDescriptor(const char* uuid, const uint8_t value[], int valueSize) :
|
||||
BLEDescriptor(new BLELocalDescriptor(uuid, value, valueSize))
|
||||
{
|
||||
}
|
||||
|
||||
BLEDescriptor::BLEDescriptor(const char* uuid, const char* value) :
|
||||
BLEDescriptor(new BLELocalDescriptor(uuid, value))
|
||||
{
|
||||
}
|
||||
|
||||
BLEDescriptor::BLEDescriptor(const BLEDescriptor& other)
|
||||
{
|
||||
_local = other._local;
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
|
||||
_remote = other._remote;
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLEDescriptor::~BLEDescriptor()
|
||||
{
|
||||
if (_local && _local->release() == 0) {
|
||||
delete _local;
|
||||
}
|
||||
|
||||
if (_remote && _remote->release() == 0) {
|
||||
delete _remote;
|
||||
}
|
||||
}
|
||||
|
||||
const char* BLEDescriptor::uuid() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->uuid();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->uuid();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int BLEDescriptor::valueSize() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->valueSize();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->valueLength();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t* BLEDescriptor::value() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->value();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->value();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BLEDescriptor::valueLength() const
|
||||
{
|
||||
return valueSize();
|
||||
}
|
||||
|
||||
uint8_t BLEDescriptor::operator[] (int offset) const
|
||||
{
|
||||
if (_local) {
|
||||
return (*_local)[offset];
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return (*_remote)[offset];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(uint8_t value[], int length)
|
||||
{
|
||||
int bytesRead = 0;
|
||||
|
||||
if (_local) {
|
||||
bytesRead = min(length, _local->valueSize());
|
||||
|
||||
memcpy(value, _local->value(), bytesRead);
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
if (!read()) {
|
||||
// read failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesRead = min(length, _remote->valueLength());
|
||||
|
||||
memcpy(value, _remote->value(), bytesRead);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(void* value, int length)
|
||||
{
|
||||
return readValue((uint8_t*)value, length);
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(uint8_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(int8_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(uint16_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(int16_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(uint32_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
int BLEDescriptor::readValue(int32_t& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
return readValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
BLEDescriptor::operator bool() const
|
||||
{
|
||||
return (_local != NULL) || (_remote != NULL);
|
||||
}
|
||||
|
||||
bool BLEDescriptor::read()
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->read();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLELocalDescriptor* BLEDescriptor::local()
|
||||
{
|
||||
return _local;
|
||||
}
|
73
lib/ArduinoBLE/src/BLEDescriptor.h
Normal file
73
lib/ArduinoBLE/src/BLEDescriptor.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_DESCRIPTOR_H_
|
||||
#define _BLE_DESCRIPTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class BLELocalDescriptor;
|
||||
class BLERemoteDescriptor;
|
||||
|
||||
class BLEDescriptor {
|
||||
public:
|
||||
BLEDescriptor();
|
||||
BLEDescriptor(const BLEDescriptor& other);
|
||||
BLEDescriptor(const char* uuid, const uint8_t value[], int valueSize);
|
||||
BLEDescriptor(const char* uuid, const char* value);
|
||||
virtual ~BLEDescriptor();
|
||||
|
||||
const char* uuid() const;
|
||||
|
||||
int valueSize() const;
|
||||
const uint8_t* value() const;
|
||||
int valueLength() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
int readValue(uint8_t value[], int length);
|
||||
int readValue(void* value, int length);
|
||||
int readValue(uint8_t& value);
|
||||
int readValue(int8_t& value);
|
||||
int readValue(uint16_t& value);
|
||||
int readValue(int16_t& value);
|
||||
int readValue(uint32_t& value);
|
||||
int readValue(int32_t& value);
|
||||
|
||||
operator bool() const;
|
||||
|
||||
bool read();
|
||||
|
||||
protected:
|
||||
friend class BLELocalCharacteristic;
|
||||
|
||||
BLEDescriptor(BLELocalDescriptor* local);
|
||||
|
||||
BLELocalDescriptor* local();
|
||||
|
||||
protected:
|
||||
friend class BLECharacteristic;
|
||||
|
||||
BLEDescriptor(BLERemoteDescriptor* remote);
|
||||
|
||||
private:
|
||||
BLELocalDescriptor* _local;
|
||||
BLERemoteDescriptor* _remote;
|
||||
};
|
||||
|
||||
#endif
|
578
lib/ArduinoBLE/src/BLEDevice.cpp
Normal file
578
lib/ArduinoBLE/src/BLEDevice.cpp
Normal file
@ -0,0 +1,578 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "utility/ATT.h"
|
||||
#include "utility/BLEUuid.h"
|
||||
#include "utility/HCI.h"
|
||||
|
||||
#include "remote/BLERemoteDevice.h"
|
||||
|
||||
#include "BLEDevice.h"
|
||||
|
||||
extern "C" int strcasecmp(char const *a, char const *b);
|
||||
|
||||
BLEDevice::BLEDevice() :
|
||||
_advertisementTypeMask(0),
|
||||
_eirDataLength(0),
|
||||
_rssi(127)
|
||||
{
|
||||
memset(_address, 0x00, sizeof(_address));
|
||||
}
|
||||
|
||||
BLEDevice::BLEDevice(uint8_t addressType, uint8_t address[6]) :
|
||||
_addressType(addressType),
|
||||
_advertisementTypeMask(0),
|
||||
_eirDataLength(0),
|
||||
_rssi(127)
|
||||
{
|
||||
memcpy(_address, address, sizeof(_address));
|
||||
}
|
||||
|
||||
BLEDevice::~BLEDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void BLEDevice::poll()
|
||||
{
|
||||
HCI.poll();
|
||||
}
|
||||
|
||||
void BLEDevice::poll(unsigned long timeout)
|
||||
{
|
||||
HCI.poll(timeout);
|
||||
}
|
||||
|
||||
bool BLEDevice::connected() const
|
||||
{
|
||||
HCI.poll();
|
||||
|
||||
if (!(*this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ATT.connected(_addressType, _address);
|
||||
}
|
||||
|
||||
bool BLEDevice::disconnect()
|
||||
{
|
||||
return ATT.disconnect(_addressType, _address);
|
||||
}
|
||||
|
||||
String BLEDevice::address() const
|
||||
{
|
||||
char result[18];
|
||||
sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x", _address[5], _address[4], _address[3], _address[2], _address[1], _address[0]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BLEDevice::hasLocalName() const
|
||||
{
|
||||
return (localName().length() > 0);
|
||||
}
|
||||
|
||||
bool BLEDevice::hasAdvertisedServiceUuid() const
|
||||
{
|
||||
return hasAdvertisedServiceUuid(0);
|
||||
}
|
||||
|
||||
bool BLEDevice::hasAdvertisedServiceUuid(int index) const
|
||||
{
|
||||
return (advertisedServiceUuid(index).length() > 0);
|
||||
}
|
||||
|
||||
int BLEDevice::advertisedServiceUuidCount() const
|
||||
{
|
||||
int advertisedServiceCount = 0;
|
||||
|
||||
for (unsigned char i = 0; i < _eirDataLength;) {
|
||||
int eirLength = _eirData[i++];
|
||||
int eirType = _eirData[i++];
|
||||
|
||||
if (eirType == 0x02 || eirType == 0x03 || eirType == 0x06 || eirType == 0x07) {
|
||||
int uuidLength;
|
||||
|
||||
if (eirType == 0x02 || eirType == 0x03) {
|
||||
uuidLength = 2;
|
||||
} else /*if (eirType == 0x06 || eirType == 0x07)*/ {
|
||||
uuidLength = 16;
|
||||
}
|
||||
|
||||
for (int j = 0; j < (eirLength - 1); j += uuidLength) {
|
||||
advertisedServiceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
i += (eirLength - 1);
|
||||
}
|
||||
|
||||
return advertisedServiceCount;
|
||||
}
|
||||
|
||||
String BLEDevice::localName() const
|
||||
{
|
||||
String localName = "";
|
||||
|
||||
for (int i = 0; i < _eirDataLength;) {
|
||||
int eirLength = _eirData[i++];
|
||||
int eirType = _eirData[i++];
|
||||
|
||||
if (eirType == 0x08 || eirType == 0x09) {
|
||||
localName.reserve(eirLength - 1);
|
||||
|
||||
for (int j = 0; j < (eirLength - 1); j++) {
|
||||
localName += (char)_eirData[i + j];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
i += (eirLength - 1);
|
||||
}
|
||||
|
||||
return localName;
|
||||
}
|
||||
|
||||
String BLEDevice::advertisedServiceUuid() const
|
||||
{
|
||||
return advertisedServiceUuid(0);
|
||||
}
|
||||
|
||||
String BLEDevice::advertisedServiceUuid(int index) const
|
||||
{
|
||||
String serviceUuid;
|
||||
int uuidIndex = 0;
|
||||
|
||||
for (unsigned char i = 0; i < _eirDataLength;) {
|
||||
int eirLength = _eirData[i++];
|
||||
int eirType = _eirData[i++];
|
||||
|
||||
if (eirType == 0x02 || eirType == 0x03 || eirType == 0x06 || eirType == 0x07) {
|
||||
int uuidLength;
|
||||
|
||||
if (eirType == 0x02 || eirType == 0x03) {
|
||||
uuidLength = 2;
|
||||
} else /*if (eirType == 0x06 || eirType == 0x07)*/ {
|
||||
uuidLength = 16;
|
||||
}
|
||||
|
||||
for (int j = 0; j < (eirLength - 1); j += uuidLength) {
|
||||
if (uuidIndex == index) {
|
||||
serviceUuid = BLEUuid::uuidToString(&_eirData[i + j * uuidLength], uuidLength);
|
||||
}
|
||||
|
||||
uuidIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
i += (eirLength - 1);
|
||||
}
|
||||
|
||||
return serviceUuid;
|
||||
}
|
||||
|
||||
bool BLEDevice::hasAdvertisementData() const
|
||||
{
|
||||
return (_eirDataLength > 0);
|
||||
}
|
||||
|
||||
int BLEDevice::advertisementDataLength() const
|
||||
{
|
||||
return _eirDataLength;
|
||||
}
|
||||
|
||||
int BLEDevice::advertisementData(uint8_t value[], int length) const
|
||||
{
|
||||
if (length > _eirDataLength) length = _eirDataLength;
|
||||
|
||||
if (length) {
|
||||
memcpy(value, _eirData, length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
bool BLEDevice::hasManufacturerData() const
|
||||
{
|
||||
return (manufacturerDataLength() > 0);
|
||||
}
|
||||
|
||||
int BLEDevice::manufacturerDataLength() const
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
for (int i = 0; i < _eirDataLength;) {
|
||||
int eirLength = _eirData[i++];
|
||||
int eirType = _eirData[i++];
|
||||
|
||||
if (eirType == 0xFF) {
|
||||
length = (eirLength - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
i += (eirLength - 1);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int BLEDevice::manufacturerData(uint8_t value[], int length) const
|
||||
{
|
||||
for (int i = 0; i < _eirDataLength;) {
|
||||
int eirLength = _eirData[i++];
|
||||
int eirType = _eirData[i++];
|
||||
|
||||
if (eirType == 0xFF) {
|
||||
if (length > (eirLength - 1)) length = (eirLength - 1);
|
||||
|
||||
memcpy(value, &_eirData[i], length);
|
||||
break;
|
||||
}
|
||||
|
||||
i += (eirLength - 1);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int BLEDevice::rssi()
|
||||
{
|
||||
uint16_t handle = ATT.connectionHandle(_addressType, _address);
|
||||
|
||||
if (handle != 0xffff) {
|
||||
return HCI.readRssi(handle);
|
||||
}
|
||||
|
||||
return _rssi;
|
||||
}
|
||||
|
||||
bool BLEDevice::connect()
|
||||
{
|
||||
return ATT.connect(_addressType, _address);
|
||||
}
|
||||
|
||||
bool BLEDevice::discoverAttributes()
|
||||
{
|
||||
return ATT.discoverAttributes(_addressType, _address, NULL);
|
||||
}
|
||||
|
||||
bool BLEDevice::discoverService(const char* serviceUuid)
|
||||
{
|
||||
return ATT.discoverAttributes(_addressType, _address, serviceUuid);
|
||||
}
|
||||
|
||||
BLEDevice::operator bool() const
|
||||
{
|
||||
uint8_t zeros[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
|
||||
|
||||
return (memcmp(_address, zeros, sizeof(zeros)) != 0);
|
||||
}
|
||||
|
||||
bool BLEDevice::operator==(const BLEDevice& rhs) const
|
||||
{
|
||||
return ((_addressType == rhs._addressType) && memcmp(_address, rhs._address, sizeof(_address)) == 0);
|
||||
}
|
||||
|
||||
bool BLEDevice::operator!=(const BLEDevice& rhs) const
|
||||
{
|
||||
return ((_addressType != rhs._addressType) || memcmp(_address, rhs._address, sizeof(_address)) != 0);
|
||||
}
|
||||
|
||||
String BLEDevice::deviceName()
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
BLEService genericAccessService = service("1800");
|
||||
|
||||
if (genericAccessService) {
|
||||
BLECharacteristic deviceNameCharacteristic = genericAccessService.characteristic("2a00");
|
||||
|
||||
if (deviceNameCharacteristic) {
|
||||
deviceNameCharacteristic.read();
|
||||
|
||||
String result;
|
||||
int valueLength = deviceNameCharacteristic.valueLength();
|
||||
const char* value = (const char*)deviceNameCharacteristic.value();
|
||||
|
||||
result.reserve(valueLength);
|
||||
|
||||
for (int i = 0; i < valueLength; i++) {
|
||||
result += value[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int BLEDevice::appearance()
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
BLEService genericAccessService = service("1801");
|
||||
|
||||
if (genericAccessService) {
|
||||
BLECharacteristic appearanceCharacteristic = genericAccessService.characteristic("2a01");
|
||||
|
||||
if (appearanceCharacteristic) {
|
||||
appearanceCharacteristic.read();
|
||||
|
||||
uint16_t result = 0;
|
||||
|
||||
memcpy (&result, appearanceCharacteristic.value(), min((int)sizeof(result), appearanceCharacteristic.valueLength()));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLEDevice::serviceCount() const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
return device->serviceCount();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLEDevice::hasService(const char* uuid) const
|
||||
{
|
||||
return hasService(uuid, 0);
|
||||
}
|
||||
|
||||
bool BLEDevice::hasService(const char* uuid, int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int count = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
BLERemoteService* s = device->service(i);
|
||||
|
||||
if (strcasecmp(uuid, s->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLEService BLEDevice::service(int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
if (index < (int)device->serviceCount()) {
|
||||
return BLEService(device->service(index));
|
||||
}
|
||||
}
|
||||
|
||||
return BLEService();
|
||||
}
|
||||
|
||||
BLEService BLEDevice::service(const char * uuid) const
|
||||
{
|
||||
return service(uuid, 0);
|
||||
}
|
||||
|
||||
BLEService BLEDevice::service(const char * uuid, int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int count = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
BLERemoteService* s = device->service(i);
|
||||
|
||||
if (strcasecmp(uuid, s->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return BLEService(s);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLEService();
|
||||
}
|
||||
|
||||
int BLEDevice::characteristicCount() const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int result = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
result += device->service(i)->characteristicCount();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLEDevice::hasCharacteristic(const char* uuid) const
|
||||
{
|
||||
return hasCharacteristic(uuid, 0);
|
||||
}
|
||||
|
||||
bool BLEDevice::hasCharacteristic(const char* uuid, int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int count = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
BLERemoteService* s = device->service(i);
|
||||
|
||||
int numCharacteristics = s->characteristicCount();
|
||||
|
||||
for (int j = 0; j < numCharacteristics; j++) {
|
||||
BLERemoteCharacteristic* c = s->characteristic(j);
|
||||
|
||||
|
||||
if (strcasecmp(c->uuid(), uuid) == 0) {
|
||||
if (count == index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLECharacteristic BLEDevice::characteristic(int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int count = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
BLERemoteService* s = device->service(i);
|
||||
|
||||
int numCharacteristics = s->characteristicCount();
|
||||
|
||||
for (int j = 0; j < numCharacteristics; j++) {
|
||||
if (count == index) {
|
||||
BLERemoteCharacteristic* c = s->characteristic(j);
|
||||
|
||||
return BLECharacteristic(c);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLECharacteristic();
|
||||
}
|
||||
|
||||
BLECharacteristic BLEDevice::characteristic(const char * uuid) const
|
||||
{
|
||||
return characteristic(uuid, 0);
|
||||
}
|
||||
|
||||
BLECharacteristic BLEDevice::characteristic(const char * uuid, int index) const
|
||||
{
|
||||
BLERemoteDevice* device = ATT.device(_addressType, _address);
|
||||
|
||||
if (device) {
|
||||
int count = 0;
|
||||
int numServices = device->serviceCount();
|
||||
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
BLERemoteService* s = device->service(i);
|
||||
|
||||
int numCharacteristics = s->characteristicCount();
|
||||
|
||||
for (int j = 0; j < numCharacteristics; j++) {
|
||||
BLERemoteCharacteristic* c = s->characteristic(j);
|
||||
|
||||
if (strcasecmp(c->uuid(), uuid) == 0) {
|
||||
if (count == index) {
|
||||
|
||||
return BLECharacteristic(c);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLECharacteristic();
|
||||
}
|
||||
|
||||
bool BLEDevice::hasAddress(uint8_t addressType, uint8_t address[6])
|
||||
{
|
||||
return (_addressType == addressType) && (memcmp(_address, address, sizeof(_address)) == 0);
|
||||
}
|
||||
|
||||
void BLEDevice::setAdvertisementData(uint8_t type, uint8_t eirDataLength, uint8_t eirData[], int8_t rssi)
|
||||
{
|
||||
_advertisementTypeMask = (1 << type);
|
||||
_eirDataLength = eirDataLength;
|
||||
memcpy(_eirData, eirData, eirDataLength);
|
||||
_rssi = rssi;
|
||||
}
|
||||
|
||||
void BLEDevice::setScanResponseData(uint8_t eirDataLength, uint8_t eirData[], int8_t rssi)
|
||||
{
|
||||
_advertisementTypeMask |= (1 << 0x04);
|
||||
memcpy(&_eirData[_eirDataLength], eirData, eirDataLength);
|
||||
_eirDataLength += eirDataLength;
|
||||
_rssi = rssi;
|
||||
}
|
||||
|
||||
bool BLEDevice::discovered()
|
||||
{
|
||||
// expect, 0x03 or 0x04 flag to be set
|
||||
return (_advertisementTypeMask & 0x18) != 0;
|
||||
}
|
||||
|
121
lib/ArduinoBLE/src/BLEDevice.h
Normal file
121
lib/ArduinoBLE/src/BLEDevice.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_DEVICE_H_
|
||||
#define _BLE_DEVICE_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BLEService.h"
|
||||
|
||||
enum BLEDeviceEvent {
|
||||
BLEConnected = 0,
|
||||
BLEDisconnected = 1,
|
||||
BLEDiscovered = 2,
|
||||
|
||||
BLEDeviceLastEvent
|
||||
};
|
||||
|
||||
class BLEDevice;
|
||||
|
||||
typedef void (*BLEDeviceEventHandler)(BLEDevice device);
|
||||
|
||||
class BLEDevice {
|
||||
public:
|
||||
BLEDevice();
|
||||
virtual ~BLEDevice();
|
||||
|
||||
virtual void poll();
|
||||
virtual void poll(unsigned long timeout);
|
||||
|
||||
virtual bool connected() const;
|
||||
virtual bool disconnect();
|
||||
|
||||
virtual String address() const;
|
||||
|
||||
bool hasLocalName() const;
|
||||
|
||||
bool hasAdvertisedServiceUuid() const;
|
||||
bool hasAdvertisedServiceUuid(int index) const;
|
||||
int advertisedServiceUuidCount() const;
|
||||
|
||||
String localName() const;
|
||||
String advertisedServiceUuid() const;
|
||||
String advertisedServiceUuid(int index) const;
|
||||
|
||||
bool hasAdvertisementData() const;
|
||||
int advertisementDataLength() const;
|
||||
int advertisementData(uint8_t value[], int length) const;
|
||||
|
||||
bool hasManufacturerData() const;
|
||||
int manufacturerDataLength() const;
|
||||
int manufacturerData(uint8_t value[], int length) const;
|
||||
|
||||
virtual int rssi();
|
||||
|
||||
bool connect();
|
||||
bool discoverAttributes();
|
||||
bool discoverService(const char* serviceUuid);
|
||||
|
||||
virtual operator bool() const;
|
||||
virtual bool operator==(const BLEDevice& rhs) const;
|
||||
virtual bool operator!=(const BLEDevice& rhs) const;
|
||||
|
||||
String deviceName();
|
||||
int appearance();
|
||||
|
||||
int serviceCount() const;
|
||||
bool hasService(const char* uuid) const;
|
||||
bool hasService(const char* uuid, int index) const;
|
||||
BLEService service(int index) const;
|
||||
BLEService service(const char * uuid) const;
|
||||
BLEService service(const char * uuid, int index) const;
|
||||
int characteristicCount() const;
|
||||
bool hasCharacteristic(const char* uuid) const;
|
||||
bool hasCharacteristic(const char* uuid, int index) const;
|
||||
BLECharacteristic characteristic(int index) const;
|
||||
BLECharacteristic characteristic(const char * uuid) const;
|
||||
BLECharacteristic characteristic(const char * uuid, int index) const;
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
friend class GAPClass;
|
||||
|
||||
BLEDevice(uint8_t addressType, uint8_t address[6]);
|
||||
|
||||
protected:
|
||||
friend class GAPClass;
|
||||
|
||||
bool hasAddress(uint8_t addressType, uint8_t address[6]);
|
||||
|
||||
void setAdvertisementData(uint8_t type, uint8_t eirDataLength, uint8_t eirData[], int8_t rssi);
|
||||
void setScanResponseData(uint8_t eirDataLength, uint8_t eirData[], int8_t rssi);
|
||||
|
||||
bool discovered();
|
||||
|
||||
private:
|
||||
uint8_t _addressType;
|
||||
uint8_t _address[6];
|
||||
uint8_t _advertisementTypeMask;
|
||||
uint8_t _eirDataLength;
|
||||
uint8_t _eirData[31 * 2];
|
||||
int8_t _rssi;
|
||||
};
|
||||
|
||||
#endif
|
79
lib/ArduinoBLE/src/BLEProperty.h
Normal file
79
lib/ArduinoBLE/src/BLEProperty.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// #include <stdint.h>
|
||||
|
||||
#ifndef _BLE_PROPERTY_H_
|
||||
#define _BLE_PROPERTY_H_
|
||||
|
||||
enum BLEProperty {
|
||||
BLEBroadcast = 0x01,
|
||||
BLERead = 0x02,
|
||||
BLEWriteWithoutResponse = 0x04,
|
||||
BLEWrite = 0x08,
|
||||
BLENotify = 0x10,
|
||||
BLEIndicate = 0x20,
|
||||
BLEAuthSignedWrite = 1 << 6,
|
||||
BLEExtProp = 1 << 7,
|
||||
};
|
||||
|
||||
enum BLEPermission {
|
||||
BLEEncryption = 1 << 9,
|
||||
BLEAuthentication = 1 << 10,
|
||||
BLEAuthorization = 1 << 11,
|
||||
// BLEWriteEncryption = 1 << 11,
|
||||
// BLEWriteAuthentication = 1 << 12,
|
||||
// BLEWriteAuthorization = 1 << 13,
|
||||
};
|
||||
|
||||
#define ESP_GATT_CHAR_PROP_BIT_BROADCAST (1 << 0) /* 0x01 */ /* relate to BTA_GATT_CHAR_PROP_BIT_BROADCAST in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_READ (1 << 1) /* 0x02 */ /* relate to BTA_GATT_CHAR_PROP_BIT_READ in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_WRITE_NR (1 << 2) /* 0x04 */ /* relate to BTA_GATT_CHAR_PROP_BIT_WRITE_NR in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_WRITE (1 << 3) /* 0x08 */ /* relate to BTA_GATT_CHAR_PROP_BIT_WRITE in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_NOTIFY (1 << 4) /* 0x10 */ /* relate to BTA_GATT_CHAR_PROP_BIT_NOTIFY in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_INDICATE (1 << 5) /* 0x20 */ /* relate to BTA_GATT_CHAR_PROP_BIT_INDICATE in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_AUTH (1 << 6) /* 0x40 */ /* relate to BTA_GATT_CHAR_PROP_BIT_AUTH in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_CHAR_PROP_BIT_EXT_PROP (1 << 7) /* 0x80 */ /* relate to BTA_GATT_CHAR_PROP_BIT_EXT_PROP in bta/bta_gatt_api.h */
|
||||
|
||||
#define ESP_GATT_PERM_READ (1 << 0) /* bit 0 - 0x0001 */ /* relate to BTA_GATT_PERM_READ in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_READ_ENCRYPTED (1 << 1) /* bit 1 - 0x0002 */ /* relate to BTA_GATT_PERM_READ_ENCRYPTED in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_READ_ENC_MITM (1 << 2) /* bit 2 - 0x0004 */ /* relate to BTA_GATT_PERM_READ_ENC_MITM in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_WRITE (1 << 4) /* bit 4 - 0x0010 */ /* relate to BTA_GATT_PERM_WRITE in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_WRITE_ENCRYPTED (1 << 5) /* bit 5 - 0x0020 */ /* relate to BTA_GATT_PERM_WRITE_ENCRYPTED in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 - 0x0040 */ /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 - 0x0080 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 - 0x0100 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */
|
||||
#define ESP_GATT_PERM_READ_AUTHORIZATION (1 << 9) /* bit 9 - 0x0200 */
|
||||
#define ESP_GATT_PERM_WRITE_AUTHORIZATION (1 << 10) /* bit 10 - 0x0400 */
|
||||
|
||||
enum BLE_GATT_PERM_ {
|
||||
BLE_GATT_READ = 1 << 0,
|
||||
READ_ENCRYPTED = 1 << 1,
|
||||
READ_ENC_MITM = 1 << 2,
|
||||
BLE_GATT_WRITE = 1 << 4,
|
||||
WRITE_ENCRYPTED = 1 << 5,
|
||||
WRITE_ENC_MITM = 1 << 6,
|
||||
WRITE_SIGNED = 1 << 7,
|
||||
WRITE_SIGNED_MITM = 1 << 8,
|
||||
READ_AUTHORIZATION = 1 << 9,
|
||||
WRITE_AUTHORIZATION = 1 << 10,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
186
lib/ArduinoBLE/src/BLEService.cpp
Normal file
186
lib/ArduinoBLE/src/BLEService.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "local/BLELocalService.h"
|
||||
#include "remote/BLERemoteService.h"
|
||||
|
||||
#include "BLEService.h"
|
||||
|
||||
extern "C" int strcasecmp(char const *a, char const *b);
|
||||
|
||||
BLEService::BLEService() :
|
||||
BLEService((BLELocalService*)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BLEService::BLEService(BLELocalService* local) :
|
||||
_local(local),
|
||||
_remote(NULL)
|
||||
{
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLEService::BLEService(BLERemoteService* remote) :
|
||||
_local(NULL),
|
||||
_remote(remote)
|
||||
{
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
BLEService::BLEService(const char* uuid) :
|
||||
BLEService(new BLELocalService(uuid))
|
||||
{
|
||||
}
|
||||
|
||||
BLEService::BLEService(const BLEService& other)
|
||||
{
|
||||
_local = other._local;
|
||||
if (_local) {
|
||||
_local->retain();
|
||||
}
|
||||
|
||||
_remote = other._remote;
|
||||
if (_remote) {
|
||||
_remote->retain();
|
||||
}
|
||||
}
|
||||
|
||||
void BLEService::clear()
|
||||
{
|
||||
if (_local) {
|
||||
_local->clear();
|
||||
}
|
||||
}
|
||||
|
||||
BLEService::~BLEService()
|
||||
{
|
||||
if (_local && _local->release() == 0) {
|
||||
delete _local;
|
||||
}
|
||||
|
||||
if (_remote && _remote->release() == 0) {
|
||||
delete _remote;
|
||||
}
|
||||
}
|
||||
|
||||
const char* BLEService::uuid() const
|
||||
{
|
||||
if (_local) {
|
||||
return _local->uuid();
|
||||
}
|
||||
|
||||
if (_remote) {
|
||||
return _remote->uuid();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void BLEService::addCharacteristic(BLECharacteristic& characteristic)
|
||||
{
|
||||
if (_local) {
|
||||
_local->addCharacteristic(characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
BLEService::operator bool() const
|
||||
{
|
||||
return (_local != NULL) || (_remote != NULL);
|
||||
}
|
||||
|
||||
int BLEService::characteristicCount() const
|
||||
{
|
||||
if (_remote) {
|
||||
return _remote->characteristicCount();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLEService::hasCharacteristic(const char* uuid) const
|
||||
{
|
||||
return hasCharacteristic(uuid, 0);
|
||||
}
|
||||
|
||||
bool BLEService::hasCharacteristic(const char* uuid, int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
int count = 0;
|
||||
int numCharacteristics = _remote->characteristicCount();
|
||||
|
||||
for (int i = 0; i < numCharacteristics; i++) {
|
||||
BLERemoteCharacteristic* c = _remote->characteristic(i);
|
||||
|
||||
if (strcasecmp(uuid, c->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLECharacteristic BLEService::characteristic(int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
return BLECharacteristic(_remote->characteristic(index));
|
||||
}
|
||||
|
||||
return BLECharacteristic();
|
||||
}
|
||||
|
||||
BLECharacteristic BLEService::characteristic(const char * uuid) const
|
||||
{
|
||||
return characteristic(uuid, 0);
|
||||
}
|
||||
|
||||
BLECharacteristic BLEService::characteristic(const char * uuid, int index) const
|
||||
{
|
||||
if (_remote) {
|
||||
int count = 0;
|
||||
int numCharacteristics = _remote->characteristicCount();
|
||||
|
||||
for (int i = 0; i < numCharacteristics; i++) {
|
||||
BLERemoteCharacteristic* c = _remote->characteristic(i);
|
||||
|
||||
if (strcasecmp(uuid, c->uuid()) == 0) {
|
||||
if (count == index) {
|
||||
return BLECharacteristic(c);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLECharacteristic();
|
||||
}
|
||||
|
||||
BLELocalService* BLEService::local()
|
||||
{
|
||||
return _local;
|
||||
}
|
68
lib/ArduinoBLE/src/BLEService.h
Normal file
68
lib/ArduinoBLE/src/BLEService.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_SERVICE_H_
|
||||
#define _BLE_SERVICE_H_
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
class BLELocalService;
|
||||
class BLERemoteService;
|
||||
|
||||
class BLEService {
|
||||
public:
|
||||
BLEService();
|
||||
BLEService(const char* uuid);
|
||||
BLEService(const BLEService& other);
|
||||
virtual ~BLEService();
|
||||
|
||||
const char* uuid() const;
|
||||
void clear();
|
||||
|
||||
void addCharacteristic(BLECharacteristic& characteristic);
|
||||
|
||||
operator bool() const;
|
||||
|
||||
int characteristicCount() const;
|
||||
bool hasCharacteristic(const char* uuid) const;
|
||||
bool hasCharacteristic(const char* uuid, int index) const;
|
||||
BLECharacteristic characteristic(int index) const;
|
||||
BLECharacteristic characteristic(const char * uuid) const;
|
||||
BLECharacteristic characteristic(const char * uuid, int index) const;
|
||||
|
||||
protected:
|
||||
friend class GATTClass;
|
||||
|
||||
BLEService(BLELocalService* local);
|
||||
|
||||
BLELocalService* local();
|
||||
|
||||
void addCharacteristic(BLELocalCharacteristic* characteristic);
|
||||
|
||||
protected:
|
||||
friend class BLEDevice;
|
||||
|
||||
BLEService(BLERemoteService* remote);
|
||||
|
||||
private:
|
||||
BLELocalService* _local;
|
||||
BLERemoteService* _remote;
|
||||
};
|
||||
|
||||
#endif
|
45
lib/ArduinoBLE/src/BLEStringCharacteristic.cpp
Normal file
45
lib/ArduinoBLE/src/BLEStringCharacteristic.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLEStringCharacteristic.h"
|
||||
|
||||
BLEStringCharacteristic::BLEStringCharacteristic(const char* uuid, unsigned int properties, int valueSize) :
|
||||
BLECharacteristic(uuid, properties, valueSize)
|
||||
{
|
||||
}
|
||||
|
||||
int BLEStringCharacteristic::writeValue(const String& value)
|
||||
{
|
||||
return BLECharacteristic::writeValue(value.c_str());
|
||||
}
|
||||
|
||||
String BLEStringCharacteristic::value(void)
|
||||
{
|
||||
String str;
|
||||
int length = BLECharacteristic::valueLength();
|
||||
const uint8_t* val = BLECharacteristic::value();
|
||||
|
||||
str.reserve(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
str += (char)val[i];
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
39
lib/ArduinoBLE/src/BLEStringCharacteristic.h
Normal file
39
lib/ArduinoBLE/src/BLEStringCharacteristic.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_STRING_CHARACTERISTIC_H_
|
||||
#define _BLE_STRING_CHARACTERISTIC_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
class BLEStringCharacteristic : public BLECharacteristic
|
||||
{
|
||||
public:
|
||||
BLEStringCharacteristic(const char* uuid, unsigned int properties, int valueSize);
|
||||
|
||||
int writeValue(const String& value);
|
||||
int setValue(const String& value) { return writeValue(value); }
|
||||
String value(void);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
102
lib/ArduinoBLE/src/BLETypedCharacteristic.h
Normal file
102
lib/ArduinoBLE/src/BLETypedCharacteristic.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_TYPED_CHARACTERISTIC_H_
|
||||
#define _BLE_TYPED_CHARACTERISTIC_H_
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
template<typename T> class BLETypedCharacteristic : public BLECharacteristic
|
||||
{
|
||||
public:
|
||||
BLETypedCharacteristic(const char* uuid, unsigned int permissions);
|
||||
|
||||
int writeValue(T value);
|
||||
int setValue(T value) { return writeValue(value); }
|
||||
T value(void);
|
||||
|
||||
int writeValueLE(T value);
|
||||
int setValueLE(T value) { return writeValueLE(value); }
|
||||
T valueLE(void);
|
||||
|
||||
int writeValueBE(T value);
|
||||
int setValueBE(T value) { return writeValueBE(value); }
|
||||
T valueBE(void);
|
||||
|
||||
private:
|
||||
T byteSwap(T value);
|
||||
};
|
||||
|
||||
template<typename T> BLETypedCharacteristic<T>::BLETypedCharacteristic(const char* uuid, unsigned int permissions) :
|
||||
BLECharacteristic(uuid, permissions, sizeof(T), true)
|
||||
{
|
||||
T value;
|
||||
memset(&value, 0x00, sizeof(value));
|
||||
|
||||
writeValue(value);
|
||||
}
|
||||
|
||||
template<typename T> int BLETypedCharacteristic<T>::writeValue(T value)
|
||||
{
|
||||
return BLECharacteristic::writeValue((uint8_t*)&value, sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T> T BLETypedCharacteristic<T>::value()
|
||||
{
|
||||
T value;
|
||||
|
||||
memcpy(&value, (unsigned char*)BLECharacteristic::value(), BLECharacteristic::valueSize());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T> int BLETypedCharacteristic<T>::writeValueLE(T value)
|
||||
{
|
||||
return writeValue(value);
|
||||
}
|
||||
|
||||
template<typename T> T BLETypedCharacteristic<T>::valueLE()
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
template<typename T> int BLETypedCharacteristic<T>::writeValueBE(T value)
|
||||
{
|
||||
return writeValue(byteSwap(value));
|
||||
}
|
||||
|
||||
template<typename T> T BLETypedCharacteristic<T>::valueBE()
|
||||
{
|
||||
return byteSwap(value());
|
||||
}
|
||||
|
||||
template<typename T> T BLETypedCharacteristic<T>::byteSwap(T value)
|
||||
{
|
||||
T result;
|
||||
unsigned char* src = (unsigned char*)&value;
|
||||
unsigned char* dst = (unsigned char*)&result;
|
||||
|
||||
for (int i = 0; i < sizeof(T); i++) {
|
||||
dst[i] = src[sizeof(T) - i - 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
92
lib/ArduinoBLE/src/BLETypedCharacteristics.cpp
Normal file
92
lib/ArduinoBLE/src/BLETypedCharacteristics.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BLETypedCharacteristics.h"
|
||||
|
||||
BLEBoolCharacteristic::BLEBoolCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<bool>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEBooleanCharacteristic::BLEBooleanCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<bool>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLECharCharacteristic::BLECharCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<char>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEUnsignedCharCharacteristic::BLEUnsignedCharCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<unsigned char>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEByteCharacteristic::BLEByteCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<byte>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEShortCharacteristic::BLEShortCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<short>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEUnsignedShortCharacteristic::BLEUnsignedShortCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<unsigned short>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEWordCharacteristic::BLEWordCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<word>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEIntCharacteristic::BLEIntCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<int>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEUnsignedIntCharacteristic::BLEUnsignedIntCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<unsigned int>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLELongCharacteristic::BLELongCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<long>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEUnsignedLongCharacteristic::BLEUnsignedLongCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<unsigned long>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEFloatCharacteristic::BLEFloatCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<float>(uuid, properties)
|
||||
{
|
||||
}
|
||||
|
||||
BLEDoubleCharacteristic::BLEDoubleCharacteristic(const char* uuid, unsigned int properties) :
|
||||
BLETypedCharacteristic<double>(uuid, properties)
|
||||
{
|
||||
}
|
95
lib/ArduinoBLE/src/BLETypedCharacteristics.h
Normal file
95
lib/ArduinoBLE/src/BLETypedCharacteristics.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_TYPED_CHARACTERISTICS_H_
|
||||
#define _BLE_TYPED_CHARACTERISTICS_H_
|
||||
|
||||
#include "BLETypedCharacteristic.h"
|
||||
|
||||
class BLEBoolCharacteristic : public BLETypedCharacteristic<bool> {
|
||||
public:
|
||||
BLEBoolCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEBooleanCharacteristic : public BLETypedCharacteristic<bool> {
|
||||
public:
|
||||
BLEBooleanCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLECharCharacteristic : public BLETypedCharacteristic<char> {
|
||||
public:
|
||||
BLECharCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEUnsignedCharCharacteristic : public BLETypedCharacteristic<unsigned char> {
|
||||
public:
|
||||
BLEUnsignedCharCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEByteCharacteristic : public BLETypedCharacteristic<byte> {
|
||||
public:
|
||||
BLEByteCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEShortCharacteristic : public BLETypedCharacteristic<short> {
|
||||
public:
|
||||
BLEShortCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEUnsignedShortCharacteristic : public BLETypedCharacteristic<unsigned short> {
|
||||
public:
|
||||
BLEUnsignedShortCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEWordCharacteristic : public BLETypedCharacteristic<word> {
|
||||
public:
|
||||
BLEWordCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEIntCharacteristic : public BLETypedCharacteristic<int> {
|
||||
public:
|
||||
BLEIntCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEUnsignedIntCharacteristic : public BLETypedCharacteristic<unsigned int> {
|
||||
public:
|
||||
BLEUnsignedIntCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLELongCharacteristic : public BLETypedCharacteristic<long> {
|
||||
public:
|
||||
BLELongCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEUnsignedLongCharacteristic : public BLETypedCharacteristic<unsigned long> {
|
||||
public:
|
||||
BLEUnsignedLongCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEFloatCharacteristic : public BLETypedCharacteristic<float> {
|
||||
public:
|
||||
BLEFloatCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
class BLEDoubleCharacteristic : public BLETypedCharacteristic<double> {
|
||||
public:
|
||||
BLEDoubleCharacteristic(const char* uuid, unsigned int permissions);
|
||||
};
|
||||
|
||||
#endif
|
69
lib/ArduinoBLE/src/local/BLELocalAttribute.cpp
Normal file
69
lib/ArduinoBLE/src/local/BLELocalAttribute.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLELocalAttribute.h"
|
||||
|
||||
BLELocalAttribute::BLELocalAttribute(const char* uuid) :
|
||||
_uuid(uuid),
|
||||
_refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLELocalAttribute::~BLELocalAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
const char* BLELocalAttribute::uuid() const
|
||||
{
|
||||
return _uuid.str();
|
||||
}
|
||||
|
||||
const uint8_t* BLELocalAttribute::uuidData() const
|
||||
{
|
||||
return _uuid.data();
|
||||
}
|
||||
|
||||
uint8_t BLELocalAttribute::uuidLength() const
|
||||
{
|
||||
return _uuid.length();
|
||||
}
|
||||
|
||||
enum BLEAttributeType BLELocalAttribute::type() const
|
||||
{
|
||||
return BLETypeUnknown;
|
||||
}
|
||||
|
||||
int BLELocalAttribute::retain()
|
||||
{
|
||||
_refCount++;
|
||||
|
||||
return _refCount;
|
||||
}
|
||||
|
||||
bool BLELocalAttribute::active()
|
||||
{
|
||||
return _refCount > 0;
|
||||
}
|
||||
|
||||
int BLELocalAttribute::release()
|
||||
{
|
||||
_refCount--;
|
||||
|
||||
return _refCount;
|
||||
}
|
61
lib/ArduinoBLE/src/local/BLELocalAttribute.h
Normal file
61
lib/ArduinoBLE/src/local/BLELocalAttribute.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LOCAL_ATTRIBUTE_H_
|
||||
#define _BLE_LOCAL_ATTRIBUTE_H_
|
||||
|
||||
#include "utility/BLEUuid.h"
|
||||
|
||||
#define BLE_ATTRIBUTE_TYPE_SIZE 2
|
||||
|
||||
enum BLEAttributeType {
|
||||
BLETypeUnknown = 0x0000,
|
||||
|
||||
BLETypeService = 0x2800,
|
||||
BLETypeCharacteristic = 0x2803,
|
||||
BLETypeDescriptor = 0x2900
|
||||
};
|
||||
|
||||
class BLELocalAttribute
|
||||
{
|
||||
public:
|
||||
BLELocalAttribute(const char* uuid);
|
||||
virtual ~BLELocalAttribute();
|
||||
|
||||
const char* uuid() const;
|
||||
|
||||
virtual enum BLEAttributeType type() const;
|
||||
|
||||
int retain();
|
||||
int release();
|
||||
bool active();
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
friend class GATTClass;
|
||||
|
||||
const uint8_t* uuidData() const;
|
||||
uint8_t uuidLength() const;
|
||||
|
||||
private:
|
||||
BLEUuid _uuid;
|
||||
int _refCount;
|
||||
};
|
||||
|
||||
#endif
|
244
lib/ArduinoBLE/src/local/BLELocalCharacteristic.cpp
Normal file
244
lib/ArduinoBLE/src/local/BLELocalCharacteristic.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "BLELocalDevice.h"
|
||||
|
||||
#include "utility/ATT.h"
|
||||
#include "utility/GAP.h"
|
||||
#include "utility/GATT.h"
|
||||
|
||||
#include "BLELocalDescriptor.h"
|
||||
#include "BLEProperty.h"
|
||||
|
||||
#include "BLELocalCharacteristic.h"
|
||||
|
||||
BLELocalCharacteristic::BLELocalCharacteristic(const char* uuid, uint16_t permissions, int valueSize, bool fixedLength) :
|
||||
BLELocalAttribute(uuid),
|
||||
_properties((uint8_t)(permissions&0x000FF)),
|
||||
_permissions((uint8_t)((permissions&0xFF00)>>8)),
|
||||
_valueSize(min(valueSize, 512)),
|
||||
_valueLength(0),
|
||||
_fixedLength(fixedLength),
|
||||
_handle(0x0000),
|
||||
_broadcast(false),
|
||||
_written(false),
|
||||
_cccdValue(0x0000)
|
||||
{
|
||||
memset(_eventHandlers, 0x00, sizeof(_eventHandlers));
|
||||
|
||||
if (permissions & (BLENotify | BLEIndicate)) {
|
||||
BLELocalDescriptor* cccd = new BLELocalDescriptor("2902", (uint8_t*)&_cccdValue, sizeof(_cccdValue));
|
||||
|
||||
cccd->retain();
|
||||
_descriptors.add(cccd);
|
||||
}
|
||||
|
||||
_value = (uint8_t*)malloc(valueSize);
|
||||
}
|
||||
|
||||
BLELocalCharacteristic::BLELocalCharacteristic(const char* uuid, uint16_t permissions, const char* value) :
|
||||
BLELocalCharacteristic(uuid, permissions, strlen(value))
|
||||
{
|
||||
writeValue(value);
|
||||
}
|
||||
BLELocalCharacteristic::~BLELocalCharacteristic()
|
||||
{
|
||||
for (unsigned int i = 0; i < descriptorCount(); i++) {
|
||||
BLELocalDescriptor* d = descriptor(i);
|
||||
|
||||
if (d->release() == 0) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
_descriptors.clear();
|
||||
|
||||
if (_value) {
|
||||
free(_value);
|
||||
}
|
||||
}
|
||||
|
||||
enum BLEAttributeType BLELocalCharacteristic::type() const
|
||||
{
|
||||
return BLETypeCharacteristic;
|
||||
}
|
||||
|
||||
uint8_t BLELocalCharacteristic::properties() const
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
uint8_t BLELocalCharacteristic::permissions() const {
|
||||
return _permissions;
|
||||
}
|
||||
|
||||
int BLELocalCharacteristic::valueSize() const
|
||||
{
|
||||
return _valueSize;
|
||||
}
|
||||
|
||||
const uint8_t* BLELocalCharacteristic::value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
int BLELocalCharacteristic::valueLength() const
|
||||
{
|
||||
return _valueLength;
|
||||
}
|
||||
|
||||
uint8_t BLELocalCharacteristic::operator[] (int offset) const
|
||||
{
|
||||
return _value[offset];
|
||||
}
|
||||
|
||||
int BLELocalCharacteristic::writeValue(const uint8_t value[], int length)
|
||||
{
|
||||
_valueLength = min(length, _valueSize);
|
||||
memcpy(_value, value, _valueLength);
|
||||
|
||||
if (_fixedLength) {
|
||||
_valueLength = _valueSize;
|
||||
}
|
||||
|
||||
if ((_properties & BLEIndicate) && (_cccdValue & 0x0002)) {
|
||||
return ATT.handleInd(valueHandle(), _value, _valueLength);
|
||||
} else if ((_properties & BLENotify) && (_cccdValue & 0x0001)) {
|
||||
return ATT.handleNotify(valueHandle(), _value, _valueLength);
|
||||
}
|
||||
|
||||
if (_broadcast) {
|
||||
uint16_t serviceUuid = GATT.serviceUuidForCharacteristic(this);
|
||||
BLE.setAdvertisedServiceData(serviceUuid, value, _valueLength);
|
||||
if (!ATT.connected() && GAP.advertising()) {
|
||||
BLE.advertise();
|
||||
}
|
||||
}
|
||||
|
||||
return _valueLength;
|
||||
}
|
||||
|
||||
int BLELocalCharacteristic::writeValue(const char* value)
|
||||
{
|
||||
return writeValue((uint8_t*)value, strlen(value));
|
||||
}
|
||||
|
||||
int BLELocalCharacteristic::broadcast()
|
||||
{
|
||||
if (_properties & BLEBroadcast) {
|
||||
_broadcast = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BLELocalCharacteristic::written()
|
||||
{
|
||||
bool written = _written;
|
||||
|
||||
_written = false;
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool BLELocalCharacteristic::subscribed()
|
||||
{
|
||||
return (_cccdValue != 0x0000);
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::addDescriptor(BLEDescriptor& descriptor)
|
||||
{
|
||||
BLELocalDescriptor* localDescriptor = descriptor.local();
|
||||
|
||||
if (localDescriptor) {
|
||||
localDescriptor->retain();
|
||||
|
||||
_descriptors.add(localDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler eventHandler)
|
||||
{
|
||||
if (event < (sizeof(_eventHandlers) / sizeof(_eventHandlers[0]))) {
|
||||
_eventHandlers[event] = eventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::setHandle(uint16_t handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
uint16_t BLELocalCharacteristic::handle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
||||
|
||||
uint16_t BLELocalCharacteristic::valueHandle() const
|
||||
{
|
||||
return (_handle + 1);
|
||||
}
|
||||
|
||||
unsigned int BLELocalCharacteristic::descriptorCount() const
|
||||
{
|
||||
return _descriptors.size();
|
||||
}
|
||||
|
||||
BLELocalDescriptor* BLELocalCharacteristic::descriptor(unsigned int index) const
|
||||
{
|
||||
return _descriptors.get(index);
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::readValue(BLEDevice device, uint16_t offset, uint8_t value[], int length)
|
||||
{
|
||||
if (_eventHandlers[BLERead]) {
|
||||
_eventHandlers[BLERead](device, BLECharacteristic(this));
|
||||
}
|
||||
|
||||
memcpy(value, _value + offset, length);
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::writeValue(BLEDevice device, const uint8_t value[], int length)
|
||||
{
|
||||
_written = true;
|
||||
|
||||
writeValue(value, length);
|
||||
|
||||
if (_eventHandlers[BLEWritten]) {
|
||||
_eventHandlers[BLEWritten](device, BLECharacteristic(this));
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalCharacteristic::writeCccdValue(BLEDevice device, uint16_t value)
|
||||
{
|
||||
value &= 0x0003;
|
||||
|
||||
if (_cccdValue != value) {
|
||||
_cccdValue = value;
|
||||
|
||||
BLECharacteristicEvent event = (_cccdValue) ? BLESubscribed : BLEUnsubscribed;
|
||||
|
||||
if (_eventHandlers[event]) {
|
||||
_eventHandlers[event](device, BLECharacteristic(this));
|
||||
}
|
||||
}
|
||||
}
|
96
lib/ArduinoBLE/src/local/BLELocalCharacteristic.h
Normal file
96
lib/ArduinoBLE/src/local/BLELocalCharacteristic.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LOCAL_CHARACTERISTIC_H_
|
||||
#define _BLE_LOCAL_CHARACTERISTIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
#include "BLEDescriptor.h"
|
||||
|
||||
#include "BLELocalAttribute.h"
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
class BLELocalDescriptor;
|
||||
|
||||
class BLELocalCharacteristic : public BLELocalAttribute {
|
||||
public:
|
||||
BLELocalCharacteristic(const char* uuid, uint16_t permissions, int valueSize, bool fixedLength = false);
|
||||
BLELocalCharacteristic(const char* uuid, uint16_t permissions, const char* value);
|
||||
virtual ~BLELocalCharacteristic();
|
||||
|
||||
virtual enum BLEAttributeType type() const;
|
||||
|
||||
uint8_t properties() const;
|
||||
uint8_t permissions() const;
|
||||
|
||||
int valueSize() const;
|
||||
const uint8_t* value() const;
|
||||
int valueLength() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
int writeValue(const uint8_t value[], int length);
|
||||
int writeValue(const char* value);
|
||||
|
||||
int broadcast();
|
||||
|
||||
bool written();
|
||||
bool subscribed();
|
||||
|
||||
void addDescriptor(BLEDescriptor& descriptor);
|
||||
|
||||
void setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler eventHandler);
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
friend class GATTClass;
|
||||
|
||||
void setHandle(uint16_t handle);
|
||||
uint16_t handle() const;
|
||||
uint16_t valueHandle() const;
|
||||
|
||||
unsigned int descriptorCount() const;
|
||||
BLELocalDescriptor* descriptor(unsigned int index) const;
|
||||
|
||||
void readValue(BLEDevice device, uint16_t offset, uint8_t value[], int length);
|
||||
void writeValue(BLEDevice device, const uint8_t value[], int length);
|
||||
void writeCccdValue(BLEDevice device, uint16_t value);
|
||||
|
||||
private:
|
||||
uint8_t _properties;
|
||||
uint8_t _permissions;
|
||||
int _valueSize;
|
||||
uint8_t* _value;
|
||||
uint16_t _valueLength;
|
||||
bool _fixedLength;
|
||||
|
||||
uint16_t _handle;
|
||||
|
||||
bool _broadcast;
|
||||
bool _written;
|
||||
|
||||
uint16_t _cccdValue;
|
||||
BLELinkedList<BLELocalDescriptor*> _descriptors;
|
||||
|
||||
BLECharacteristicEventHandler _eventHandlers[BLECharacteristicEventLast];
|
||||
};
|
||||
|
||||
#endif
|
69
lib/ArduinoBLE/src/local/BLELocalDescriptor.cpp
Normal file
69
lib/ArduinoBLE/src/local/BLELocalDescriptor.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BLELocalDescriptor.h"
|
||||
|
||||
BLELocalDescriptor::BLELocalDescriptor(const char* uuid, const uint8_t value[], int valueSize) :
|
||||
BLELocalAttribute(uuid),
|
||||
_value(value),
|
||||
_valueSize(min(valueSize, 512)),
|
||||
_handle(0x0000)
|
||||
{
|
||||
}
|
||||
|
||||
BLELocalDescriptor::BLELocalDescriptor(const char* uuid, const char* value) :
|
||||
BLELocalDescriptor(uuid, (const uint8_t*)value, strlen(value))
|
||||
{
|
||||
}
|
||||
|
||||
BLELocalDescriptor::~BLELocalDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
enum BLEAttributeType BLELocalDescriptor::type() const
|
||||
{
|
||||
return BLETypeDescriptor;
|
||||
}
|
||||
|
||||
int BLELocalDescriptor::valueSize() const
|
||||
{
|
||||
return _valueSize;
|
||||
}
|
||||
|
||||
const uint8_t* BLELocalDescriptor::value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
uint8_t BLELocalDescriptor::operator[] (int offset) const
|
||||
{
|
||||
return _value[offset];
|
||||
}
|
||||
|
||||
void BLELocalDescriptor::setHandle(uint16_t handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
uint16_t BLELocalDescriptor::handle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
52
lib/ArduinoBLE/src/local/BLELocalDescriptor.h
Normal file
52
lib/ArduinoBLE/src/local/BLELocalDescriptor.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LOCAL_DESCRIPTOR_H_
|
||||
#define _BLE_LOCAL_DESCRIPTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "BLELocalAttribute.h"
|
||||
|
||||
class BLELocalDescriptor : public BLELocalAttribute {
|
||||
public:
|
||||
BLELocalDescriptor(const char* uuid, const uint8_t value[], int valueSize);
|
||||
BLELocalDescriptor(const char* uuid, const char* value);
|
||||
virtual ~BLELocalDescriptor();
|
||||
|
||||
virtual enum BLEAttributeType type() const;
|
||||
|
||||
int valueSize() const;
|
||||
const uint8_t* value() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
protected:
|
||||
friend class GATTClass;
|
||||
|
||||
void setHandle(uint16_t handle);
|
||||
uint16_t handle() const;
|
||||
|
||||
private:
|
||||
const uint8_t* _value;
|
||||
int _valueSize;
|
||||
|
||||
uint16_t _handle;
|
||||
};
|
||||
|
||||
#endif
|
489
lib/ArduinoBLE/src/local/BLELocalDevice.cpp
Normal file
489
lib/ArduinoBLE/src/local/BLELocalDevice.cpp
Normal file
@ -0,0 +1,489 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "utility/ATT.h"
|
||||
#include "utility/HCI.h"
|
||||
#include "utility/GAP.h"
|
||||
#include "utility/GATT.h"
|
||||
#include "utility/L2CAPSignaling.h"
|
||||
|
||||
#include "BLELocalDevice.h"
|
||||
|
||||
#if defined(PORTENTA_H7_PINS) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_OPTA)
|
||||
#ifndef BT_REG_ON
|
||||
#define BT_REG_ON PJ_12
|
||||
#endif
|
||||
#elif defined(ARDUINO_NICLA_VISION)
|
||||
#ifndef BT_REG_ON
|
||||
#define BT_REG_ON PF_14
|
||||
#endif
|
||||
#elif defined(ARDUINO_GIGA)
|
||||
#ifndef BT_REG_ON
|
||||
#define BT_REG_ON PA_10
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BLELocalDevice::BLELocalDevice()
|
||||
{
|
||||
_advertisingData.setFlags(BLEFlagsGeneralDiscoverable | BLEFlagsBREDRNotSupported);
|
||||
}
|
||||
|
||||
BLELocalDevice::~BLELocalDevice()
|
||||
{
|
||||
}
|
||||
|
||||
int BLELocalDevice::begin()
|
||||
{
|
||||
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT)
|
||||
// reset the NINA in BLE mode
|
||||
pinMode(SPIWIFI_SS, OUTPUT);
|
||||
pinMode(NINA_RESETN, OUTPUT);
|
||||
|
||||
digitalWrite(SPIWIFI_SS, LOW);
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
|
||||
digitalWrite(NINA_RESETN, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(NINA_RESETN, LOW);
|
||||
delay(750);
|
||||
#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT)
|
||||
// inverted reset
|
||||
digitalWrite(NINA_RESETN, LOW);
|
||||
delay(100);
|
||||
digitalWrite(NINA_RESETN, HIGH);
|
||||
delay(750);
|
||||
#elif defined(PORTENTA_H7_PINS) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)
|
||||
// BT_REG_ON -> HIGH
|
||||
pinMode(BT_REG_ON, OUTPUT);
|
||||
digitalWrite(BT_REG_ON, LOW);
|
||||
delay(500);
|
||||
digitalWrite(BT_REG_ON, HIGH);
|
||||
delay(500);
|
||||
#elif defined(ARDUINO_PORTENTA_C33)
|
||||
#define NINA_GPIO0 (100)
|
||||
#define NINA_RESETN (101)
|
||||
pinMode(NINA_GPIO0, OUTPUT);
|
||||
pinMode(NINA_RESETN, OUTPUT);
|
||||
Serial5.begin(921600);
|
||||
|
||||
digitalWrite(NINA_GPIO0, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(NINA_RESETN, HIGH);
|
||||
digitalWrite(NINA_RESETN, LOW);
|
||||
digitalWrite(NINA_RESETN, HIGH);
|
||||
auto _start = millis();
|
||||
while (millis() - _start < 500) {
|
||||
if (Serial5.available()) {
|
||||
Serial5.read();
|
||||
}
|
||||
}
|
||||
//pinMode(94, OUTPUT);
|
||||
//digitalWrite(94, LOW);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ARDUINO_AVR_UNO_WIFI_REV2
|
||||
// set SS HIGH
|
||||
digitalWrite(SPIWIFI_SS, HIGH);
|
||||
|
||||
// set RTS HIGH
|
||||
pinMode(NINA_RTS, OUTPUT);
|
||||
digitalWrite(NINA_RTS, HIGH);
|
||||
|
||||
// set CTS as input
|
||||
pinMode(NINA_CTS, INPUT);
|
||||
#endif
|
||||
|
||||
if (!HCI.begin()) {
|
||||
end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
if (HCI.reset() != 0) {
|
||||
end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t hciVer;
|
||||
uint16_t hciRev;
|
||||
uint8_t lmpVer;
|
||||
uint16_t manufacturer;
|
||||
uint16_t lmpSubVer;
|
||||
|
||||
if (HCI.readLocalVersion(hciVer, hciRev, lmpVer, manufacturer, lmpSubVer) != 0) {
|
||||
end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HCI.setEventMask(0x3FFFFFFFFFFFFFFF) != 0) {
|
||||
end();
|
||||
return 0;
|
||||
}
|
||||
if (HCI.setLeEventMask(0x00000000000003FF) != 0) {
|
||||
end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t pktLen;
|
||||
uint8_t maxPkt;
|
||||
|
||||
if (HCI.readLeBufferSize(pktLen, maxPkt) != 0) {
|
||||
end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// The HCI should allow automatic address resolution.
|
||||
|
||||
// // If we have callbacks to remember bonded devices:
|
||||
// if(HCI._getIRKs!=0){
|
||||
// uint8_t nIRKs = 0;
|
||||
// uint8_t** BADDR_Type = new uint8_t*;
|
||||
// uint8_t*** BADDRs = new uint8_t**;
|
||||
// uint8_t*** IRKs = new uint8_t**;
|
||||
// uint8_t* memcheck;
|
||||
|
||||
|
||||
// if(!HCI._getIRKs(&nIRKs, BADDR_Type, BADDRs, IRKs)){
|
||||
// Serial.println("error");
|
||||
// }
|
||||
// for(int i=0; i<nIRKs; i++){
|
||||
// Serial.print("Baddr type: ");
|
||||
// Serial.println((*BADDR_Type)[i]);
|
||||
// Serial.print("BADDR:");
|
||||
// for(int k=0; k<6; k++){
|
||||
// Serial.print(", 0x");
|
||||
// Serial.print((*BADDRs)[i][k],HEX);
|
||||
// }
|
||||
// Serial.println();
|
||||
// Serial.print("IRK:");
|
||||
// for(int k=0; k<16; k++){
|
||||
// Serial.print(", 0x");
|
||||
// Serial.print((*IRKs)[i][k],HEX);
|
||||
// }
|
||||
// Serial.println();
|
||||
|
||||
// // save this
|
||||
// uint8_t zeros[16];
|
||||
// for(int k=0; k<16; k++) zeros[15-k] = 0;
|
||||
|
||||
// // HCI.leAddResolvingAddress((*BADDR_Type)[i],(*BADDRs)[i],(*IRKs)[i], zeros);
|
||||
|
||||
// delete[] (*BADDRs)[i];
|
||||
// delete[] (*IRKs)[i];
|
||||
// }
|
||||
// delete[] (*BADDR_Type);
|
||||
// delete BADDR_Type;
|
||||
// delete[] (*BADDRs);
|
||||
// delete BADDRs;
|
||||
// delete[] (*IRKs);
|
||||
// delete IRKs;
|
||||
|
||||
// memcheck = new uint8_t[1];
|
||||
// Serial.print("nIRK location: 0x");
|
||||
// Serial.println((int)memcheck,HEX);
|
||||
// delete[] memcheck;
|
||||
|
||||
// }
|
||||
|
||||
GATT.begin();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BLELocalDevice::end()
|
||||
{
|
||||
GATT.end();
|
||||
|
||||
HCI.end();
|
||||
|
||||
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
|
||||
// disable the NINA
|
||||
digitalWrite(NINA_RESETN, HIGH);
|
||||
#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT)
|
||||
// disable the NINA
|
||||
digitalWrite(NINA_RESETN, LOW);
|
||||
#elif defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)
|
||||
digitalWrite(BT_REG_ON, LOW);
|
||||
#endif
|
||||
_advertisingData.clear();
|
||||
_scanResponseData.clear();
|
||||
}
|
||||
|
||||
void BLELocalDevice::poll()
|
||||
{
|
||||
HCI.poll();
|
||||
}
|
||||
|
||||
void BLELocalDevice::poll(unsigned long timeout)
|
||||
{
|
||||
HCI.poll(timeout);
|
||||
}
|
||||
|
||||
bool BLELocalDevice::connected() const
|
||||
{
|
||||
HCI.poll();
|
||||
|
||||
return ATT.connected();
|
||||
}
|
||||
|
||||
/*
|
||||
* Whether there is at least one paired device
|
||||
*/
|
||||
bool BLELocalDevice::paired()
|
||||
{
|
||||
HCI.poll();
|
||||
|
||||
return ATT.paired();
|
||||
}
|
||||
|
||||
bool BLELocalDevice::disconnect()
|
||||
{
|
||||
return ATT.disconnect();
|
||||
}
|
||||
|
||||
String BLELocalDevice::address() const
|
||||
{
|
||||
uint8_t addr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
HCI.readBdAddr(addr);
|
||||
|
||||
char result[18];
|
||||
sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int BLELocalDevice::rssi()
|
||||
{
|
||||
BLEDevice central = ATT.central();
|
||||
|
||||
if (central) {
|
||||
return central.rssi();
|
||||
}
|
||||
|
||||
return 127;
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setAdvertisedServiceUuid(const char* advertisedServiceUuid)
|
||||
{
|
||||
return _advertisingData.setAdvertisedServiceUuid(advertisedServiceUuid);
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setAdvertisedService(const BLEService& service)
|
||||
{
|
||||
return setAdvertisedServiceUuid(service.uuid());
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length)
|
||||
{
|
||||
return _advertisingData.setAdvertisedServiceData(uuid, data, length);
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
return _advertisingData.setManufacturerData(manufacturerData, manufacturerDataLength);
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength)
|
||||
{
|
||||
return _advertisingData.setManufacturerData(companyId, manufacturerData, manufacturerDataLength);
|
||||
}
|
||||
|
||||
bool BLELocalDevice::setLocalName(const char *localName)
|
||||
{
|
||||
return _scanResponseData.setLocalName(localName);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setAdvertisingData(BLEAdvertisingData& advertisingData)
|
||||
{
|
||||
_advertisingData = advertisingData;
|
||||
if (!_advertisingData.hasFlags()) {
|
||||
_advertisingData.setFlags(BLEFlagsGeneralDiscoverable | BLEFlagsBREDRNotSupported);
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalDevice::setScanResponseData(BLEAdvertisingData& scanResponseData)
|
||||
{
|
||||
_scanResponseData = scanResponseData;
|
||||
}
|
||||
|
||||
BLEAdvertisingData& BLELocalDevice::getAdvertisingData()
|
||||
{
|
||||
return _advertisingData;
|
||||
}
|
||||
|
||||
BLEAdvertisingData& BLELocalDevice::getScanResponseData()
|
||||
{
|
||||
return _scanResponseData;
|
||||
}
|
||||
|
||||
void BLELocalDevice::setDeviceName(const char* deviceName)
|
||||
{
|
||||
GATT.setDeviceName(deviceName);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setAppearance(uint16_t appearance)
|
||||
{
|
||||
GATT.setAppearance(appearance);
|
||||
}
|
||||
|
||||
void BLELocalDevice::addService(BLEService& service)
|
||||
{
|
||||
GATT.addService(service);
|
||||
}
|
||||
|
||||
int BLELocalDevice::advertise()
|
||||
{
|
||||
_advertisingData.updateData();
|
||||
_scanResponseData.updateData();
|
||||
return GAP.advertise( _advertisingData.data(), _advertisingData.dataLength(),
|
||||
_scanResponseData.data(), _scanResponseData.dataLength());
|
||||
}
|
||||
|
||||
void BLELocalDevice::stopAdvertise()
|
||||
{
|
||||
GAP.stopAdvertise();
|
||||
}
|
||||
|
||||
int BLELocalDevice::scan(bool withDuplicates)
|
||||
{
|
||||
return GAP.scan(withDuplicates);
|
||||
}
|
||||
|
||||
int BLELocalDevice::scanForName(String name, bool withDuplicates)
|
||||
{
|
||||
return GAP.scanForName(name, withDuplicates);
|
||||
}
|
||||
|
||||
int BLELocalDevice::scanForUuid(String uuid, bool withDuplicates)
|
||||
{
|
||||
return GAP.scanForUuid(uuid, withDuplicates);
|
||||
}
|
||||
|
||||
int BLELocalDevice::scanForAddress(String address, bool withDuplicates)
|
||||
{
|
||||
return GAP.scanForAddress(address, withDuplicates);
|
||||
}
|
||||
|
||||
void BLELocalDevice::stopScan()
|
||||
{
|
||||
GAP.stopScan();
|
||||
}
|
||||
|
||||
BLEDevice BLELocalDevice::central()
|
||||
{
|
||||
HCI.poll();
|
||||
|
||||
return ATT.central();
|
||||
}
|
||||
|
||||
BLEDevice BLELocalDevice::available()
|
||||
{
|
||||
HCI.poll();
|
||||
|
||||
return GAP.available();
|
||||
}
|
||||
|
||||
void BLELocalDevice::setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler)
|
||||
{
|
||||
if (event == BLEDiscovered) {
|
||||
GAP.setEventHandler(event, eventHandler);
|
||||
} else {
|
||||
ATT.setEventHandler(event, eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalDevice::setAdvertisingInterval(uint16_t advertisingInterval)
|
||||
{
|
||||
GAP.setAdvertisingInterval(advertisingInterval);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setConnectionInterval(uint16_t minimumConnectionInterval, uint16_t maximumConnectionInterval)
|
||||
{
|
||||
L2CAPSignaling.setConnectionInterval(minimumConnectionInterval, maximumConnectionInterval);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setSupervisionTimeout(uint16_t supervisionTimeout)
|
||||
{
|
||||
L2CAPSignaling.setSupervisionTimeout(supervisionTimeout);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setConnectable(bool connectable)
|
||||
{
|
||||
GAP.setConnectable(connectable);
|
||||
}
|
||||
|
||||
void BLELocalDevice::setTimeout(unsigned long timeout)
|
||||
{
|
||||
ATT.setTimeout(timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Control whether pairing is allowed or rejected
|
||||
* Use true/false or the Pairable enum
|
||||
*/
|
||||
void BLELocalDevice::setPairable(uint8_t pairable)
|
||||
{
|
||||
L2CAPSignaling.setPairingEnabled(pairable);
|
||||
}
|
||||
|
||||
/*
|
||||
* Whether pairing is currently allowed
|
||||
*/
|
||||
bool BLELocalDevice::pairable()
|
||||
{
|
||||
return L2CAPSignaling.isPairingEnabled();
|
||||
}
|
||||
|
||||
void BLELocalDevice::setGetIRKs(int (*getIRKs)(uint8_t* nIRKs, uint8_t** BADDR_type, uint8_t*** BADDRs, uint8_t*** IRKs)){
|
||||
HCI._getIRKs = getIRKs;
|
||||
}
|
||||
void BLELocalDevice::setGetLTK(int (*getLTK)(uint8_t* BADDR, uint8_t* LTK)){
|
||||
HCI._getLTK = getLTK;
|
||||
}
|
||||
void BLELocalDevice::setStoreLTK(int (*storeLTK)(uint8_t*, uint8_t*)){
|
||||
HCI._storeLTK = storeLTK;
|
||||
}
|
||||
void BLELocalDevice::setStoreIRK(int (*storeIRK)(uint8_t*, uint8_t*)){
|
||||
HCI._storeIRK = storeIRK;
|
||||
}
|
||||
void BLELocalDevice::setDisplayCode(void (*displayCode)(uint32_t confirmationCode)){
|
||||
HCI._displayCode = displayCode;
|
||||
}
|
||||
void BLELocalDevice::setBinaryConfirmPairing(bool (*binaryConfirmPairing)()){
|
||||
HCI._binaryConfirmPairing = binaryConfirmPairing;
|
||||
}
|
||||
|
||||
void BLELocalDevice::debug(Stream& stream)
|
||||
{
|
||||
HCI.debug(stream);
|
||||
}
|
||||
|
||||
void BLELocalDevice::noDebug()
|
||||
{
|
||||
HCI.noDebug();
|
||||
}
|
||||
|
||||
#if !defined(FAKE_BLELOCALDEVICE)
|
||||
BLELocalDevice BLEObj;
|
||||
BLELocalDevice& BLE = BLEObj;
|
||||
#endif
|
123
lib/ArduinoBLE/src/local/BLELocalDevice.h
Normal file
123
lib/ArduinoBLE/src/local/BLELocalDevice.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LOCAL_DEVICE_H_
|
||||
#define _BLE_LOCAL_DEVICE_H_
|
||||
|
||||
#include "BLEDevice.h"
|
||||
#include "BLEService.h"
|
||||
#include "BLEAdvertisingData.h"
|
||||
|
||||
enum Pairable {
|
||||
NO = 0,
|
||||
YES = 1,
|
||||
ONCE = 2,
|
||||
};
|
||||
|
||||
class BLELocalDevice {
|
||||
public:
|
||||
BLELocalDevice();
|
||||
virtual ~BLELocalDevice();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void poll();
|
||||
virtual void poll(unsigned long timeout);
|
||||
|
||||
virtual bool connected() const;
|
||||
virtual bool disconnect();
|
||||
|
||||
virtual String address() const;
|
||||
|
||||
virtual int rssi();
|
||||
|
||||
virtual bool setAdvertisedServiceUuid(const char* advertisedServiceUuid);
|
||||
virtual bool setAdvertisedService(const BLEService& service);
|
||||
virtual bool setAdvertisedServiceData(uint16_t uuid, const uint8_t data[], int length);
|
||||
virtual bool setManufacturerData(const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
virtual bool setManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength);
|
||||
virtual bool setLocalName(const char *localName);
|
||||
|
||||
virtual void setAdvertisingData(BLEAdvertisingData& advertisingData);
|
||||
virtual void setScanResponseData(BLEAdvertisingData& scanResponseData);
|
||||
|
||||
virtual void setDeviceName(const char* deviceName);
|
||||
virtual void setAppearance(uint16_t appearance);
|
||||
|
||||
virtual void addService(BLEService& service);
|
||||
|
||||
virtual int advertise();
|
||||
virtual void stopAdvertise();
|
||||
|
||||
virtual int scan(bool withDuplicates = false);
|
||||
virtual int scanForName(String name, bool withDuplicates = false);
|
||||
virtual int scanForUuid(String uuid, bool withDuplicates = false);
|
||||
virtual int scanForAddress(String address, bool withDuplicates = false);
|
||||
virtual void stopScan();
|
||||
|
||||
virtual BLEDevice central();
|
||||
virtual BLEDevice available();
|
||||
|
||||
virtual void setAdvertisingInterval(uint16_t advertisingInterval);
|
||||
virtual void setConnectionInterval(uint16_t minimumConnectionInterval, uint16_t maximumConnectionInterval);
|
||||
virtual void setSupervisionTimeout(uint16_t supervisionTimeout);
|
||||
virtual void setConnectable(bool connectable);
|
||||
|
||||
virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||
|
||||
virtual void setTimeout(unsigned long timeout);
|
||||
|
||||
virtual void debug(Stream& stream);
|
||||
virtual void noDebug();
|
||||
|
||||
virtual void setPairable(uint8_t pairable);
|
||||
virtual bool pairable();
|
||||
virtual bool paired();
|
||||
|
||||
// address - The mac to store
|
||||
// IRK - The IRK to store with this mac
|
||||
virtual void setStoreIRK(int (*storeIRK)(uint8_t* address, uint8_t* IRK));
|
||||
// nIRKs - the number of IRKs being provided.
|
||||
// BDAddrType - an array containing the type of each address (0 public, 1 static random)
|
||||
// BDAddrs - an array containing the list of addresses
|
||||
virtual void setGetIRKs(int (*getIRKs)(uint8_t* nIRKs, uint8_t** BDAddrType, uint8_t*** BDAddrs, uint8_t*** IRKs));
|
||||
// address - the address to store [6 bytes]
|
||||
// LTK - the LTK to store with this mac [16 bytes]
|
||||
virtual void setStoreLTK(int (*storeLTK)(uint8_t* address, uint8_t* LTK));
|
||||
// address - The mac address needing its LTK
|
||||
// LTK - 16 octet LTK for the mac address
|
||||
virtual void setGetLTK(int (*getLTK)(uint8_t* address, uint8_t* LTK));
|
||||
|
||||
virtual void setDisplayCode(void (*displayCode)(uint32_t confirmationCode));
|
||||
virtual void setBinaryConfirmPairing(bool (*binaryConfirmPairing)());
|
||||
uint8_t BDaddress[6];
|
||||
|
||||
protected:
|
||||
virtual BLEAdvertisingData& getAdvertisingData();
|
||||
virtual BLEAdvertisingData& getScanResponseData();
|
||||
|
||||
private:
|
||||
BLEAdvertisingData _advertisingData;
|
||||
BLEAdvertisingData _scanResponseData;
|
||||
};
|
||||
|
||||
extern BLELocalDevice& BLE;
|
||||
|
||||
#endif
|
94
lib/ArduinoBLE/src/local/BLELocalService.cpp
Normal file
94
lib/ArduinoBLE/src/local/BLELocalService.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLELocalCharacteristic.h"
|
||||
|
||||
#include "BLELocalService.h"
|
||||
|
||||
BLELocalService::BLELocalService(const char* uuid) :
|
||||
BLELocalAttribute(uuid),
|
||||
_startHandle(0x0000),
|
||||
_endHandle(0x0000)
|
||||
{
|
||||
}
|
||||
|
||||
void BLELocalService::clear() {
|
||||
_characteristics.clear();
|
||||
_startHandle = 0;
|
||||
_endHandle = 0;
|
||||
}
|
||||
|
||||
BLELocalService::~BLELocalService()
|
||||
{
|
||||
for (unsigned int i = 0; i < characteristicCount(); i++) {
|
||||
BLELocalCharacteristic* c = characteristic(i);
|
||||
|
||||
if (c->release() == 0) {
|
||||
delete c;
|
||||
}
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
enum BLEAttributeType BLELocalService::type() const
|
||||
{
|
||||
return BLETypeService;
|
||||
}
|
||||
|
||||
void BLELocalService::addCharacteristic(BLECharacteristic& characteristic)
|
||||
{
|
||||
BLELocalCharacteristic* localCharacteristic = characteristic.local();
|
||||
|
||||
if (localCharacteristic) {
|
||||
addCharacteristic(localCharacteristic);
|
||||
}
|
||||
}
|
||||
|
||||
void BLELocalService::setHandles(uint16_t start, uint16_t end)
|
||||
{
|
||||
_startHandle = start;
|
||||
_endHandle = end;
|
||||
}
|
||||
|
||||
uint16_t BLELocalService::startHandle() const
|
||||
{
|
||||
return _startHandle;
|
||||
}
|
||||
|
||||
uint16_t BLELocalService::endHandle() const
|
||||
{
|
||||
return _endHandle;
|
||||
}
|
||||
|
||||
unsigned int BLELocalService::characteristicCount() const
|
||||
{
|
||||
return _characteristics.size();
|
||||
}
|
||||
|
||||
BLELocalCharacteristic* BLELocalService::characteristic(unsigned int index) const
|
||||
{
|
||||
return _characteristics.get(index);
|
||||
}
|
||||
|
||||
void BLELocalService::addCharacteristic(BLELocalCharacteristic* characteristic)
|
||||
{
|
||||
characteristic->retain();
|
||||
|
||||
_characteristics.add(characteristic);
|
||||
}
|
61
lib/ArduinoBLE/src/local/BLELocalService.h
Normal file
61
lib/ArduinoBLE/src/local/BLELocalService.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LOCAL_SERVICE_H_
|
||||
#define _BLE_LOCAL_SERVICE_H_
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
#include "BLELocalAttribute.h"
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
class BLELocalCharacteristic;
|
||||
|
||||
class BLELocalService : public BLELocalAttribute {
|
||||
public:
|
||||
BLELocalService(const char* uuid);
|
||||
virtual ~BLELocalService();
|
||||
|
||||
virtual enum BLEAttributeType type() const;
|
||||
|
||||
void addCharacteristic(BLECharacteristic& characteristic);
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
friend class GATTClass;
|
||||
|
||||
void setHandles(uint16_t start, uint16_t end);
|
||||
uint16_t startHandle() const;
|
||||
uint16_t endHandle() const;
|
||||
|
||||
unsigned int characteristicCount() const;
|
||||
BLELocalCharacteristic* characteristic(unsigned int index) const;
|
||||
|
||||
void addCharacteristic(BLELocalCharacteristic* characteristic);
|
||||
|
||||
private:
|
||||
uint16_t _startHandle;
|
||||
uint16_t _endHandle;
|
||||
|
||||
BLELinkedList<BLELocalCharacteristic*> _characteristics;
|
||||
};
|
||||
|
||||
#endif
|
51
lib/ArduinoBLE/src/remote/BLERemoteAttribute.cpp
Normal file
51
lib/ArduinoBLE/src/remote/BLERemoteAttribute.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "utility/BLEUuid.h"
|
||||
|
||||
#include "BLERemoteAttribute.h"
|
||||
|
||||
BLERemoteAttribute::BLERemoteAttribute(const uint8_t uuid[], uint8_t uuidLen) :
|
||||
_uuid(BLEUuid::uuidToString(uuid, uuidLen)),
|
||||
_refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLERemoteAttribute::~BLERemoteAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
const char* BLERemoteAttribute::uuid() const
|
||||
{
|
||||
return _uuid.c_str();
|
||||
}
|
||||
|
||||
int BLERemoteAttribute::retain()
|
||||
{
|
||||
_refCount++;
|
||||
|
||||
return _refCount;
|
||||
}
|
||||
|
||||
int BLERemoteAttribute::release()
|
||||
{
|
||||
_refCount--;
|
||||
|
||||
return _refCount;
|
||||
}
|
41
lib/ArduinoBLE/src/remote/BLERemoteAttribute.h
Normal file
41
lib/ArduinoBLE/src/remote/BLERemoteAttribute.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_REMOTE_ATTRIBUTE_H_
|
||||
#define _BLE_REMOTE_ATTRIBUTE_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class BLERemoteAttribute
|
||||
{
|
||||
public:
|
||||
BLERemoteAttribute(const uint8_t uuid[], uint8_t uuidLen);
|
||||
virtual ~BLERemoteAttribute();
|
||||
|
||||
const char* uuid() const;
|
||||
|
||||
int retain();
|
||||
int release();
|
||||
|
||||
private:
|
||||
String _uuid;
|
||||
int _refCount;
|
||||
};
|
||||
|
||||
#endif
|
264
lib/ArduinoBLE/src/remote/BLERemoteCharacteristic.cpp
Normal file
264
lib/ArduinoBLE/src/remote/BLERemoteCharacteristic.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLEProperty.h"
|
||||
|
||||
#include "utility/ATT.h"
|
||||
|
||||
#include "BLERemoteCharacteristic.h"
|
||||
|
||||
BLERemoteCharacteristic::BLERemoteCharacteristic(const uint8_t uuid[], uint8_t uuidLen, uint16_t connectionHandle,
|
||||
uint16_t startHandle, uint16_t permissions, uint16_t valueHandle) :
|
||||
BLERemoteAttribute(uuid, uuidLen),
|
||||
_connectionHandle(connectionHandle),
|
||||
_startHandle(startHandle),
|
||||
_properties((uint8_t)(permissions & 0x00FF)),
|
||||
_permissions((uint8_t)((permissions & 0xFF00)>>8)),
|
||||
_valueHandle(valueHandle),
|
||||
_value(NULL),
|
||||
_valueLength(0),
|
||||
_valueUpdated(false),
|
||||
_updatedValueRead(true),
|
||||
_valueUpdatedEventHandler(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BLERemoteCharacteristic::~BLERemoteCharacteristic()
|
||||
{
|
||||
for (unsigned int i = 0; i < descriptorCount(); i++) {
|
||||
BLERemoteDescriptor* d = descriptor(i);
|
||||
|
||||
if (d->release() == 0) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
_descriptors.clear();
|
||||
|
||||
if (_value) {
|
||||
free(_value);
|
||||
_value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t BLERemoteCharacteristic::startHandle() const
|
||||
{
|
||||
return _startHandle;
|
||||
}
|
||||
|
||||
uint8_t BLERemoteCharacteristic::properties() const
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
const uint8_t* BLERemoteCharacteristic::value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
int BLERemoteCharacteristic::valueLength() const
|
||||
{
|
||||
return _valueLength;
|
||||
}
|
||||
|
||||
uint8_t BLERemoteCharacteristic::operator[] (int offset) const
|
||||
{
|
||||
if (_value) {
|
||||
return _value[offset];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLERemoteCharacteristic::writeValue(const uint8_t value[], int length, bool withResponse)
|
||||
{
|
||||
if (!ATT.connected(_connectionHandle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t maxLength = ATT.mtu(_connectionHandle) - 3;
|
||||
|
||||
if (length > (int)maxLength) {
|
||||
// cap to MTU max length
|
||||
length = maxLength;
|
||||
}
|
||||
|
||||
_value = (uint8_t*)realloc(_value, length);
|
||||
if (_value == NULL) {
|
||||
// realloc failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((_properties & BLEWrite) && withResponse) {
|
||||
uint8_t resp[4];
|
||||
int respLength = ATT.writeReq(_connectionHandle, _valueHandle, value, length, resp);
|
||||
|
||||
if (!respLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resp[0] == 0x01) {
|
||||
// error
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(_value, value, length);
|
||||
_valueLength = length;
|
||||
|
||||
return 1;
|
||||
} else if (_properties & BLEWriteWithoutResponse) {
|
||||
ATT.writeCmd(_connectionHandle, _valueHandle, value, length);
|
||||
|
||||
memcpy(_value, value, length);
|
||||
_valueLength = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLERemoteCharacteristic::writeValue(const char* value, bool withResponse)
|
||||
{
|
||||
return writeValue((uint8_t*)value, strlen(value), withResponse);
|
||||
}
|
||||
|
||||
bool BLERemoteCharacteristic::valueUpdated()
|
||||
{
|
||||
ATT.connected(_connectionHandle); // to force a poll
|
||||
|
||||
bool result = _valueUpdated;
|
||||
|
||||
_valueUpdated = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BLERemoteCharacteristic::updatedValueRead()
|
||||
{
|
||||
bool result = _updatedValueRead;
|
||||
|
||||
_updatedValueRead = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BLERemoteCharacteristic::read()
|
||||
{
|
||||
if (!ATT.connected(_connectionHandle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t resp[256];
|
||||
|
||||
int respLength = ATT.readReq(_connectionHandle, _valueHandle, resp);
|
||||
|
||||
if (!respLength) {
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resp[0] == 0x01) {
|
||||
// error
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
_valueLength = respLength - 1;
|
||||
_value = (uint8_t*)realloc(_value, _valueLength);
|
||||
|
||||
if (_value == NULL) {
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(_value, &resp[1], _valueLength);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BLERemoteCharacteristic::writeCccd(uint16_t value)
|
||||
{
|
||||
int numDescriptors = descriptorCount();
|
||||
|
||||
for (int i = 0; i < numDescriptors; i++) {
|
||||
BLERemoteDescriptor* d = descriptor(i);
|
||||
|
||||
if (strcmp(d->uuid(), "2902") == 0) {
|
||||
return d->writeValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (_properties & (BLENotify | BLEIndicate)) {
|
||||
// no CCCD descriptor found, fallback to _valueHandle + 1
|
||||
BLERemoteDescriptor cccd(NULL, 0, _connectionHandle, _valueHandle + 1);
|
||||
|
||||
return cccd.writeValue((uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t BLERemoteCharacteristic::valueHandle() const
|
||||
{
|
||||
return _valueHandle;
|
||||
}
|
||||
|
||||
unsigned int BLERemoteCharacteristic::descriptorCount() const
|
||||
{
|
||||
return _descriptors.size();
|
||||
}
|
||||
|
||||
BLERemoteDescriptor* BLERemoteCharacteristic::descriptor(unsigned int index) const
|
||||
{
|
||||
return _descriptors.get(index);
|
||||
}
|
||||
|
||||
void BLERemoteCharacteristic::setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler eventHandler)
|
||||
{
|
||||
if (event == BLEUpdated) {
|
||||
_valueUpdatedEventHandler = eventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
void BLERemoteCharacteristic::addDescriptor(BLERemoteDescriptor* descriptor)
|
||||
{
|
||||
descriptor->retain();
|
||||
|
||||
_descriptors.add(descriptor);
|
||||
}
|
||||
|
||||
void BLERemoteCharacteristic::writeValue(BLEDevice device, const uint8_t value[], int length)
|
||||
{
|
||||
_valueLength = length;
|
||||
_value = (uint8_t*)realloc(_value, _valueLength);
|
||||
|
||||
if (_value == NULL) {
|
||||
_valueLength = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_valueUpdated = true;
|
||||
_updatedValueRead = false;
|
||||
memcpy(_value, value, _valueLength);
|
||||
|
||||
if (_valueUpdatedEventHandler) {
|
||||
_valueUpdatedEventHandler(device, BLECharacteristic(this));
|
||||
}
|
||||
}
|
84
lib/ArduinoBLE/src/remote/BLERemoteCharacteristic.h
Normal file
84
lib/ArduinoBLE/src/remote/BLERemoteCharacteristic.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_REMOTE_CHARACTERISTIC_H_
|
||||
#define _BLE_REMOTE_CHARACTERISTIC_H_
|
||||
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
#include "BLERemoteAttribute.h"
|
||||
#include "BLERemoteDescriptor.h"
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
class BLERemoteCharacteristic : public BLERemoteAttribute {
|
||||
public:
|
||||
BLERemoteCharacteristic(const uint8_t uuid[], uint8_t uuidLen, uint16_t connectionHandle, uint16_t startHandle, uint16_t permissions, uint16_t valueHandle);
|
||||
virtual ~BLERemoteCharacteristic();
|
||||
|
||||
uint8_t properties() const;
|
||||
uint8_t permissions() const;
|
||||
|
||||
const uint8_t* value() const;
|
||||
int valueLength() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
int writeValue(const uint8_t value[], int length, bool withResponse = true);
|
||||
int writeValue(const char* value, bool withResponse = true);
|
||||
|
||||
bool valueUpdated();
|
||||
bool updatedValueRead();
|
||||
|
||||
bool read();
|
||||
bool writeCccd(uint16_t value);
|
||||
|
||||
unsigned int descriptorCount() const;
|
||||
BLERemoteDescriptor* descriptor(unsigned int index) const;
|
||||
|
||||
void setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler eventHandler);
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
|
||||
uint16_t startHandle() const;
|
||||
uint16_t valueHandle() const;
|
||||
|
||||
void addDescriptor(BLERemoteDescriptor* descriptor);
|
||||
|
||||
void writeValue(BLEDevice device, const uint8_t value[], int length);
|
||||
|
||||
private:
|
||||
uint16_t _connectionHandle;
|
||||
uint16_t _startHandle;
|
||||
uint8_t _properties;
|
||||
uint8_t _permissions;
|
||||
uint16_t _valueHandle;
|
||||
|
||||
uint8_t* _value;
|
||||
int _valueLength;
|
||||
|
||||
bool _valueUpdated;
|
||||
bool _updatedValueRead;
|
||||
|
||||
BLELinkedList<BLERemoteDescriptor*> _descriptors;
|
||||
|
||||
BLECharacteristicEventHandler _valueUpdatedEventHandler;
|
||||
};
|
||||
|
||||
#endif
|
134
lib/ArduinoBLE/src/remote/BLERemoteDescriptor.cpp
Normal file
134
lib/ArduinoBLE/src/remote/BLERemoteDescriptor.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "utility/ATT.h"
|
||||
|
||||
#include "BLERemoteDescriptor.h"
|
||||
|
||||
BLERemoteDescriptor::BLERemoteDescriptor(const uint8_t uuid[], uint8_t uuidLen, uint16_t connectionHandle, uint16_t handle) :
|
||||
BLERemoteAttribute(uuid, uuidLen),
|
||||
_connectionHandle(connectionHandle),
|
||||
_handle(handle),
|
||||
_value(NULL),
|
||||
_valueLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLERemoteDescriptor::~BLERemoteDescriptor()
|
||||
{
|
||||
if (_value) {
|
||||
free(_value);
|
||||
_value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* BLERemoteDescriptor::value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
int BLERemoteDescriptor::valueLength() const
|
||||
{
|
||||
return _valueLength;
|
||||
}
|
||||
|
||||
uint8_t BLERemoteDescriptor::operator[] (int offset) const
|
||||
{
|
||||
if (_value) {
|
||||
return _value[offset];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BLERemoteDescriptor::writeValue(const uint8_t value[], int length)
|
||||
{
|
||||
if (!ATT.connected(_connectionHandle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t maxLength = ATT.mtu(_connectionHandle) - 3;
|
||||
|
||||
if (length > (int)maxLength) {
|
||||
// cap to MTU max length
|
||||
length = maxLength;
|
||||
}
|
||||
|
||||
_value = (uint8_t*)realloc(_value, length);
|
||||
if (_value == NULL) {
|
||||
// realloc failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t resp[4];
|
||||
int respLength = ATT.writeReq(_connectionHandle, _handle, value, length, resp);
|
||||
|
||||
if (!respLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resp[0] == 0x01) {
|
||||
// error
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(_value, value, length);
|
||||
_valueLength = length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool BLERemoteDescriptor::read()
|
||||
{
|
||||
if (!ATT.connected(_connectionHandle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t resp[256];
|
||||
|
||||
int respLength = ATT.readReq(_connectionHandle, _handle, resp);
|
||||
|
||||
if (!respLength) {
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resp[0] == 0x01) {
|
||||
// error
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
_valueLength = respLength - 1;
|
||||
_value = (uint8_t*)realloc(_value, _valueLength);
|
||||
|
||||
if (_value == NULL) {
|
||||
_valueLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(_value, &resp[1], _valueLength);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t BLERemoteDescriptor::handle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
50
lib/ArduinoBLE/src/remote/BLERemoteDescriptor.h
Normal file
50
lib/ArduinoBLE/src/remote/BLERemoteDescriptor.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_REMOTE_DESCRIPTOR_H_
|
||||
#define _BLE_REMOTE_DESCRIPTOR_H_
|
||||
|
||||
#include "BLERemoteAttribute.h"
|
||||
|
||||
class BLERemoteDescriptor : public BLERemoteAttribute {
|
||||
public:
|
||||
BLERemoteDescriptor(const uint8_t uuid[], uint8_t uuidLen, uint16_t connectionHandle, uint16_t handle);
|
||||
virtual ~BLERemoteDescriptor();
|
||||
|
||||
const uint8_t* value() const;
|
||||
int valueLength() const;
|
||||
uint8_t operator[] (int offset) const;
|
||||
|
||||
int writeValue(const uint8_t value[], int length);
|
||||
|
||||
bool read();
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
uint16_t handle() const;
|
||||
|
||||
private:
|
||||
uint16_t _connectionHandle;
|
||||
uint16_t _handle;
|
||||
|
||||
uint8_t* _value;
|
||||
int _valueLength;
|
||||
};
|
||||
|
||||
#endif
|
59
lib/ArduinoBLE/src/remote/BLERemoteDevice.cpp
Normal file
59
lib/ArduinoBLE/src/remote/BLERemoteDevice.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLERemoteDevice.h"
|
||||
|
||||
BLERemoteDevice::BLERemoteDevice()
|
||||
{
|
||||
}
|
||||
|
||||
BLERemoteDevice::~BLERemoteDevice()
|
||||
{
|
||||
clearServices();
|
||||
}
|
||||
|
||||
void BLERemoteDevice::addService(BLERemoteService* service)
|
||||
{
|
||||
service->retain();
|
||||
|
||||
_services.add(service);
|
||||
}
|
||||
|
||||
unsigned int BLERemoteDevice::serviceCount() const
|
||||
{
|
||||
return _services.size();
|
||||
}
|
||||
|
||||
BLERemoteService* BLERemoteDevice::service(unsigned int index) const
|
||||
{
|
||||
return _services.get(index);
|
||||
}
|
||||
|
||||
void BLERemoteDevice::clearServices()
|
||||
{
|
||||
for (unsigned int i = 0; i < serviceCount(); i++) {
|
||||
BLERemoteService* s = service(i);
|
||||
|
||||
if (s->release() == 0) {
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
_services.clear();
|
||||
}
|
43
lib/ArduinoBLE/src/remote/BLERemoteDevice.h
Normal file
43
lib/ArduinoBLE/src/remote/BLERemoteDevice.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_REMOTE_DEVICE_H_
|
||||
#define _BLE_REMOTE_DEVICE_H_
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
#include "BLERemoteService.h"
|
||||
|
||||
class BLERemoteDevice /*: public BLEDevice*/ {
|
||||
public:
|
||||
BLERemoteDevice();
|
||||
virtual ~BLERemoteDevice();
|
||||
|
||||
void addService(BLERemoteService* service);
|
||||
|
||||
unsigned int serviceCount() const;
|
||||
BLERemoteService* service(unsigned int index) const;
|
||||
|
||||
void clearServices();
|
||||
|
||||
private:
|
||||
BLELinkedList<BLERemoteService*> _services;
|
||||
};
|
||||
|
||||
#endif
|
67
lib/ArduinoBLE/src/remote/BLERemoteService.cpp
Normal file
67
lib/ArduinoBLE/src/remote/BLERemoteService.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLERemoteService.h"
|
||||
|
||||
BLERemoteService::BLERemoteService(const uint8_t uuid[], uint8_t uuidLen, uint16_t startHandle, uint16_t endHandle) :
|
||||
BLERemoteAttribute(uuid, uuidLen),
|
||||
_startHandle(startHandle),
|
||||
_endHandle(endHandle)
|
||||
{
|
||||
}
|
||||
|
||||
BLERemoteService::~BLERemoteService()
|
||||
{
|
||||
for (unsigned int i = 0; i < characteristicCount(); i++) {
|
||||
BLERemoteCharacteristic* c = characteristic(i);
|
||||
|
||||
if (c->release() == 0) {
|
||||
delete c;
|
||||
}
|
||||
}
|
||||
|
||||
_characteristics.clear();
|
||||
}
|
||||
|
||||
uint16_t BLERemoteService::startHandle() const
|
||||
{
|
||||
return _startHandle;
|
||||
}
|
||||
|
||||
uint16_t BLERemoteService::endHandle() const
|
||||
{
|
||||
return _endHandle;
|
||||
}
|
||||
|
||||
unsigned int BLERemoteService::characteristicCount() const
|
||||
{
|
||||
return _characteristics.size();
|
||||
}
|
||||
|
||||
BLERemoteCharacteristic* BLERemoteService::characteristic(unsigned int index) const
|
||||
{
|
||||
return _characteristics.get(index);
|
||||
}
|
||||
|
||||
void BLERemoteService::addCharacteristic(BLERemoteCharacteristic* characteristic)
|
||||
{
|
||||
characteristic-> retain();
|
||||
|
||||
_characteristics.add(characteristic);
|
||||
}
|
53
lib/ArduinoBLE/src/remote/BLERemoteService.h
Normal file
53
lib/ArduinoBLE/src/remote/BLERemoteService.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_REMOTE_SERVICE_H_
|
||||
#define _BLE_REMOTE_SERVICE_H_
|
||||
|
||||
#include "BLERemoteAttribute.h"
|
||||
#include "BLERemoteCharacteristic.h"
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
class BLERemoteService : public BLERemoteAttribute {
|
||||
public:
|
||||
BLERemoteService(const uint8_t uuid[], uint8_t uuidLen, uint16_t startHandle, uint16_t endHandle);
|
||||
virtual ~BLERemoteService();
|
||||
|
||||
unsigned int characteristicCount() const;
|
||||
BLERemoteCharacteristic* characteristic(unsigned int index) const;
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
|
||||
uint16_t startHandle() const;
|
||||
uint16_t endHandle() const;
|
||||
|
||||
void addCharacteristic(BLERemoteCharacteristic* characteristic);
|
||||
|
||||
private:
|
||||
uint16_t _startHandle;
|
||||
uint16_t _endHandle;
|
||||
|
||||
String _uuid;
|
||||
|
||||
BLELinkedList<BLERemoteCharacteristic*> _characteristics;
|
||||
};
|
||||
|
||||
#endif
|
1963
lib/ArduinoBLE/src/utility/ATT.cpp
Normal file
1963
lib/ArduinoBLE/src/utility/ATT.cpp
Normal file
File diff suppressed because it is too large
Load Diff
177
lib/ArduinoBLE/src/utility/ATT.h
Normal file
177
lib/ArduinoBLE/src/utility/ATT.h
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ATT_H_
|
||||
#define _ATT_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BLEDevice.h"
|
||||
#include "keyDistribution.h"
|
||||
|
||||
#define ATT_CID 0x0004
|
||||
#define BLE_CTL 0x0008
|
||||
|
||||
#if DM_CONN_MAX
|
||||
#define ATT_MAX_PEERS DM_CONN_MAX // Mbed + Cordio
|
||||
#elif __AVR__
|
||||
#define ATT_MAX_PEERS 3
|
||||
#else
|
||||
#define ATT_MAX_PEERS 8
|
||||
#endif
|
||||
|
||||
enum PEER_ENCRYPTION {
|
||||
NO_ENCRYPTION = 0,
|
||||
PAIRING_REQUEST = 1 << 0,
|
||||
REQUESTED_ENCRYPTION = 1 << 1,
|
||||
SENT_PUBKEY = 1 << 2,
|
||||
DH_KEY_CALULATED = 1 << 3,
|
||||
RECEIVED_DH_CHECK = 1 << 4,
|
||||
SENT_DH_CHECK = 1 << 5,
|
||||
ENCRYPTED_AES = 1 << 7
|
||||
};
|
||||
|
||||
class BLERemoteDevice;
|
||||
|
||||
class ATTClass {
|
||||
public:
|
||||
ATTClass();
|
||||
virtual ~ATTClass();
|
||||
|
||||
virtual void setMaxMtu(uint16_t maxMtu);
|
||||
virtual void setTimeout(unsigned long timeout);
|
||||
|
||||
virtual bool connect(uint8_t peerBdaddrType, uint8_t peerBdaddr[6]);
|
||||
virtual bool disconnect(uint8_t peerBdaddrType, uint8_t peerBdaddr[6]);
|
||||
virtual bool discoverAttributes(uint8_t peerBdaddrType, uint8_t peerBdaddr[6], const char* serviceUuidFilter);
|
||||
|
||||
virtual void addConnection(uint16_t handle, uint8_t role, uint8_t peerBdaddrType,
|
||||
uint8_t peerBdaddr[6], uint16_t interval,
|
||||
uint16_t latency, uint16_t supervisionTimeout,
|
||||
uint8_t masterClockAccuracy);
|
||||
|
||||
virtual void handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
|
||||
virtual void removeConnection(uint16_t handle, uint8_t reason);
|
||||
|
||||
virtual uint16_t connectionHandle(uint8_t addressType, const uint8_t address[6]) const;
|
||||
virtual BLERemoteDevice* device(uint8_t addressType, const uint8_t address[6]) const;
|
||||
virtual bool connected() const;
|
||||
virtual bool connected(uint8_t addressType, const uint8_t address[6]) const;
|
||||
virtual bool connected(uint16_t handle) const;
|
||||
virtual bool paired() const;
|
||||
virtual bool paired(uint16_t handle) const;
|
||||
virtual uint16_t mtu(uint16_t handle) const;
|
||||
|
||||
virtual bool disconnect();
|
||||
|
||||
virtual BLEDevice central();
|
||||
|
||||
virtual int handleNotify(uint16_t handle, const uint8_t* value, int length);
|
||||
virtual int handleInd(uint16_t handle, const uint8_t* value, int length);
|
||||
|
||||
virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||
|
||||
virtual int readReq(uint16_t connectionHandle, uint16_t handle, uint8_t responseBuffer[]);
|
||||
virtual int writeReq(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen, uint8_t responseBuffer[]);
|
||||
virtual void writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen);
|
||||
virtual int setPeerEncryption(uint16_t connectionHandle, uint8_t encryption);
|
||||
uint8_t getPeerEncryption(uint16_t connectionHandle);
|
||||
uint16_t getPeerEncrptingConnectionHandle();
|
||||
virtual int getPeerAddr(uint16_t connectionHandle, uint8_t peerAddr[]);
|
||||
virtual int getPeerAddrWithType(uint16_t connectionHandle, uint8_t peerAddr[]);
|
||||
virtual int setPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
|
||||
virtual int getPeerIOCap(uint16_t connectionHandle, uint8_t IOCap[]);
|
||||
virtual int getPeerResolvedAddress(uint16_t connectionHandle, uint8_t* resolvedAddress);
|
||||
uint8_t holdBuffer[64];
|
||||
uint8_t writeBuffer[64];
|
||||
uint8_t holdBufferSize;
|
||||
uint8_t writeBufferSize;
|
||||
virtual int processWriteBuffer();
|
||||
KeyDistribution remoteKeyDistribution;
|
||||
KeyDistribution localKeyDistribution;
|
||||
uint8_t peerIRK[16];
|
||||
/// This is just a random number... Not sure it has use unless privacy mode is active.
|
||||
uint8_t localIRK[16] = {0x54,0x83,0x63,0x7c,0xc5,0x1e,0xf7,0xec,0x32,0xdd,0xad,0x51,0x89,0x4b,0x9e,0x07};
|
||||
private:
|
||||
virtual void error(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void mtuReq(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual int mtuReq(uint16_t connectionHandle, uint16_t mtu, uint8_t responseBuffer[]);
|
||||
virtual void mtuResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void findInfoReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual int findInfoReq(uint16_t connectionHandle, uint16_t startHandle, uint16_t endHandle, uint8_t responseBuffer[]);
|
||||
virtual void findInfoResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void findByTypeReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual void readByTypeReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual int readByTypeReq(uint16_t connectionHandle, uint16_t startHandle, uint16_t endHandle, uint16_t type, uint8_t responseBuffer[]);
|
||||
virtual void readByTypeResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void readOrReadBlobReq(uint16_t connectionHandle, uint16_t mtu, uint8_t opcode, uint8_t dlen, uint8_t data[]);
|
||||
virtual void readResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void readByGroupReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual int readByGroupReq(uint16_t connectionHandle, uint16_t startHandle, uint16_t endHandle, uint16_t uuid, uint8_t responseBuffer[]);
|
||||
virtual void readByGroupResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void writeReqOrCmd(uint16_t connectionHandle, uint16_t mtu, uint8_t op, uint8_t dlen, uint8_t data[]);
|
||||
virtual void writeResp(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void prepWriteReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual void execWriteReq(uint16_t connectionHandle, uint16_t mtu, uint8_t dlen, uint8_t data[]);
|
||||
virtual void handleNotifyOrInd(uint16_t connectionHandle, uint8_t opcode, uint8_t dlen, uint8_t data[]);
|
||||
virtual void handleCnf(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
virtual void sendError(uint16_t connectionHandle, uint8_t opcode, uint16_t handle, uint8_t code);
|
||||
|
||||
virtual bool exchangeMtu(uint16_t connectionHandle);
|
||||
virtual bool discoverServices(uint16_t connectionHandle, BLERemoteDevice* device, const char* serviceUuidFilter);
|
||||
virtual bool discoverCharacteristics(uint16_t connectionHandle, BLERemoteDevice* device);
|
||||
virtual bool discoverDescriptors(uint16_t connectionHandle, BLERemoteDevice* device);
|
||||
|
||||
virtual int sendReq(uint16_t connectionHandle, void* requestBuffer, int requestLength, uint8_t responseBuffer[]);
|
||||
|
||||
private:
|
||||
uint16_t _maxMtu;
|
||||
unsigned long _timeout;
|
||||
struct {
|
||||
uint16_t connectionHandle;
|
||||
uint8_t role;
|
||||
uint8_t addressType;
|
||||
uint8_t address[6];
|
||||
uint8_t resolvedAddress[6];
|
||||
uint16_t mtu;
|
||||
BLERemoteDevice* device;
|
||||
uint8_t encryption;
|
||||
uint8_t IOCap[3];
|
||||
} _peers[ATT_MAX_PEERS];
|
||||
|
||||
volatile bool _cnf;
|
||||
|
||||
uint16_t _longWriteHandle;
|
||||
uint8_t* _longWriteValue;
|
||||
uint16_t _longWriteValueLength;
|
||||
|
||||
struct {
|
||||
uint16_t connectionHandle;
|
||||
uint8_t op;
|
||||
uint8_t* buffer;
|
||||
uint8_t length;
|
||||
} _pendingResp;
|
||||
|
||||
BLEDeviceEventHandler _eventHandlers[2];
|
||||
};
|
||||
|
||||
extern ATTClass& ATT;
|
||||
|
||||
#endif
|
147
lib/ArduinoBLE/src/utility/BLELinkedList.h
Normal file
147
lib/ArduinoBLE/src/utility/BLELinkedList.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_LINKED_LIST_
|
||||
#define _BLE_LINKED_LIST_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
template<class T> struct BLELinkedListNode
|
||||
{
|
||||
T data;
|
||||
BLELinkedListNode<T>* next;
|
||||
};
|
||||
|
||||
template <typename T> class BLELinkedList {
|
||||
public:
|
||||
BLELinkedList();
|
||||
~BLELinkedList();
|
||||
|
||||
void add(T);
|
||||
T get(unsigned int index) const;
|
||||
void clear();
|
||||
T remove(unsigned int index);
|
||||
|
||||
unsigned int size() const;
|
||||
|
||||
private:
|
||||
unsigned int _size;
|
||||
BLELinkedListNode<T>* _root;
|
||||
BLELinkedListNode<T>* _last;
|
||||
};
|
||||
|
||||
template <typename T> BLELinkedList<T>::BLELinkedList() :
|
||||
_size(0),
|
||||
_root(NULL),
|
||||
_last(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T> BLELinkedList<T>::~BLELinkedList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
template <typename T> void BLELinkedList<T>::add(T item)
|
||||
{
|
||||
BLELinkedListNode<T>* itemNode = new BLELinkedListNode<T>();
|
||||
|
||||
itemNode->data = item;
|
||||
itemNode->next = NULL;
|
||||
|
||||
if (_root == NULL) {
|
||||
_root = itemNode;
|
||||
} else {
|
||||
_last->next = itemNode;
|
||||
}
|
||||
_last = itemNode;
|
||||
|
||||
_size++;
|
||||
}
|
||||
|
||||
template <typename T> T BLELinkedList<T>::get(unsigned int index) const
|
||||
{
|
||||
if (index >= _size) {
|
||||
return T();
|
||||
}
|
||||
|
||||
BLELinkedListNode<T>* itemNode = _root;
|
||||
|
||||
for (unsigned int i = 0; i < index; i++) {
|
||||
itemNode = itemNode->next;
|
||||
}
|
||||
|
||||
return itemNode->data;
|
||||
}
|
||||
|
||||
template <typename T> void BLELinkedList<T>::clear()
|
||||
{
|
||||
BLELinkedListNode<T>* itemNode = _root;
|
||||
|
||||
for (unsigned int i = 0; i < _size; i++) {
|
||||
BLELinkedListNode<T>* n = itemNode;
|
||||
|
||||
itemNode = itemNode->next;
|
||||
|
||||
delete n;
|
||||
}
|
||||
|
||||
_size = 0;
|
||||
_root = NULL;
|
||||
_last = NULL;
|
||||
}
|
||||
|
||||
template <typename T> unsigned int BLELinkedList<T>::size() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
template <typename T> T BLELinkedList<T>::remove(unsigned int index)
|
||||
{
|
||||
if (index >= _size) {
|
||||
return T();
|
||||
}
|
||||
|
||||
BLELinkedListNode<T>* previousItemNode = NULL;
|
||||
BLELinkedListNode<T>* itemNode = _root;
|
||||
|
||||
for (unsigned int i = 0; i < index; i++) {
|
||||
previousItemNode = itemNode;
|
||||
itemNode = itemNode->next;
|
||||
}
|
||||
|
||||
T result = itemNode->data;
|
||||
|
||||
if (previousItemNode == NULL) {
|
||||
_root = itemNode->next;
|
||||
} else {
|
||||
previousItemNode->next = itemNode->next;
|
||||
}
|
||||
|
||||
if (_last == itemNode) {
|
||||
_last = previousItemNode;
|
||||
}
|
||||
|
||||
delete itemNode;
|
||||
_size--;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
93
lib/ArduinoBLE/src/utility/BLEUuid.cpp
Normal file
93
lib/ArduinoBLE/src/utility/BLEUuid.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BLEUuid.h"
|
||||
|
||||
BLEUuid::BLEUuid(const char * str) :
|
||||
_str(str)
|
||||
{
|
||||
char temp[] = {0, 0, 0};
|
||||
|
||||
memset(_data, 0x00, sizeof(_data));
|
||||
|
||||
_length = 0;
|
||||
|
||||
if (str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = strlen(str) - 1; i >= 0 && _length < BLE_UUID_MAX_LENGTH; i -= 2) {
|
||||
if (str[i] == '-') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
temp[0] = str[i - 1];
|
||||
temp[1] = str[i];
|
||||
|
||||
_data[_length] = strtoul(temp, NULL, 16);
|
||||
|
||||
_length++;
|
||||
}
|
||||
|
||||
if (_length <= 2) {
|
||||
_length = 2;
|
||||
} else {
|
||||
_length = 16;
|
||||
}
|
||||
}
|
||||
|
||||
const char* BLEUuid::str() const
|
||||
{
|
||||
return _str;
|
||||
}
|
||||
|
||||
const uint8_t* BLEUuid::data() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
uint8_t BLEUuid::length() const
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
const char* BLEUuid::uuidToString(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
static char uuid[36 + 1];
|
||||
char* c = uuid;
|
||||
|
||||
for (int i = length - 1; i >= 0; i--) {
|
||||
uint8_t b = data[i];
|
||||
|
||||
utoa(b >> 4, c++, 16);
|
||||
utoa(b & 0x0f, c++, 16);
|
||||
|
||||
if (i == 6 || i == 8 || i == 10 || i == 12) {
|
||||
*c++ = '-';
|
||||
}
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
|
||||
return uuid;
|
||||
}
|
44
lib/ArduinoBLE/src/utility/BLEUuid.h
Normal file
44
lib/ArduinoBLE/src/utility/BLEUuid.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BLE_UUID_H_
|
||||
#define _BLE_UUID_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define BLE_UUID_MAX_LENGTH 16
|
||||
|
||||
class BLEUuid
|
||||
{
|
||||
public:
|
||||
BLEUuid(const char * str);
|
||||
|
||||
const char* str() const;
|
||||
const uint8_t * data() const;
|
||||
uint8_t length() const;
|
||||
|
||||
static const char* uuidToString(const uint8_t* data, uint8_t length);
|
||||
|
||||
private:
|
||||
const char* _str;
|
||||
uint8_t _data[BLE_UUID_MAX_LENGTH];
|
||||
uint8_t _length;
|
||||
};
|
||||
|
||||
#endif
|
17
lib/ArduinoBLE/src/utility/CordioHCICustomDriver.h
Normal file
17
lib/ArduinoBLE/src/utility/CordioHCICustomDriver.h
Normal file
@ -0,0 +1,17 @@
|
||||
#if defined(CORE_CM4)
|
||||
|
||||
#include "CyH4TransportDriver.h"
|
||||
|
||||
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver()
|
||||
{
|
||||
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
|
||||
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
|
||||
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, NC, DEF_BT_BAUD_RATE,
|
||||
CYBSP_BT_HOST_WAKE, CYBSP_BT_DEVICE_WAKE
|
||||
);
|
||||
return s_transport_driver;
|
||||
}
|
||||
|
||||
#define CUSTOM_HCI_DRIVER
|
||||
|
||||
#endif
|
272
lib/ArduinoBLE/src/utility/GAP.cpp
Normal file
272
lib/ArduinoBLE/src/utility/GAP.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BLEUuid.h"
|
||||
#include "HCI.h"
|
||||
|
||||
#include "GAP.h"
|
||||
|
||||
#define GAP_MAX_DISCOVERED_QUEUE_SIZE 32
|
||||
|
||||
#define GAP_ADV_IND (0x00)
|
||||
#define GAP_ADV_SCAN_IND (0x02)
|
||||
#define GAP_ADV_NONCONN_IND (0x03)
|
||||
|
||||
GAPClass::GAPClass() :
|
||||
_advertising(false),
|
||||
_scanning(false),
|
||||
_advertisingInterval(160),
|
||||
_connectable(true),
|
||||
_discoverEventHandler(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
GAPClass::~GAPClass()
|
||||
{
|
||||
}
|
||||
|
||||
bool GAPClass::advertising()
|
||||
{
|
||||
return _advertising;
|
||||
}
|
||||
|
||||
int GAPClass::advertise(uint8_t* advData, uint8_t advDataLen, uint8_t* scanData, uint8_t scanDataLen)
|
||||
{
|
||||
uint8_t directBdaddr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t type = (_connectable) ? GAP_ADV_IND : (scanDataLen ? GAP_ADV_SCAN_IND : GAP_ADV_NONCONN_IND);
|
||||
|
||||
stopAdvertise();
|
||||
|
||||
if (HCI.leSetAdvertisingParameters(_advertisingInterval, _advertisingInterval, type, 0x00, 0x00, directBdaddr, 0x07, 0) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HCI.leSetAdvertisingData(advDataLen, advData) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HCI.leSetScanResponseData(scanDataLen, scanData) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HCI.leSetAdvertiseEnable(0x01) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_advertising = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GAPClass::stopAdvertise()
|
||||
{
|
||||
_advertising = false;
|
||||
|
||||
HCI.leSetAdvertiseEnable(0x00);
|
||||
}
|
||||
|
||||
int GAPClass::scan(bool withDuplicates)
|
||||
{
|
||||
HCI.leSetScanEnable(false, true);
|
||||
|
||||
// active scan, 20 ms scan interval (N * 0.625), 20 ms scan window (N * 0.625), public own address type, no filter
|
||||
/*
|
||||
Warning (from BLUETOOTH SPECIFICATION 5.x):
|
||||
- scan interval: mandatory range from 0x0012 to 0x1000; only even values are valid
|
||||
- scan window: mandatory range from 0x0011 to 0x1000
|
||||
- The scan window can only be less than or equal to the scan interval
|
||||
*/
|
||||
if (HCI.leSetScanParameters(0x01, 0x0020, 0x0020, 0x00, 0x00) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_scanning = true;
|
||||
|
||||
if (HCI.leSetScanEnable(true, !withDuplicates) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GAPClass::scanForName(String name, bool withDuplicates)
|
||||
{
|
||||
_scanNameFilter = name;
|
||||
_scanUuidFilter = "";
|
||||
_scanAddressFilter = "";
|
||||
|
||||
return scan(withDuplicates);
|
||||
}
|
||||
|
||||
int GAPClass::scanForUuid(String uuid, bool withDuplicates)
|
||||
{
|
||||
_scanNameFilter = "";
|
||||
_scanUuidFilter = uuid;
|
||||
_scanAddressFilter = "";
|
||||
|
||||
return scan(withDuplicates);
|
||||
}
|
||||
|
||||
int GAPClass::scanForAddress(String address, bool withDuplicates)
|
||||
{
|
||||
_scanNameFilter = "";
|
||||
_scanUuidFilter = "";
|
||||
_scanAddressFilter = address;
|
||||
|
||||
return scan(withDuplicates);
|
||||
}
|
||||
|
||||
void GAPClass::stopScan()
|
||||
{
|
||||
HCI.leSetScanEnable(false, false);
|
||||
|
||||
_scanning = false;
|
||||
|
||||
for (unsigned int i = 0; i < _discoveredDevices.size(); i++) {
|
||||
BLEDevice* device = _discoveredDevices.get(i);
|
||||
|
||||
delete device;
|
||||
}
|
||||
|
||||
_discoveredDevices.clear();
|
||||
}
|
||||
|
||||
BLEDevice GAPClass::available()
|
||||
{
|
||||
for (unsigned int i = 0; i < _discoveredDevices.size(); i++) {
|
||||
BLEDevice* device = _discoveredDevices.get(i);
|
||||
|
||||
if (device->discovered()) {
|
||||
BLEDevice result = *device;
|
||||
|
||||
_discoveredDevices.remove(i);
|
||||
delete device;
|
||||
|
||||
if (matchesScanFilter(result)) {
|
||||
return result;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLEDevice();
|
||||
}
|
||||
|
||||
void GAPClass::setAdvertisingInterval(uint16_t advertisingInterval)
|
||||
{
|
||||
_advertisingInterval = advertisingInterval;
|
||||
}
|
||||
|
||||
void GAPClass::setConnectable(bool connectable)
|
||||
{
|
||||
_connectable = connectable;
|
||||
}
|
||||
|
||||
void GAPClass::setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler)
|
||||
{
|
||||
if (event == BLEDiscovered) {
|
||||
_discoverEventHandler = eventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
void GAPClass::handleLeAdvertisingReport(uint8_t type, uint8_t addressType, uint8_t address[6],
|
||||
uint8_t eirLength, uint8_t eirData[], int8_t rssi)
|
||||
{
|
||||
if (!_scanning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_discoverEventHandler && type == 0x03) {
|
||||
// call event handler and skip adding to discover list
|
||||
BLEDevice device(addressType, address);
|
||||
|
||||
device.setAdvertisementData(type, eirLength, eirData, rssi);
|
||||
|
||||
if (matchesScanFilter(device)) {
|
||||
_discoverEventHandler(device);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BLEDevice* discoveredDevice = NULL;
|
||||
int discoveredIndex = -1;
|
||||
|
||||
for (unsigned int i = 0; i < _discoveredDevices.size(); i++) {
|
||||
BLEDevice* device = _discoveredDevices.get(i);
|
||||
|
||||
if (device->hasAddress(addressType, address)) {
|
||||
discoveredDevice = device;
|
||||
discoveredIndex = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (discoveredDevice == NULL) {
|
||||
if (_discoveredDevices.size() >= GAP_MAX_DISCOVERED_QUEUE_SIZE) {
|
||||
BLEDevice* device_first = _discoveredDevices.remove(0);
|
||||
if (device_first != NULL) {
|
||||
delete device_first;
|
||||
}
|
||||
}
|
||||
|
||||
discoveredDevice = new BLEDevice(addressType, address);
|
||||
|
||||
_discoveredDevices.add(discoveredDevice);
|
||||
discoveredIndex = _discoveredDevices.size() - 1;
|
||||
}
|
||||
|
||||
if (type != 0x04) {
|
||||
discoveredDevice->setAdvertisementData(type, eirLength, eirData, rssi);
|
||||
} else {
|
||||
discoveredDevice->setScanResponseData(eirLength, eirData, rssi);
|
||||
}
|
||||
|
||||
if (discoveredDevice->discovered() && _discoverEventHandler) {
|
||||
// remove from list and report as discovered
|
||||
BLEDevice device = *discoveredDevice;
|
||||
|
||||
_discoveredDevices.remove(discoveredIndex);
|
||||
delete discoveredDevice;
|
||||
|
||||
if (matchesScanFilter(device)) {
|
||||
_discoverEventHandler(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GAPClass::matchesScanFilter(const BLEDevice& device)
|
||||
{
|
||||
if (_scanAddressFilter.length() > 0 && !(_scanAddressFilter.equalsIgnoreCase(device.address()))) {
|
||||
return false; // drop doesn't match
|
||||
} else if (_scanNameFilter.length() > 0 && _scanNameFilter != device.localName()) {
|
||||
return false; // drop doesn't match
|
||||
} else if (_scanUuidFilter.length() > 0 && !(_scanUuidFilter.equalsIgnoreCase(device.advertisedServiceUuid()))) {
|
||||
return false; // drop doesn't match
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(FAKE_GAP)
|
||||
GAPClass GAPObj;
|
||||
GAPClass& GAP = GAPObj;
|
||||
#endif
|
74
lib/ArduinoBLE/src/utility/GAP.h
Normal file
74
lib/ArduinoBLE/src/utility/GAP.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GAP_H_
|
||||
#define _GAP_H_
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
#include "BLEDevice.h"
|
||||
|
||||
class GAPClass {
|
||||
public:
|
||||
GAPClass();
|
||||
virtual ~GAPClass();
|
||||
|
||||
virtual bool advertising();
|
||||
virtual int advertise(uint8_t* advData, uint8_t advDataLength, uint8_t* scanData, uint8_t scanDataLength);
|
||||
virtual void stopAdvertise();
|
||||
|
||||
virtual int scan(bool withDuplicates);
|
||||
virtual int scanForName(String name, bool withDuplicates);
|
||||
virtual int scanForUuid(String uuid, bool withDuplicates);
|
||||
virtual int scanForAddress(String address, bool withDuplicates);
|
||||
virtual void stopScan();
|
||||
virtual BLEDevice available();
|
||||
|
||||
virtual void setAdvertisingInterval(uint16_t advertisingInterval);
|
||||
virtual void setConnectable(bool connectable);
|
||||
|
||||
virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||
|
||||
protected:
|
||||
friend class HCIClass;
|
||||
|
||||
virtual void handleLeAdvertisingReport(uint8_t type, uint8_t addressType, uint8_t address[6],
|
||||
uint8_t eirLength, uint8_t eirData[], int8_t rssi);
|
||||
|
||||
private:
|
||||
virtual bool matchesScanFilter(const BLEDevice& device);
|
||||
|
||||
private:
|
||||
bool _advertising;
|
||||
bool _scanning;
|
||||
|
||||
uint16_t _advertisingInterval;
|
||||
bool _connectable;
|
||||
|
||||
BLEDeviceEventHandler _discoverEventHandler;
|
||||
BLELinkedList<BLEDevice*> _discoveredDevices;
|
||||
|
||||
String _scanNameFilter;
|
||||
String _scanUuidFilter;
|
||||
String _scanAddressFilter;
|
||||
};
|
||||
|
||||
extern GAPClass& GAP;
|
||||
|
||||
#endif
|
210
lib/ArduinoBLE/src/utility/GATT.cpp
Normal file
210
lib/ArduinoBLE/src/utility/GATT.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "local/BLELocalCharacteristic.h"
|
||||
#include "local/BLELocalDescriptor.h"
|
||||
#include "local/BLELocalService.h"
|
||||
|
||||
#include "BLEProperty.h"
|
||||
|
||||
#include "GATT.h"
|
||||
|
||||
GATTClass::GATTClass() :
|
||||
_genericAccessService(NULL),
|
||||
_deviceNameCharacteristic(NULL),
|
||||
_appearanceCharacteristic(NULL),
|
||||
_genericAttributeService(NULL),
|
||||
_servicesChangedCharacteristic(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
GATTClass::~GATTClass()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
void GATTClass::begin()
|
||||
{
|
||||
_genericAccessService = new BLELocalService("1800");
|
||||
_deviceNameCharacteristic = new BLELocalCharacteristic("2a00", BLERead, 20);
|
||||
_appearanceCharacteristic = new BLELocalCharacteristic("2a01", BLERead, 2);
|
||||
_genericAttributeService = new BLELocalService("1801");
|
||||
_servicesChangedCharacteristic = new BLELocalCharacteristic("2a05", BLEIndicate, 4);
|
||||
|
||||
_genericAccessService->retain();
|
||||
_deviceNameCharacteristic->retain();
|
||||
_appearanceCharacteristic->retain();
|
||||
_genericAttributeService->retain();
|
||||
_servicesChangedCharacteristic->retain();
|
||||
|
||||
_genericAccessService->addCharacteristic(_deviceNameCharacteristic);
|
||||
_genericAccessService->addCharacteristic(_appearanceCharacteristic);
|
||||
_genericAttributeService->addCharacteristic(_servicesChangedCharacteristic);
|
||||
|
||||
setDeviceName("Arduino");
|
||||
setAppearance(0x000);
|
||||
|
||||
clearAttributes();
|
||||
|
||||
addService(_genericAccessService);
|
||||
addService(_genericAttributeService);
|
||||
}
|
||||
|
||||
void GATTClass::end()
|
||||
{
|
||||
if (_genericAccessService && _genericAccessService->release() == 0) {
|
||||
delete(_genericAccessService);
|
||||
_genericAccessService = NULL;
|
||||
}
|
||||
|
||||
if (_deviceNameCharacteristic && _deviceNameCharacteristic->release() == 0) {
|
||||
delete(_deviceNameCharacteristic);
|
||||
_deviceNameCharacteristic = NULL;
|
||||
}
|
||||
|
||||
if (_appearanceCharacteristic && _appearanceCharacteristic->release() == 0) {
|
||||
delete(_appearanceCharacteristic);
|
||||
_appearanceCharacteristic = NULL;
|
||||
}
|
||||
|
||||
if (_genericAttributeService && _genericAttributeService->release() == 0) {
|
||||
delete(_genericAttributeService);
|
||||
_genericAttributeService = NULL;
|
||||
}
|
||||
|
||||
if (_servicesChangedCharacteristic && _servicesChangedCharacteristic->release() == 0) {
|
||||
delete(_servicesChangedCharacteristic);
|
||||
_servicesChangedCharacteristic = NULL;
|
||||
}
|
||||
|
||||
clearAttributes();
|
||||
}
|
||||
|
||||
void GATTClass::setDeviceName(const char* deviceName)
|
||||
{
|
||||
_deviceNameCharacteristic->writeValue(deviceName);
|
||||
}
|
||||
|
||||
void GATTClass::setAppearance(uint16_t appearance)
|
||||
{
|
||||
_appearanceCharacteristic->writeValue((uint8_t*)&appearance, sizeof(appearance));
|
||||
}
|
||||
|
||||
void GATTClass::addService(BLEService& service)
|
||||
{
|
||||
BLELocalService* localService = service.local();
|
||||
|
||||
if (localService) {
|
||||
addService(localService);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int GATTClass::attributeCount() const
|
||||
{
|
||||
return _attributes.size();
|
||||
}
|
||||
|
||||
BLELocalAttribute* GATTClass::attribute(unsigned int index) const
|
||||
{
|
||||
return _attributes.get(index);
|
||||
}
|
||||
|
||||
uint16_t GATTClass::serviceUuidForCharacteristic(BLELocalCharacteristic* characteristic) const
|
||||
{
|
||||
uint16_t serviceUuid = 0x0000;
|
||||
|
||||
BLELocalService* lastService = NULL;
|
||||
|
||||
for (unsigned int i = 0; i < attributeCount(); i++) {
|
||||
BLELocalAttribute* a = attribute(i);
|
||||
uint16_t attributeType = a->type();
|
||||
|
||||
if (attributeType == BLETypeService) {
|
||||
lastService = (BLELocalService*)a;
|
||||
} else if (a == characteristic) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastService) {
|
||||
if (lastService->uuidLength() == 2) {
|
||||
serviceUuid = *(uint16_t*)(lastService->uuidData());
|
||||
} else {
|
||||
serviceUuid = *(uint16_t*)(lastService->uuidData() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
return serviceUuid;
|
||||
}
|
||||
|
||||
void GATTClass::addService(BLELocalService* service)
|
||||
{
|
||||
service->retain();
|
||||
_attributes.add(service);
|
||||
_services.add(service);
|
||||
|
||||
uint16_t startHandle = attributeCount();
|
||||
|
||||
for (unsigned int i = 0; i < service->characteristicCount(); i++) {
|
||||
BLELocalCharacteristic* characteristic = service->characteristic(i);
|
||||
|
||||
characteristic->retain();
|
||||
_attributes.add(characteristic);
|
||||
characteristic->setHandle(attributeCount());
|
||||
|
||||
// add the characteristic again to make space of the characteristic value handle
|
||||
characteristic->retain();
|
||||
_attributes.add(characteristic);
|
||||
|
||||
for (unsigned int j = 0; j < characteristic->descriptorCount(); j++) {
|
||||
BLELocalDescriptor* descriptor = characteristic->descriptor(j);
|
||||
|
||||
descriptor->retain();
|
||||
_attributes.add(descriptor);
|
||||
descriptor->setHandle(attributeCount());
|
||||
}
|
||||
}
|
||||
|
||||
service->setHandles(startHandle, attributeCount());
|
||||
}
|
||||
|
||||
void GATTClass::clearAttributes()
|
||||
{
|
||||
for (unsigned int i = 0; i < attributeCount(); i++) {
|
||||
BLELocalAttribute* a = attribute(i);
|
||||
|
||||
if (a->release() == 0) {
|
||||
delete a;
|
||||
}
|
||||
}
|
||||
_attributes.clear();
|
||||
|
||||
for (unsigned int i = 0; i < _services.size(); i++) {
|
||||
_services.get(i)->clear();
|
||||
}
|
||||
_services.clear();
|
||||
|
||||
}
|
||||
|
||||
#if !defined(FAKE_GATT)
|
||||
GATTClass GATTObj;
|
||||
GATTClass& GATT = GATTObj;
|
||||
#endif
|
73
lib/ArduinoBLE/src/utility/GATT.h
Normal file
73
lib/ArduinoBLE/src/utility/GATT.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GATT_H_
|
||||
#define _GATT_H_
|
||||
|
||||
#include "utility/BLELinkedList.h"
|
||||
|
||||
#include "local/BLELocalAttribute.h"
|
||||
#include "local/BLELocalCharacteristic.h"
|
||||
#include "local/BLELocalService.h"
|
||||
|
||||
#include "BLEService.h"
|
||||
|
||||
class GATTClass {
|
||||
public:
|
||||
GATTClass();
|
||||
virtual ~GATTClass();
|
||||
|
||||
virtual void begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void setDeviceName(const char* deviceName);
|
||||
virtual void setAppearance(uint16_t appearance);
|
||||
|
||||
virtual void addService(BLEService& service);
|
||||
|
||||
protected:
|
||||
friend class ATTClass;
|
||||
|
||||
virtual unsigned int attributeCount() const;
|
||||
virtual BLELocalAttribute* attribute(unsigned int index) const;
|
||||
|
||||
protected:
|
||||
friend class BLELocalCharacteristic;
|
||||
|
||||
virtual uint16_t serviceUuidForCharacteristic(BLELocalCharacteristic* characteristic) const;
|
||||
|
||||
private:
|
||||
virtual void addService(BLELocalService* service);
|
||||
|
||||
virtual void clearAttributes();
|
||||
|
||||
private:
|
||||
BLELinkedList<BLELocalAttribute*> _attributes;
|
||||
BLELinkedList<BLELocalService*> _services;
|
||||
|
||||
BLELocalService* _genericAccessService;
|
||||
BLELocalCharacteristic* _deviceNameCharacteristic;
|
||||
BLELocalCharacteristic* _appearanceCharacteristic;
|
||||
BLELocalService* _genericAttributeService;
|
||||
BLELocalCharacteristic* _servicesChangedCharacteristic;
|
||||
};
|
||||
|
||||
extern GATTClass& GATT;
|
||||
|
||||
#endif
|
1561
lib/ArduinoBLE/src/utility/HCI.cpp
Normal file
1561
lib/ArduinoBLE/src/utility/HCI.cpp
Normal file
File diff suppressed because it is too large
Load Diff
168
lib/ArduinoBLE/src/utility/HCI.h
Normal file
168
lib/ArduinoBLE/src/utility/HCI.h
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HCI_H_
|
||||
#define _HCI_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "bitDescriptions.h"
|
||||
|
||||
#include "L2CAPSignaling.h"
|
||||
|
||||
#define OGF_LINK_CTL 0x01
|
||||
#define OGF_HOST_CTL 0x03
|
||||
#define OGF_INFO_PARAM 0x04
|
||||
#define OGF_STATUS_PARAM 0x05
|
||||
#define OGF_LE_CTL 0x08
|
||||
|
||||
enum LE_COMMAND {
|
||||
ENCRYPT = 0x0017,
|
||||
RANDOM = 0x0018,
|
||||
LONG_TERM_KEY_REPLY = 0x001A,
|
||||
LONG_TERM_KEY_NEGATIVE_REPLY = 0x001B,
|
||||
READ_LOCAL_P256 = 0x0025,
|
||||
GENERATE_DH_KEY_V1 = 0x0026,
|
||||
GENERATE_DH_KEY_V2 = 0x005E
|
||||
};
|
||||
enum LE_META_EVENT {
|
||||
CONN_COMPLETE = 0x01,
|
||||
ADVERTISING_REPORT = 0x02,
|
||||
LONG_TERM_KEY_REQUEST = 0x05,
|
||||
REMOTE_CONN_PARAM_REQ = 0x06,
|
||||
READ_LOCAL_P256_COMPLETE = 0x08,
|
||||
GENERATE_DH_KEY_COMPLETE = 0x09,
|
||||
ENHANCED_CONN_COMPLETE = 0x0A,
|
||||
};
|
||||
String metaEventToString(LE_META_EVENT event);
|
||||
String commandToString(LE_COMMAND command);
|
||||
|
||||
class HCIClass {
|
||||
public:
|
||||
HCIClass();
|
||||
virtual ~HCIClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void poll();
|
||||
virtual void poll(unsigned long timeout);
|
||||
|
||||
virtual int reset();
|
||||
virtual int readLocalVersion(uint8_t& hciVer, uint16_t& hciRev, uint8_t& lmpVer,
|
||||
uint16_t& manufacturer, uint16_t& lmpSubVer);
|
||||
|
||||
virtual int readBdAddr(uint8_t addr[6]);
|
||||
virtual int readBdAddr();
|
||||
|
||||
virtual int readRssi(uint16_t handle);
|
||||
|
||||
virtual int setEventMask(uint64_t eventMask);
|
||||
virtual int setLeEventMask(uint64_t leEventMask);
|
||||
virtual int readLeBufferSize(uint16_t& pktLen, uint8_t& maxPkt);
|
||||
virtual int leSetRandomAddress(uint8_t addr[6]);
|
||||
virtual int leSetAdvertisingParameters(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint8_t advType, uint8_t ownBdaddrType,
|
||||
uint8_t directBdaddrType, uint8_t directBdaddr[6],
|
||||
uint8_t chanMap,
|
||||
uint8_t filter);
|
||||
virtual int leSetAdvertisingData(uint8_t length, uint8_t data[]);
|
||||
virtual int leSetScanResponseData(uint8_t length, uint8_t data[]);
|
||||
virtual int leSetAdvertiseEnable(uint8_t enable);
|
||||
virtual int leSetScanParameters(uint8_t type, uint16_t interval, uint16_t window,
|
||||
uint8_t ownBdaddrType, uint8_t filter);
|
||||
virtual int leSetScanEnable(uint8_t enabled, uint8_t duplicates);
|
||||
virtual int leCreateConn(uint16_t interval, uint16_t window, uint8_t initiatorFilter,
|
||||
uint8_t peerBdaddrType, uint8_t peerBdaddr[6], uint8_t ownBdaddrType,
|
||||
uint16_t minInterval, uint16_t maxInterval, uint16_t latency,
|
||||
uint16_t supervisionTimeout, uint16_t minCeLength, uint16_t maxCeLength);
|
||||
virtual int leConnUpdate(uint16_t handle, uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t supervisionTimeout);
|
||||
virtual int leCancelConn();
|
||||
virtual int leEncrypt(uint8_t* Key, uint8_t* plaintext, uint8_t* status, uint8_t* ciphertext);
|
||||
// Generate a 64 bit random number
|
||||
virtual int leRand(uint8_t rand[]);
|
||||
virtual AuthReq localAuthreq();
|
||||
virtual uint8_t localIOCap();
|
||||
|
||||
virtual void saveNewAddress(uint8_t addressType, uint8_t* address, uint8_t* peerIrk, uint8_t* remoteIrk);
|
||||
virtual void leAddResolvingAddress(uint8_t addressType, uint8_t* address, uint8_t* peerIrk, uint8_t* remoteIrk);
|
||||
virtual int leStopResolvingAddresses();
|
||||
virtual int leStartResolvingAddresses();
|
||||
virtual int leReadPeerResolvableAddress(uint8_t peerAddressType, uint8_t* peerIdentityAddress, uint8_t* peerResolvableAddress);
|
||||
|
||||
virtual void readStoredLKs();
|
||||
virtual int readStoredLK(uint8_t BD_ADDR[], uint8_t read_all = 0);
|
||||
virtual void writeLK(uint8_t peerAddress[], uint8_t LK[]);
|
||||
virtual int tryResolveAddress(uint8_t* BDAddr, uint8_t* address);
|
||||
|
||||
virtual int sendAclPkt(uint16_t handle, uint8_t cid, uint8_t plen, void* data);
|
||||
|
||||
virtual int disconnect(uint16_t handle);
|
||||
|
||||
virtual void debug(Stream& stream);
|
||||
virtual void noDebug();
|
||||
|
||||
// TODO: Send command be private again & use ATT implementation of send command within ATT.
|
||||
virtual int sendCommand(uint16_t opcode, uint8_t plen = 0, void* parameters = NULL);
|
||||
uint8_t remotePublicKeyBuffer[64];
|
||||
uint8_t localPublicKeyBuffer[64];
|
||||
uint8_t remoteDHKeyCheckBuffer[16];
|
||||
uint8_t Na[16];
|
||||
uint8_t Nb[16];
|
||||
uint8_t DHKey[32];
|
||||
uint8_t localAddr[6];
|
||||
uint8_t LTK[16];
|
||||
virtual int getLTK(uint8_t* address, uint8_t* LTK);
|
||||
virtual int storeLTK(uint8_t* address, uint8_t* LTK);
|
||||
virtual int storeIRK(uint8_t* address, uint8_t* IRK);
|
||||
int (*_storeIRK)(uint8_t* address, uint8_t* peerIrk) = 0;
|
||||
int (*_getIRKs)(uint8_t* nIRKs,uint8_t** BADDR_type, uint8_t*** BADDRs, uint8_t*** IRKs) = 0;
|
||||
int (*_storeLTK)(uint8_t*, uint8_t*) = 0;
|
||||
int (*_getLTK)(uint8_t*, uint8_t*) = 0;
|
||||
void (*_displayCode)(uint32_t confirmationCode) = 0;
|
||||
bool (*_binaryConfirmPairing)() = 0;
|
||||
|
||||
private:
|
||||
|
||||
virtual void handleAclDataPkt(uint8_t plen, uint8_t pdata[]);
|
||||
virtual void handleNumCompPkts(uint16_t handle, uint16_t numPkts);
|
||||
virtual void handleEventPkt(uint8_t plen, uint8_t pdata[]);
|
||||
|
||||
virtual void dumpPkt(const char* prefix, uint8_t plen, uint8_t pdata[]);
|
||||
|
||||
Stream* _debug;
|
||||
|
||||
int _recvIndex;
|
||||
uint8_t _recvBuffer[3 + 255];
|
||||
|
||||
uint16_t _cmdCompleteOpcode;
|
||||
int _cmdCompleteStatus;
|
||||
uint8_t _cmdResponseLen;
|
||||
uint8_t* _cmdResponse;
|
||||
|
||||
uint8_t _maxPkt;
|
||||
uint8_t _pendingPkt;
|
||||
|
||||
uint8_t _l2CapPduBuffer[255];
|
||||
uint8_t _l2CapPduBufferSize;
|
||||
};
|
||||
|
||||
extern HCIClass& HCI;
|
||||
|
||||
#endif
|
336
lib/ArduinoBLE/src/utility/HCICordioTransport.cpp
Normal file
336
lib/ArduinoBLE/src/utility/HCICordioTransport.cpp
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_MBED) && !defined(TARGET_NANO_RP2040_CONNECT) // && !defined(CORE_CM4)
|
||||
#include <Arduino.h>
|
||||
#include <mbed.h>
|
||||
|
||||
#include <driver/CordioHCITransportDriver.h>
|
||||
#include <driver/CordioHCIDriver.h>
|
||||
|
||||
#if defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)
|
||||
#include "ble/BLE.h"
|
||||
#include <events/mbed_events.h>
|
||||
#endif
|
||||
|
||||
// Parts of this file are based on: https://github.com/ARMmbed/mbed-os-cordio-hci-passthrough/pull/2
|
||||
// With permission from the Arm Mbed team to re-license
|
||||
|
||||
#if CORDIO_ZERO_COPY_HCI
|
||||
#include <wsf_types.h>
|
||||
#include <wsf_buf.h>
|
||||
#include <wsf_msg.h>
|
||||
#include <wsf_os.h>
|
||||
#include <wsf_buf.h>
|
||||
#include <wsf_timer.h>
|
||||
|
||||
/* avoid many small allocs (and WSF doesn't have smaller buffers) */
|
||||
#define MIN_WSF_ALLOC (16)
|
||||
#endif //CORDIO_ZERO_COPY_HCI
|
||||
|
||||
#include "HCICordioTransport.h"
|
||||
|
||||
#if (MBED_VERSION > MBED_ENCODE_VERSION(6, 2, 0))
|
||||
#define BLE_NAMESPACE ble
|
||||
#else
|
||||
#define BLE_NAMESPACE ble::vendor::cordio
|
||||
#endif
|
||||
|
||||
#include "CordioHCICustomDriver.h"
|
||||
|
||||
extern BLE_NAMESPACE::CordioHCIDriver& ble_cordio_get_hci_driver();
|
||||
extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len);
|
||||
|
||||
namespace BLE_NAMESPACE {
|
||||
struct CordioHCIHook {
|
||||
static CordioHCIDriver& getDriver() {
|
||||
return ble_cordio_get_hci_driver();
|
||||
}
|
||||
|
||||
static CordioHCITransportDriver& getTransportDriver() {
|
||||
return getDriver()._transport_driver;
|
||||
}
|
||||
|
||||
static void setDataReceivedHandler(void (*handler)(uint8_t*, uint8_t)) {
|
||||
getTransportDriver().set_data_received_handler(handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
using BLE_NAMESPACE::CordioHCIHook;
|
||||
|
||||
#if CORDIO_ZERO_COPY_HCI
|
||||
extern uint8_t *SystemHeapStart;
|
||||
extern uint32_t SystemHeapSize;
|
||||
|
||||
void init_wsf(BLE_NAMESPACE::buf_pool_desc_t& buf_pool_desc) {
|
||||
static bool init = false;
|
||||
|
||||
if (init) {
|
||||
return;
|
||||
}
|
||||
init = true;
|
||||
|
||||
// use the buffer for the WSF heap
|
||||
SystemHeapStart = buf_pool_desc.buffer_memory;
|
||||
SystemHeapSize = buf_pool_desc.buffer_size;
|
||||
|
||||
// Initialize buffers with the ones provided by the HCI driver
|
||||
uint16_t bytes_used = WsfBufInit(
|
||||
buf_pool_desc.pool_count,
|
||||
(wsfBufPoolDesc_t*)buf_pool_desc.pool_description
|
||||
);
|
||||
|
||||
// Raise assert if not enough memory was allocated
|
||||
MBED_ASSERT(bytes_used != 0);
|
||||
|
||||
SystemHeapStart += bytes_used;
|
||||
SystemHeapSize -= bytes_used;
|
||||
|
||||
WsfTimerInit();
|
||||
}
|
||||
|
||||
|
||||
extern "C" void wsf_mbed_ble_signal_event(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
#endif //CORDIO_ZERO_COPY_HCI
|
||||
|
||||
static void bleLoop()
|
||||
{
|
||||
#if CORDIO_ZERO_COPY_HCI
|
||||
uint64_t last_update_us = 0;
|
||||
mbed::LowPowerTimer timer;
|
||||
|
||||
timer.start();
|
||||
|
||||
while (true) {
|
||||
last_update_us += (uint64_t) timer.read_high_resolution_us();
|
||||
timer.reset();
|
||||
|
||||
uint64_t last_update_ms = (last_update_us / 1000);
|
||||
wsfTimerTicks_t wsf_ticks = (last_update_ms / WSF_MS_PER_TICK);
|
||||
|
||||
if (wsf_ticks > 0) {
|
||||
WsfTimerUpdate(wsf_ticks);
|
||||
last_update_us -= (last_update_ms * 1000);
|
||||
}
|
||||
|
||||
wsfOsDispatcher();
|
||||
|
||||
bool sleep = false;
|
||||
{
|
||||
/* call needs interrupts disabled */
|
||||
mbed::CriticalSectionLock critical_section;
|
||||
if (wsfOsReadyToSleep()) {
|
||||
sleep = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time_spent = (uint64_t) timer.read_high_resolution_us();
|
||||
|
||||
/* don't bother sleeping if we're already past tick */
|
||||
if (sleep && (WSF_MS_PER_TICK * 1000 > time_spent)) {
|
||||
/* sleep to maintain constant tick rate */
|
||||
uint64_t wait_time_us = WSF_MS_PER_TICK * 1000 - time_spent;
|
||||
uint64_t wait_time_ms = wait_time_us / 1000;
|
||||
|
||||
wait_time_us = wait_time_us % 1000;
|
||||
|
||||
if (wait_time_ms) {
|
||||
rtos::ThisThread::sleep_for(wait_time_ms);
|
||||
}
|
||||
|
||||
if (wait_time_us) {
|
||||
wait_us(wait_time_us);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
while(true) {
|
||||
rtos::ThisThread::sleep_for(osWaitForever);
|
||||
}
|
||||
#endif // CORDIO_ZERO_COPY_HCI
|
||||
}
|
||||
|
||||
static rtos::EventFlags bleEventFlags;
|
||||
static rtos::Thread* bleLoopThread = NULL;
|
||||
|
||||
|
||||
HCICordioTransportClass::HCICordioTransportClass() :
|
||||
_begun(false)
|
||||
{
|
||||
}
|
||||
|
||||
HCICordioTransportClass::~HCICordioTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
#if (defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)) && !defined(CUSTOM_HCI_DRIVER)
|
||||
events::EventQueue eventQueue(10 * EVENTS_EVENT_SIZE);
|
||||
void scheduleMbedBleEvents(BLE::OnEventsToProcessCallbackContext *context) {
|
||||
eventQueue.call(mbed::Callback<void()>(&context->ble, &BLE::processEvents));
|
||||
}
|
||||
|
||||
void completeCallback(BLE::InitializationCompleteCallbackContext *context) {
|
||||
eventQueue.break_dispatch();
|
||||
}
|
||||
#endif
|
||||
|
||||
int HCICordioTransportClass::begin()
|
||||
{
|
||||
_rxBuf.clear();
|
||||
|
||||
#if CORDIO_ZERO_COPY_HCI
|
||||
BLE_NAMESPACE::buf_pool_desc_t bufPoolDesc = CordioHCIHook::getDriver().get_buffer_pool_description();
|
||||
init_wsf(bufPoolDesc);
|
||||
#endif
|
||||
|
||||
#if (defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)) && !defined(CUSTOM_HCI_DRIVER)
|
||||
|
||||
BLE &ble = BLE::Instance();
|
||||
ble.onEventsToProcess(scheduleMbedBleEvents);
|
||||
|
||||
ble.init(completeCallback);
|
||||
eventQueue.dispatch(10000);
|
||||
|
||||
if (!ble.hasInitialized()){
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
CordioHCIHook::getDriver().initialize();
|
||||
#endif
|
||||
|
||||
if (bleLoopThread == NULL) {
|
||||
bleLoopThread = new rtos::Thread();
|
||||
bleLoopThread->start(bleLoop);
|
||||
}
|
||||
|
||||
CordioHCIHook::setDataReceivedHandler(HCICordioTransportClass::onDataReceived);
|
||||
|
||||
_begun = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HCICordioTransportClass::end()
|
||||
{
|
||||
if (bleLoopThread != NULL) {
|
||||
bleLoopThread->terminate();
|
||||
delete bleLoopThread;
|
||||
bleLoopThread = NULL;
|
||||
}
|
||||
// Reset the callback with the mbed-os default handler to properly handle the following CYW43xxx chip initializations and begins
|
||||
CordioHCIHook::setDataReceivedHandler(hciTrSerialRxIncoming);
|
||||
|
||||
#if (defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_GIGA) || defined(ARDUINO_OPTA)) && !defined(CUSTOM_HCI_DRIVER)
|
||||
BLE &ble = BLE::Instance();
|
||||
ble.shutdown();
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_STM32H7)
|
||||
CordioHCIHook::getDriver().terminate();
|
||||
#endif
|
||||
|
||||
_begun = false;
|
||||
}
|
||||
|
||||
void HCICordioTransportClass::wait(unsigned long timeout)
|
||||
{
|
||||
{
|
||||
mbed::CriticalSectionLock critical_section;
|
||||
if (available()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for handleRxData to signal
|
||||
bleEventFlags.wait_all(0x01, timeout, true);
|
||||
}
|
||||
|
||||
int HCICordioTransportClass::available()
|
||||
{
|
||||
return _rxBuf.available();
|
||||
}
|
||||
|
||||
int HCICordioTransportClass::peek()
|
||||
{
|
||||
return _rxBuf.peek();
|
||||
}
|
||||
|
||||
int HCICordioTransportClass::read()
|
||||
{
|
||||
return _rxBuf.read_char();
|
||||
}
|
||||
|
||||
void HCICordioTransportClass::lockForRead() {
|
||||
mbed::CriticalSectionLock::enable();
|
||||
}
|
||||
|
||||
void HCICordioTransportClass::unlockForRead() {
|
||||
mbed::CriticalSectionLock::disable();
|
||||
}
|
||||
|
||||
size_t HCICordioTransportClass::write(const uint8_t* data, size_t length)
|
||||
{
|
||||
if (!_begun) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t packetLength = length - 1;
|
||||
uint8_t packetType = data[0];
|
||||
|
||||
#if CORDIO_ZERO_COPY_HCI
|
||||
uint8_t* packet = (uint8_t*)WsfMsgAlloc(max(packetLength, MIN_WSF_ALLOC));
|
||||
|
||||
memcpy(packet, &data[1], packetLength);
|
||||
|
||||
return CordioHCIHook::getTransportDriver().write(packetType, packetLength, packet);
|
||||
#else
|
||||
return CordioHCIHook::getTransportDriver().write(packetType, packetLength, (uint8_t*)&data[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void HCICordioTransportClass::handleRxData(uint8_t* data, uint8_t len)
|
||||
{
|
||||
{
|
||||
mbed::CriticalSectionLock critical_section;
|
||||
if (_rxBuf.availableForStore() < len) {
|
||||
// drop!
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
_rxBuf.store_char(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bleEventFlags.set(0x01);
|
||||
}
|
||||
|
||||
HCICordioTransportClass HCICordioTransport;
|
||||
HCITransportInterface& HCITransport = HCICordioTransport;
|
||||
|
||||
void HCICordioTransportClass::onDataReceived(uint8_t* data, uint8_t len)
|
||||
{
|
||||
HCICordioTransport.handleRxData(data, len);
|
||||
}
|
||||
|
||||
#endif
|
57
lib/ArduinoBLE/src/utility/HCICordioTransport.h
Normal file
57
lib/ArduinoBLE/src/utility/HCICordioTransport.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2019 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HCI_CORDIO_TRANSPORT_H_
|
||||
#define _HCI_CORDIO_TRANSPORT_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "api/RingBuffer.h"
|
||||
|
||||
#include "HCITransport.h"
|
||||
|
||||
class HCICordioTransportClass : public HCITransportInterface {
|
||||
public:
|
||||
HCICordioTransportClass();
|
||||
virtual ~HCICordioTransportClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void wait(unsigned long timeout);
|
||||
|
||||
virtual int available();
|
||||
virtual int peek();
|
||||
virtual int read();
|
||||
|
||||
virtual void lockForRead() override;
|
||||
virtual void unlockForRead() override;
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length);
|
||||
|
||||
private:
|
||||
static void onDataReceived(uint8_t* data, uint8_t len);
|
||||
void handleRxData(uint8_t* data, uint8_t len);
|
||||
|
||||
private:
|
||||
bool _begun;
|
||||
RingBufferN<256> _rxBuf;
|
||||
};
|
||||
|
||||
#endif
|
130
lib/ArduinoBLE/src/utility/HCISilabsTransport.cpp
Normal file
130
lib/ArduinoBLE/src/utility/HCISilabsTransport.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2024 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_SILABS)
|
||||
|
||||
#include "HCISilabsTransport.h"
|
||||
#include "sl_string.h"
|
||||
|
||||
extern "C" {
|
||||
#include "sl_btctrl_linklayer.h"
|
||||
#include "sl_hci_common_transport.h"
|
||||
}
|
||||
|
||||
extern "C" int strcasecmp(char const *a, char const *b) {
|
||||
return sl_strcasecmp(a, b);
|
||||
}
|
||||
|
||||
static RingBufferN<512> buf;
|
||||
|
||||
HCISilabsTransportClass::HCISilabsTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
HCISilabsTransportClass::~HCISilabsTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
int HCISilabsTransportClass::begin()
|
||||
{
|
||||
if(!sl_btctrl_is_initialized()) {
|
||||
sl_bt_controller_init();
|
||||
}
|
||||
|
||||
/* Initialize adv & scan components */
|
||||
sl_btctrl_init_adv();
|
||||
sl_btctrl_init_scan();
|
||||
sl_btctrl_init_conn();
|
||||
sl_btctrl_init_adv_ext();
|
||||
sl_btctrl_init_scan_ext();
|
||||
|
||||
/* Initialize HCI controller */
|
||||
sl_bthci_init_upper();
|
||||
sl_btctrl_hci_parser_init_default();
|
||||
sl_btctrl_hci_parser_init_conn();
|
||||
sl_btctrl_hci_parser_init_adv();
|
||||
sl_btctrl_hci_parser_init_phy();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HCISilabsTransportClass::end()
|
||||
{
|
||||
sl_bt_controller_deinit();
|
||||
}
|
||||
|
||||
void HCISilabsTransportClass::wait(unsigned long timeout)
|
||||
{
|
||||
for (unsigned long start = millis(); (millis() - start) < timeout;) {
|
||||
if (available()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HCISilabsTransportClass::available()
|
||||
{
|
||||
return buf.available();
|
||||
}
|
||||
|
||||
int HCISilabsTransportClass::peek()
|
||||
{
|
||||
return buf.peek();
|
||||
}
|
||||
|
||||
int HCISilabsTransportClass::read()
|
||||
{
|
||||
return buf.read_char();
|
||||
}
|
||||
|
||||
size_t HCISilabsTransportClass::write(const uint8_t* data, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = hci_common_transport_receive((uint8_t *)data, len, true);
|
||||
|
||||
if (ret == 0) return len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
/**
|
||||
* @brief Transmit HCI message using the currently used transport layer.
|
||||
* The HCI calls this function to transmit a full HCI message.
|
||||
* @param[in] data Packet type followed by HCI packet data.
|
||||
* @param[in] len Length of the `data` parameter
|
||||
* @return 0 - on success, or non-zero on failure.
|
||||
*/
|
||||
uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
buf.store_char(data[i]);
|
||||
if (buf.isFull()) return SL_STATUS_FAIL;
|
||||
}
|
||||
|
||||
sl_btctrl_hci_transmit_complete(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HCISilabsTransportClass HCISilabsTransport;
|
||||
|
||||
HCITransportInterface& HCITransport = HCISilabsTransport;
|
||||
|
||||
#endif
|
42
lib/ArduinoBLE/src/utility/HCISilabsTransport.h
Normal file
42
lib/ArduinoBLE/src/utility/HCISilabsTransport.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HCI_SILABS_TRANSPORT_H_
|
||||
#define _HCI_SILABS_TRANSPORT_H_
|
||||
|
||||
#include "HCITransport.h"
|
||||
|
||||
class HCISilabsTransportClass : public HCITransportInterface {
|
||||
public:
|
||||
HCISilabsTransportClass();
|
||||
virtual ~HCISilabsTransportClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void wait(unsigned long timeout);
|
||||
|
||||
virtual int available();
|
||||
virtual int peek();
|
||||
virtual int read();
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length);
|
||||
};
|
||||
|
||||
#endif
|
47
lib/ArduinoBLE/src/utility/HCITransport.h
Normal file
47
lib/ArduinoBLE/src/utility/HCITransport.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HCI_TRANSPORT_INTERFACE_H_
|
||||
#define _HCI_TRANSPORT_INTERFACE_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class HCITransportInterface {
|
||||
public:
|
||||
virtual int begin() = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
virtual void wait(unsigned long timeout) = 0;
|
||||
|
||||
virtual int available() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual int read() = 0;
|
||||
|
||||
// Some transports require a lock to use available/peek/read
|
||||
// These methods allow to keep the lock while reading an unknown number of bytes
|
||||
// These methods might disable interrupts. Only keep the lock as long as necessary.
|
||||
virtual void lockForRead() {}
|
||||
virtual void unlockForRead() {}
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length) = 0;
|
||||
};
|
||||
|
||||
extern HCITransportInterface& HCITransport;
|
||||
|
||||
#endif
|
109
lib/ArduinoBLE/src/utility/HCIUartTransport.cpp
Normal file
109
lib/ArduinoBLE/src/utility/HCIUartTransport.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) && !defined(ARDUINO_SILABS) && !defined(ARDUINO_UNOR4_WIFI) || defined(TARGET_NANO_RP2040_CONNECT) //|| defined(CORE_CM4)
|
||||
|
||||
#include "HCIUartTransport.h"
|
||||
|
||||
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
|
||||
#define SerialHCI Serial2
|
||||
#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT)
|
||||
// SerialHCI is already defined in the variant
|
||||
#elif defined(ARDUINO_PORTENTA_H7_M4)
|
||||
// SerialHCI is already defined in the variant
|
||||
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION)
|
||||
#define SerialHCI Serial2
|
||||
#elif defined(ARDUINO_OPTA)
|
||||
#define SerialHCI Serial3
|
||||
#elif defined(ARDUINO_PORTENTA_C33)
|
||||
#define SerialHCI Serial5
|
||||
#elif defined(ARDUINO_GIGA)
|
||||
arduino::UART SerialHCI(CYBSP_BT_UART_TX, CYBSP_BT_UART_RX, CYBSP_BT_UART_RTS, CYBSP_BT_UART_CTS);
|
||||
#else
|
||||
#error "Unsupported board selected!"
|
||||
#endif
|
||||
|
||||
HCIUartTransportClass::HCIUartTransportClass(HardwareSerial& uart, unsigned long baudrate) :
|
||||
_uart(&uart),
|
||||
_baudrate(baudrate)
|
||||
{
|
||||
}
|
||||
|
||||
HCIUartTransportClass::~HCIUartTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
int HCIUartTransportClass::begin()
|
||||
{
|
||||
_uart->begin(_baudrate);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HCIUartTransportClass::end()
|
||||
{
|
||||
_uart->end();
|
||||
}
|
||||
|
||||
void HCIUartTransportClass::wait(unsigned long timeout)
|
||||
{
|
||||
for (unsigned long start = millis(); (millis() - start) < timeout;) {
|
||||
if (available()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HCIUartTransportClass::available()
|
||||
{
|
||||
return _uart->available();
|
||||
}
|
||||
|
||||
int HCIUartTransportClass::peek()
|
||||
{
|
||||
return _uart->peek();
|
||||
}
|
||||
|
||||
int HCIUartTransportClass::read()
|
||||
{
|
||||
return _uart->read();
|
||||
}
|
||||
|
||||
size_t HCIUartTransportClass::write(const uint8_t* data, size_t length)
|
||||
{
|
||||
#ifdef ARDUINO_AVR_UNO_WIFI_REV2
|
||||
// wait while the CTS pin is low
|
||||
while (digitalRead(NINA_CTS) == HIGH);
|
||||
#endif
|
||||
|
||||
size_t result = _uart->write(data, length);
|
||||
|
||||
_uart->flush();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_NANO_RP2040_CONNECT)
|
||||
HCIUartTransportClass HCIUartTransport(SerialHCI, 119600);
|
||||
#else
|
||||
HCIUartTransportClass HCIUartTransport(SerialHCI, 912600);
|
||||
#endif
|
||||
HCITransportInterface& HCITransport = HCIUartTransport;
|
||||
|
||||
#endif
|
46
lib/ArduinoBLE/src/utility/HCIUartTransport.h
Normal file
46
lib/ArduinoBLE/src/utility/HCIUartTransport.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _HCI_UART_TRANSPORT_H_
|
||||
#define _HCI_UART_TRANSPORT_H_
|
||||
|
||||
#include "HCITransport.h"
|
||||
|
||||
class HCIUartTransportClass : public HCITransportInterface {
|
||||
public:
|
||||
HCIUartTransportClass(HardwareSerial& uart, unsigned long baudrate);
|
||||
virtual ~HCIUartTransportClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void wait(unsigned long timeout);
|
||||
|
||||
virtual int available();
|
||||
virtual int peek();
|
||||
virtual int read();
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length);
|
||||
|
||||
private:
|
||||
HardwareSerial* _uart;
|
||||
unsigned long _baudrate;
|
||||
};
|
||||
|
||||
#endif
|
144
lib/ArduinoBLE/src/utility/HCIVirtualTransport.cpp
Normal file
144
lib/ArduinoBLE/src/utility/HCIVirtualTransport.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(ESP32)
|
||||
|
||||
#include "HCIVirtualTransport.h"
|
||||
|
||||
StreamBufferHandle_t rec_buffer;
|
||||
StreamBufferHandle_t send_buffer;
|
||||
TaskHandle_t bleHandle;
|
||||
|
||||
|
||||
static void notify_host_send_available(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int notify_host_recv(uint8_t *data, uint16_t length)
|
||||
{
|
||||
xStreamBufferSend(rec_buffer,data,length,portMAX_DELAY); // !!!potentially waiting forever
|
||||
return 0;
|
||||
}
|
||||
|
||||
static esp_vhci_host_callback_t vhci_host_cb = {
|
||||
notify_host_send_available,
|
||||
notify_host_recv
|
||||
};
|
||||
|
||||
void bleTask(void *pvParameters)
|
||||
{
|
||||
esp_vhci_host_register_callback(&vhci_host_cb);
|
||||
size_t length;
|
||||
uint8_t mybuf[258];
|
||||
|
||||
while(true){
|
||||
length = xStreamBufferReceive(send_buffer,mybuf,258,portMAX_DELAY);
|
||||
while (!esp_vhci_host_check_send_available()) {}
|
||||
esp_vhci_host_send_packet(mybuf, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HCIVirtualTransportClass::HCIVirtualTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
HCIVirtualTransportClass::~HCIVirtualTransportClass()
|
||||
{
|
||||
}
|
||||
|
||||
int HCIVirtualTransportClass::begin()
|
||||
{
|
||||
btStarted(); // this somehow stops the arduino ide from initializing bluedroid
|
||||
|
||||
rec_buffer = xStreamBufferCreate(258, 1);
|
||||
send_buffer = xStreamBufferCreate(258, 1);
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
bt_cfg.mode = ESP_BT_MODE_BLE; //original esp32 chip
|
||||
#else
|
||||
#if !(CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2)
|
||||
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE; //different api for newer models
|
||||
#endif
|
||||
#endif
|
||||
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
esp_bt_controller_init(&bt_cfg);
|
||||
esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||
xTaskCreatePinnedToCore(&bleTask, "bleTask", 2048, NULL, 5, &bleHandle, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HCIVirtualTransportClass::end()
|
||||
{
|
||||
vStreamBufferDelete(rec_buffer);
|
||||
vStreamBufferDelete(send_buffer);
|
||||
esp_bt_controller_disable();
|
||||
esp_bt_controller_deinit();
|
||||
vTaskDelete(bleHandle);
|
||||
}
|
||||
|
||||
void HCIVirtualTransportClass::wait(unsigned long timeout)
|
||||
{
|
||||
for (unsigned long start = (esp_timer_get_time() / 1000ULL); ((esp_timer_get_time() / 1000ULL) - start) < timeout;) {
|
||||
if (available()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HCIVirtualTransportClass::available()
|
||||
{
|
||||
size_t bytes = xStreamBufferBytesAvailable(rec_buffer);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// never called
|
||||
int HCIVirtualTransportClass::peek()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int HCIVirtualTransportClass::read()
|
||||
{
|
||||
uint8_t c;
|
||||
if(xStreamBufferReceive(rec_buffer, &c, 1, portMAX_DELAY)) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t HCIVirtualTransportClass::write(const uint8_t* data, size_t length)
|
||||
{
|
||||
size_t result = xStreamBufferSend(send_buffer,data,length,portMAX_DELAY);
|
||||
return result;
|
||||
}
|
||||
|
||||
HCIVirtualTransportClass HCIVirtualTransport;
|
||||
|
||||
HCITransportInterface& HCITransport = HCIVirtualTransport;
|
||||
|
||||
#endif
|
50
lib/ArduinoBLE/src/utility/HCIVirtualTransport.h
Normal file
50
lib/ArduinoBLE/src/utility/HCIVirtualTransport.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "HCITransport.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/stream_buffer.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "esp32-hal-bt.h" // this is needed to disable bluedroid
|
||||
|
||||
|
||||
class HCIVirtualTransportClass : public HCITransportInterface {
|
||||
public:
|
||||
HCIVirtualTransportClass();
|
||||
virtual ~HCIVirtualTransportClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void wait(unsigned long timeout);
|
||||
|
||||
virtual int available();
|
||||
virtual int peek();
|
||||
virtual int read();
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length);
|
||||
};
|
112
lib/ArduinoBLE/src/utility/HCIVirtualTransportAT.cpp
Normal file
112
lib/ArduinoBLE/src/utility/HCIVirtualTransportAT.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_UNOR4_WIFI)
|
||||
|
||||
#include "HCIVirtualTransportAT.h"
|
||||
|
||||
extern ModemClass modem;
|
||||
|
||||
HCIVirtualTransportATClass::HCIVirtualTransportATClass()
|
||||
{
|
||||
}
|
||||
|
||||
HCIVirtualTransportATClass::~HCIVirtualTransportATClass()
|
||||
{
|
||||
}
|
||||
|
||||
static RingBufferN<258> buf;
|
||||
|
||||
int HCIVirtualTransportATClass::begin()
|
||||
{
|
||||
// TODO: add this helper
|
||||
//modem.debug(Serial);
|
||||
buf.clear();
|
||||
//modem.debug(true);
|
||||
std::string res = "";
|
||||
modem.begin();
|
||||
if (modem.write(std::string(PROMPT(_HCI_BEGIN)), res, CMD(_HCI_BEGIN))) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HCIVirtualTransportATClass::end()
|
||||
{
|
||||
}
|
||||
|
||||
void HCIVirtualTransportATClass::wait(unsigned long timeout)
|
||||
{
|
||||
std::string res = "";
|
||||
modem.write(std::string(PROMPT(_HCI_WAIT)), res, "%d\n\r", CMD_WRITE(_HCI_WAIT), timeout);
|
||||
}
|
||||
|
||||
int HCIVirtualTransportATClass::available()
|
||||
{
|
||||
std::string res = "";
|
||||
if (buf.available()) {
|
||||
return buf.available();
|
||||
}
|
||||
if (modem.write(std::string(PROMPT(_HCI_AVAILABLE)), res, CMD_READ(_HCI_AVAILABLE))) {
|
||||
return atoi(res.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// never called
|
||||
int HCIVirtualTransportATClass::peek()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int HCIVirtualTransportATClass::read()
|
||||
{
|
||||
uint8_t c;
|
||||
std::string res = "";
|
||||
if (buf.available()) {
|
||||
return buf.read_char();
|
||||
}
|
||||
modem.avoid_trim_results();
|
||||
modem.read_using_size();
|
||||
if (modem.write(std::string(PROMPT(_HCI_READ)), res, CMD(_HCI_READ))) {
|
||||
for(int i = 0; i < res.size(); i++) {
|
||||
buf.store_char((uint8_t)res[i]);
|
||||
}
|
||||
return buf.read_char();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t HCIVirtualTransportATClass::write(const uint8_t* data, size_t length)
|
||||
{
|
||||
std::string res = "";
|
||||
modem.write_nowait(std::string(PROMPT(_HCI_WRITE)), res, "%s%d\r\n" , CMD_WRITE(_HCI_WRITE), length);
|
||||
if(modem.passthrough(data, length)) {
|
||||
return length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HCIVirtualTransportATClass HCIVirtualTransportAT;
|
||||
|
||||
HCITransportInterface& HCITransport = HCIVirtualTransportAT;
|
||||
|
||||
#endif
|
42
lib/ArduinoBLE/src/utility/HCIVirtualTransportAT.h
Normal file
42
lib/ArduinoBLE/src/utility/HCIVirtualTransportAT.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "HCITransport.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "WiFiS3.h"
|
||||
|
||||
class HCIVirtualTransportATClass : public HCITransportInterface {
|
||||
public:
|
||||
HCIVirtualTransportATClass();
|
||||
virtual ~HCIVirtualTransportATClass();
|
||||
|
||||
virtual int begin();
|
||||
virtual void end();
|
||||
|
||||
virtual void wait(unsigned long timeout);
|
||||
|
||||
virtual int available();
|
||||
virtual int peek();
|
||||
virtual int read();
|
||||
|
||||
virtual size_t write(const uint8_t* data, size_t length);
|
||||
};
|
510
lib/ArduinoBLE/src/utility/L2CAPSignaling.cpp
Normal file
510
lib/ArduinoBLE/src/utility/L2CAPSignaling.cpp
Normal file
@ -0,0 +1,510 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "HCI.h"
|
||||
#include "ATT.h"
|
||||
#include "btct.h"
|
||||
#include "L2CAPSignaling.h"
|
||||
#include "keyDistribution.h"
|
||||
#include "bitDescriptions.h"
|
||||
#define CONNECTION_PARAMETER_UPDATE_REQUEST 0x12
|
||||
#define CONNECTION_PARAMETER_UPDATE_RESPONSE 0x13
|
||||
|
||||
//#define _BLE_TRACE_
|
||||
|
||||
L2CAPSignalingClass::L2CAPSignalingClass() :
|
||||
_minInterval(0),
|
||||
_maxInterval(0),
|
||||
_supervisionTimeout(0),
|
||||
_pairing_enabled(1)
|
||||
{
|
||||
}
|
||||
|
||||
L2CAPSignalingClass::~L2CAPSignalingClass()
|
||||
{
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::addConnection(uint16_t handle, uint8_t role, uint8_t /*peerBdaddrType*/,
|
||||
uint8_t /*peerBdaddr*/[6], uint16_t interval,
|
||||
uint16_t /*latency*/, uint16_t supervisionTimeout,
|
||||
uint8_t /*masterClockAccuracy*/)
|
||||
{
|
||||
if (role != 1) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
bool updateParameters = false;
|
||||
uint16_t updatedMinInterval = interval;
|
||||
uint16_t updatedMaxInterval = interval;
|
||||
uint16_t updatedSupervisionTimeout = supervisionTimeout;
|
||||
|
||||
if (_minInterval && _maxInterval) {
|
||||
if (interval < _minInterval || interval > _maxInterval) {
|
||||
updatedMinInterval = _minInterval;
|
||||
updatedMaxInterval = _maxInterval;
|
||||
updateParameters = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_supervisionTimeout && supervisionTimeout != _supervisionTimeout) {
|
||||
updatedSupervisionTimeout = _supervisionTimeout;
|
||||
updateParameters = true;
|
||||
}
|
||||
|
||||
if (updateParameters) {
|
||||
struct __attribute__ ((packed)) L2CAPConnectionParameterUpdateRequest {
|
||||
uint8_t code;
|
||||
uint8_t identifier;
|
||||
uint16_t length;
|
||||
uint16_t minInterval;
|
||||
uint16_t maxInterval;
|
||||
uint16_t latency;
|
||||
uint16_t supervisionTimeout;
|
||||
} request = { CONNECTION_PARAMETER_UPDATE_REQUEST, 0x01, 8,
|
||||
updatedMinInterval, updatedMaxInterval, 0x0000, updatedSupervisionTimeout };
|
||||
|
||||
HCI.sendAclPkt(handle, SIGNALING_CID, sizeof(request), &request);
|
||||
}
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[])
|
||||
{
|
||||
struct __attribute__ ((packed)) L2CAPSignalingHdr {
|
||||
uint8_t code;
|
||||
uint8_t identifier;
|
||||
uint16_t length;
|
||||
} *l2capSignalingHdr = (L2CAPSignalingHdr*)data;
|
||||
|
||||
if (dlen < sizeof(L2CAPSignalingHdr)) {
|
||||
// too short, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (dlen != (sizeof(L2CAPSignalingHdr) + l2capSignalingHdr->length)) {
|
||||
// invalid length, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t code = l2capSignalingHdr->code;
|
||||
uint8_t identifier = l2capSignalingHdr->identifier;
|
||||
uint16_t length = l2capSignalingHdr->length;
|
||||
data = &data[sizeof(L2CAPSignalingHdr)];
|
||||
|
||||
if (code == CONNECTION_PARAMETER_UPDATE_REQUEST) {
|
||||
connectionParameterUpdateRequest(connectionHandle, identifier, length, data);
|
||||
} else if (code == CONNECTION_PARAMETER_UPDATE_RESPONSE) {
|
||||
connectionParameterUpdateResponse(connectionHandle, identifier, length, data);
|
||||
}
|
||||
}
|
||||
void L2CAPSignalingClass::handleSecurityData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[])
|
||||
{
|
||||
struct __attribute__ ((packed)) L2CAPSignalingHdr {
|
||||
uint8_t code;
|
||||
uint8_t data[64];
|
||||
} *l2capSignalingHdr = (L2CAPSignalingHdr*)data;
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("dlen: ");
|
||||
Serial.println(dlen);
|
||||
#else
|
||||
(void)dlen;
|
||||
#endif
|
||||
uint8_t code = l2capSignalingHdr->code;
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("handleSecurityData: code: 0x");
|
||||
Serial.println(code, HEX);
|
||||
Serial.print("rx security:");
|
||||
btct.printBytes(data,dlen);
|
||||
#endif
|
||||
if (code == CONNECTION_PAIRING_REQUEST) {
|
||||
|
||||
if (isPairingEnabled()){
|
||||
if (_pairing_enabled >= 2) _pairing_enabled = 0; // 2 = pair once only
|
||||
|
||||
// 0x1
|
||||
struct __attribute__ ((packed)) PairingRequest {
|
||||
uint8_t ioCapability;
|
||||
uint8_t oobDataFlag;
|
||||
uint8_t authReq;
|
||||
uint8_t maxEncSize;
|
||||
uint8_t initiatorKeyDistribution;
|
||||
uint8_t responderKeyDistribution;
|
||||
} *pairingRequest = (PairingRequest*)l2capSignalingHdr->data;
|
||||
|
||||
KeyDistribution responseKD = KeyDistribution();
|
||||
responseKD.setIdKey(true);
|
||||
|
||||
ATT.remoteKeyDistribution = responseKD;// KeyDistribution(pairingRequest->initiatorKeyDistribution);
|
||||
ATT.localKeyDistribution = responseKD; //KeyDistribution(pairingRequest->responderKeyDistribution);
|
||||
// KeyDistribution rkd(pairingRequest->responderKeyDistribution);
|
||||
AuthReq req(pairingRequest->authReq);
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("Req has properties: ");
|
||||
Serial.print(req.Bonding()?"bonding, ":"no bonding, ");
|
||||
Serial.print(req.CT2()?"CT2, ":"no CT2, ");
|
||||
Serial.print(req.KeyPress()?"KeyPress, ":"no KeyPress, ");
|
||||
Serial.print(req.MITM()?"MITM, ":"no MITM, ");
|
||||
Serial.print(req.SC()?"SC, ":"no SC, ");
|
||||
#endif
|
||||
|
||||
uint8_t peerIOCap[3];
|
||||
peerIOCap[0] = pairingRequest->authReq;
|
||||
peerIOCap[1] = pairingRequest->oobDataFlag;
|
||||
peerIOCap[2] = pairingRequest->ioCapability;
|
||||
ATT.setPeerIOCap(connectionHandle, peerIOCap);
|
||||
ATT.setPeerEncryption(connectionHandle, ATT.getPeerEncryption(connectionHandle) | PEER_ENCRYPTION::PAIRING_REQUEST);
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("Peer encryption : 0b");
|
||||
Serial.println(ATT.getPeerEncryption(connectionHandle), BIN);
|
||||
#endif
|
||||
struct __attribute__ ((packed)) PairingResponse {
|
||||
uint8_t code;
|
||||
uint8_t ioCapability;
|
||||
uint8_t oobDataFlag;
|
||||
uint8_t authReq;
|
||||
uint8_t maxEncSize;
|
||||
uint8_t initiatorKeyDistribution;
|
||||
uint8_t responderKeyDistribution;
|
||||
} response = { CONNECTION_PAIRING_RESPONSE, HCI.localIOCap(), 0, HCI.localAuthreq().getOctet(), 0x10, responseKD.getOctet(), responseKD.getOctet()};
|
||||
|
||||
HCI.sendAclPkt(connectionHandle, SECURITY_CID, sizeof(response), &response);
|
||||
|
||||
} else {
|
||||
// Pairing not enabled
|
||||
uint8_t ret[2] = {CONNECTION_PAIRING_FAILED, 0x05}; // reqect pairing
|
||||
HCI.sendAclPkt(connectionHandle, SECURITY_CID, sizeof(ret), ret);
|
||||
ATT.setPeerEncryption(connectionHandle, NO_ENCRYPTION);
|
||||
}
|
||||
}
|
||||
else if (code == CONNECTION_PAIRING_RANDOM)
|
||||
{
|
||||
struct __attribute__ ((packed)) PairingRandom {
|
||||
uint8_t Na[16];
|
||||
} *pairingRandom = (PairingRandom*)l2capSignalingHdr->data;
|
||||
for(int i=0; i<16; i++){
|
||||
HCI.Na[15-i] = pairingRandom->Na[i];
|
||||
}
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("[Info] Pairing random.");
|
||||
#endif
|
||||
struct __attribute__ ((packed)) PairingResponse {
|
||||
uint8_t code;
|
||||
uint8_t Nb[16];
|
||||
} response = { CONNECTION_PAIRING_RANDOM, 0};
|
||||
for(int i=0; i< 16; i++) response.Nb[15-i] = HCI.Nb[i];
|
||||
|
||||
HCI.sendAclPkt(connectionHandle, SECURITY_CID, sizeof(response), &response);
|
||||
|
||||
// We now have all needed for compare value
|
||||
uint8_t g2Result[4];
|
||||
uint8_t U[32];
|
||||
uint8_t V[32];
|
||||
|
||||
for(int i=0; i<32; i++){
|
||||
U[31-i] = HCI.remotePublicKeyBuffer[i];
|
||||
V[31-i] = HCI.localPublicKeyBuffer[i];
|
||||
}
|
||||
|
||||
btct.g2(U,V,HCI.Na,HCI.Nb, g2Result);
|
||||
uint32_t result = 0;
|
||||
for(int i=0; i<4; i++) result += g2Result[3-i] << 8*i;
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("U : ");
|
||||
btct.printBytes(U,32);
|
||||
Serial.print("V : ");
|
||||
btct.printBytes(V,32);
|
||||
Serial.print("X : ");
|
||||
btct.printBytes(HCI.Na,16);
|
||||
Serial.print("Y : ");
|
||||
btct.printBytes(HCI.Nb,16);
|
||||
Serial.print("g2res : ");
|
||||
btct.printBytes(g2Result,4);
|
||||
Serial.print("Result : ");
|
||||
Serial.println(result);
|
||||
#endif
|
||||
|
||||
if(HCI._displayCode!=0){
|
||||
HCI._displayCode(result%1000000);
|
||||
}
|
||||
if(HCI._binaryConfirmPairing!=0){
|
||||
if(!HCI._binaryConfirmPairing()){
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("User rejection");
|
||||
#endif
|
||||
uint8_t rejection[2];
|
||||
rejection[0] = CONNECTION_PAIRING_FAILED;
|
||||
rejection[1] = 0x0C; // Numeric comparison failed
|
||||
HCI.sendAclPkt(connectionHandle, SECURITY_CID, 2, rejection);
|
||||
ATT.setPeerEncryption(connectionHandle, PEER_ENCRYPTION::NO_ENCRYPTION);
|
||||
}else{
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("User did confirm");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code == CONNECTION_PAIRING_RESPONSE)
|
||||
{
|
||||
}
|
||||
else if(code == CONNECTION_PAIRING_FAILED)
|
||||
{
|
||||
#ifdef _BLE_TRACE_
|
||||
struct __attribute__ ((packed)) PairingFailed
|
||||
{
|
||||
uint8_t code;
|
||||
uint8_t reason;
|
||||
} *pairingFailed = (PairingFailed*)data;
|
||||
Serial.print("Pairing failed with code: 0x");
|
||||
Serial.println(pairingFailed->reason,HEX);
|
||||
#endif
|
||||
ATT.setPeerEncryption(connectionHandle, PEER_ENCRYPTION::NO_ENCRYPTION);
|
||||
}
|
||||
else if (code == CONNECTION_IDENTITY_INFORMATION){
|
||||
struct __attribute__ ((packed)) IdentityInformation {
|
||||
uint8_t code;
|
||||
uint8_t PeerIRK[16];
|
||||
} *identityInformation = (IdentityInformation*)data;
|
||||
for(int i=0; i<16; i++) ATT.peerIRK[15-i] = identityInformation->PeerIRK[i];
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("Saved peer IRK");
|
||||
#endif
|
||||
}
|
||||
else if (code == CONNECTION_IDENTITY_ADDRESS){
|
||||
struct __attribute__ ((packed)) IdentityAddress {
|
||||
uint8_t code;
|
||||
uint8_t addressType;
|
||||
uint8_t address[6];
|
||||
} *identityAddress = (IdentityAddress*)data;
|
||||
// we can save this information now.
|
||||
uint8_t peerAddress[6];
|
||||
for(int i=0; i<6; i++) peerAddress[5-i] = identityAddress->address[i];
|
||||
|
||||
HCI.saveNewAddress(identityAddress->addressType, peerAddress, ATT.peerIRK, ATT.localIRK);
|
||||
if(HCI._storeLTK!=0){
|
||||
HCI._storeLTK(peerAddress, HCI.LTK);
|
||||
}
|
||||
}
|
||||
else if (code == CONNECTION_PAIRING_PUBLIC_KEY){
|
||||
/// Received a public key
|
||||
struct __attribute__ ((packed)) ConnectionPairingPublicKey {
|
||||
uint8_t x[32];
|
||||
uint8_t y[32];
|
||||
} *connectionPairingPublicKey = (ConnectionPairingPublicKey*)l2capSignalingHdr->data;
|
||||
struct __attribute__ ((packed)) GenerateDHKeyCommand {
|
||||
uint8_t x[32];
|
||||
uint8_t y[32];
|
||||
} generateDHKeyCommand = {
|
||||
{0x00},
|
||||
{0x00},
|
||||
};
|
||||
memcpy(generateDHKeyCommand.x,connectionPairingPublicKey->x,32);
|
||||
memcpy(generateDHKeyCommand.y,connectionPairingPublicKey->y,32);
|
||||
|
||||
if(ATT.setPeerEncryption(connectionHandle, ATT.getPeerEncryption(connectionHandle) | PEER_ENCRYPTION::REQUESTED_ENCRYPTION)){
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("[Info] Pairing public key");
|
||||
Serial.println("Requested encryption stored.");
|
||||
#endif
|
||||
}else{
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("[Info] Pairing public key");
|
||||
Serial.print("Failed to store encryption request with handle: 0x");
|
||||
Serial.println(connectionHandle,HEX);
|
||||
#endif
|
||||
}
|
||||
|
||||
memcpy(HCI.remotePublicKeyBuffer,&generateDHKeyCommand,sizeof(generateDHKeyCommand));
|
||||
HCI.sendCommand( (OGF_LE_CTL << 10 )| LE_COMMAND::READ_LOCAL_P256, 0);
|
||||
}
|
||||
else if(code == CONNECTION_PAIRING_DHKEY_CHECK)
|
||||
{
|
||||
uint8_t RemoteDHKeyCheck[16];
|
||||
for(int i=0; i<16; i++) RemoteDHKeyCheck[15-i] = l2capSignalingHdr->data[i];
|
||||
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("[Info] DH Key check");
|
||||
Serial.print("Remote DHKey Check: ");
|
||||
btct.printBytes(RemoteDHKeyCheck, 16);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
uint8_t encryptionState = ATT.getPeerEncryption(connectionHandle) | PEER_ENCRYPTION::RECEIVED_DH_CHECK;
|
||||
ATT.setPeerEncryption(connectionHandle, encryptionState);
|
||||
if((encryptionState & PEER_ENCRYPTION::DH_KEY_CALULATED) == 0){
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("DHKey not yet ready, will calculate f5, f6 later");
|
||||
#endif
|
||||
// store RemoteDHKeyCheck for later check
|
||||
memcpy(HCI.remoteDHKeyCheckBuffer,RemoteDHKeyCheck,16);
|
||||
|
||||
} else {
|
||||
// We've already calculated the DHKey so we can calculate our check and send it.
|
||||
smCalculateLTKandConfirm(connectionHandle, RemoteDHKeyCheck);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::smCalculateLTKandConfirm(uint16_t handle, uint8_t expectedEa[])
|
||||
{ // Authentication stage 2: LTK Calculation
|
||||
|
||||
uint8_t localAddress[7];
|
||||
uint8_t remoteAddress[7];
|
||||
ATT.getPeerAddrWithType(handle, remoteAddress);
|
||||
|
||||
HCI.readBdAddr();
|
||||
memcpy(&localAddress[1],HCI.localAddr,6);
|
||||
localAddress[0] = 0; // IOT 33 uses a static address // TODO: confirm for Nano BLE
|
||||
|
||||
// Compute the LTK and MacKey
|
||||
uint8_t MacKey[16];
|
||||
btct.f5(HCI.DHKey, HCI.Na, HCI.Nb, remoteAddress, localAddress, MacKey, HCI.LTK);
|
||||
|
||||
// Compute Ea and Eb
|
||||
uint8_t Ea[16];
|
||||
uint8_t Eb[16];
|
||||
uint8_t R[16];
|
||||
uint8_t MasterIOCap[3];
|
||||
uint8_t SlaveIOCap[3] = {HCI.localAuthreq().getOctet(), 0x0, HCI.localIOCap()};
|
||||
|
||||
ATT.getPeerIOCap(handle, MasterIOCap);
|
||||
for(int i=0; i<16; i++) R[i] = 0;
|
||||
|
||||
btct.f6(MacKey, HCI.Na,HCI.Nb,R, MasterIOCap, remoteAddress, localAddress, Ea);
|
||||
btct.f6(MacKey, HCI.Nb,HCI.Na,R, SlaveIOCap, localAddress, remoteAddress, Eb);
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("Calculate and confirm LTK via f5, f6:");
|
||||
Serial.print("DHKey : "); btct.printBytes(HCI.DHKey,32);
|
||||
Serial.print("Na : "); btct.printBytes(HCI.Na,16);
|
||||
Serial.print("Nb : "); btct.printBytes(HCI.Nb,16);
|
||||
Serial.print("MacKey : "); btct.printBytes(MacKey,16);
|
||||
Serial.print("LTK : "); btct.printBytes(HCI.LTK,16);
|
||||
Serial.print("Expected Ea: "); btct.printBytes(expectedEa, 16);
|
||||
Serial.print("Ea : "); btct.printBytes(Ea, 16);
|
||||
Serial.print("Eb : "); btct.printBytes(Eb,16);
|
||||
Serial.print("Local Addr : "); btct.printBytes(localAddress, 7);
|
||||
Serial.print("LocalIOCap : "); btct.printBytes(SlaveIOCap, 3);
|
||||
Serial.print("MasterAddr : "); btct.printBytes(remoteAddress, 7);
|
||||
Serial.print("MasterIOCAP: "); btct.printBytes(MasterIOCap, 3);
|
||||
#endif
|
||||
|
||||
// Check if Ea = expectedEa
|
||||
if (memcmp(Ea, expectedEa, 16) == 0){
|
||||
// Check ok
|
||||
// Send our confirmation value to complete authentication stage 2
|
||||
uint8_t ret[17];
|
||||
ret[0] = CONNECTION_PAIRING_DHKEY_CHECK;
|
||||
for(uint32_t i=0; i<sizeof(Eb); i++){
|
||||
ret[sizeof(Eb)-i] = Eb[i];
|
||||
}
|
||||
HCI.sendAclPkt(handle, SECURITY_CID, sizeof(ret), ret );
|
||||
uint8_t encryption = ATT.getPeerEncryption(handle) | PEER_ENCRYPTION::SENT_DH_CHECK;
|
||||
ATT.setPeerEncryption(handle, encryption);
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("DHKey check ok - send Eb back");
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// Check failed, abort pairing
|
||||
uint8_t ret[2] = {CONNECTION_PAIRING_FAILED, 0x0B}; // 0x0B = DHKey Check Failed
|
||||
HCI.sendAclPkt(handle, SECURITY_CID, sizeof(ret), ret);
|
||||
ATT.setPeerEncryption(handle, NO_ENCRYPTION);
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("Error: DHKey check failed - Aborting");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::removeConnection(uint8_t /*handle*/, uint16_t /*reason*/)
|
||||
{
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::setConnectionInterval(uint16_t minInterval, uint16_t maxInterval)
|
||||
{
|
||||
_minInterval = minInterval;
|
||||
_maxInterval = maxInterval;
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::setSupervisionTimeout(uint16_t supervisionTimeout)
|
||||
{
|
||||
_supervisionTimeout = supervisionTimeout;
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::setPairingEnabled(uint8_t enabled)
|
||||
{
|
||||
_pairing_enabled = enabled;
|
||||
}
|
||||
bool L2CAPSignalingClass::isPairingEnabled()
|
||||
{
|
||||
return _pairing_enabled > 0;
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::connectionParameterUpdateRequest(uint16_t handle, uint8_t identifier, uint8_t dlen, uint8_t data[])
|
||||
{
|
||||
struct __attribute__ ((packed)) L2CAPConnectionParameterUpdateRequest {
|
||||
uint16_t minInterval;
|
||||
uint16_t maxInterval;
|
||||
uint16_t latency;
|
||||
uint16_t supervisionTimeout;
|
||||
} *request = (L2CAPConnectionParameterUpdateRequest*)data;
|
||||
|
||||
if (dlen < sizeof(L2CAPConnectionParameterUpdateRequest)) {
|
||||
// too short, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
struct __attribute__ ((packed)) L2CAPConnectionParameterUpdateResponse {
|
||||
uint8_t code;
|
||||
uint8_t identifier;
|
||||
uint16_t length;
|
||||
uint16_t value;
|
||||
} response = { CONNECTION_PARAMETER_UPDATE_RESPONSE, identifier, 2, 0x0000 };
|
||||
|
||||
if (_minInterval && _maxInterval) {
|
||||
if (request->minInterval < _minInterval || request->maxInterval > _maxInterval) {
|
||||
response.value = 0x0001; // reject
|
||||
}
|
||||
}
|
||||
|
||||
if (_supervisionTimeout) {
|
||||
if (request->supervisionTimeout != _supervisionTimeout) {
|
||||
response.value = 0x0001; // reject
|
||||
}
|
||||
}
|
||||
|
||||
HCI.sendAclPkt(handle, SIGNALING_CID, sizeof(response), &response);
|
||||
|
||||
if (response.value == 0x0000) {
|
||||
HCI.leConnUpdate(handle, request->minInterval, request->maxInterval, request->latency, request->supervisionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void L2CAPSignalingClass::connectionParameterUpdateResponse(uint16_t /*handle*/, uint8_t /*identifier*/, uint8_t /*dlen*/, uint8_t /*data*/[])
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(FAKE_L2CAP)
|
||||
L2CAPSignalingClass L2CAPSignalingObj;
|
||||
L2CAPSignalingClass& L2CAPSignaling = L2CAPSignalingObj;
|
||||
#endif
|
96
lib/ArduinoBLE/src/utility/L2CAPSignaling.h
Normal file
96
lib/ArduinoBLE/src/utility/L2CAPSignaling.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _L2CAP_SIGNALING_H_
|
||||
#define _L2CAP_SIGNALING_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SIGNALING_CID 0x0005
|
||||
#define SECURITY_CID 0x0006
|
||||
|
||||
|
||||
#define CONNECTION_PAIRING_REQUEST 0x01
|
||||
#define CONNECTION_PAIRING_RESPONSE 0x02
|
||||
#define CONNECTION_PAIRING_CONFIRM 0x03
|
||||
#define CONNECTION_PAIRING_RANDOM 0x04
|
||||
#define CONNECTION_PAIRING_FAILED 0x05
|
||||
#define CONNECTION_ENCRYPTION_INFORMATION 0x06
|
||||
#define CONNECTION_MASTER_IDENTIFICATION 0x07
|
||||
#define CONNECTION_IDENTITY_INFORMATION 0x08
|
||||
#define CONNECTION_IDENTITY_ADDRESS 0x09
|
||||
#define CONNECTION_SIGNING_INFORMATION 0x0A
|
||||
#define CONNECTION_SECURITY_REQUEST 0x0B
|
||||
#define CONNECTION_PAIRING_PUBLIC_KEY 0x0C
|
||||
#define CONNECTION_PAIRING_DHKEY_CHECK 0x0D
|
||||
#define CONNECTION_PAIRING_KEYPRESS 0x0E
|
||||
|
||||
#define IOCAP_DISPLAY_ONLY 0x00
|
||||
#define IOCAP_DISPLAY_YES_NO 0x01
|
||||
#define IOCAP_KEYBOARD_ONLY 0x02
|
||||
#define IOCAP_NO_INPUT_NO_OUTPUT 0x03
|
||||
#define IOCAP_KEYBOARD_DISPLAY 0x04
|
||||
|
||||
|
||||
#define LOCAL_AUTHREQ 0b00101101
|
||||
// #define LOCAL_IOCAP IOCAP_DISPLAY_ONLY // will use JustWorks pairing
|
||||
|
||||
class L2CAPSignalingClass {
|
||||
public:
|
||||
L2CAPSignalingClass();
|
||||
virtual ~L2CAPSignalingClass();
|
||||
|
||||
virtual void addConnection(uint16_t handle, uint8_t role, uint8_t peerBdaddrType,
|
||||
uint8_t peerBdaddr[6], uint16_t interval,
|
||||
uint16_t latency, uint16_t supervisionTimeout,
|
||||
uint8_t masterClockAccuracy);
|
||||
|
||||
virtual void handleData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
|
||||
virtual void handleSecurityData(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]);
|
||||
|
||||
virtual void removeConnection(uint8_t handle, uint16_t reason);
|
||||
|
||||
virtual void setConnectionInterval(uint16_t minInterval, uint16_t maxInterval);
|
||||
|
||||
virtual void setSupervisionTimeout(uint16_t supervisionTimeout);
|
||||
|
||||
virtual void setPairingEnabled(uint8_t enabled);
|
||||
virtual bool isPairingEnabled();
|
||||
|
||||
|
||||
|
||||
virtual void smCalculateLTKandConfirm(uint16_t handle, uint8_t expectedEa[]);
|
||||
|
||||
|
||||
private:
|
||||
virtual void connectionParameterUpdateRequest(uint16_t handle, uint8_t identifier, uint8_t dlen, uint8_t data[]);
|
||||
virtual void connectionParameterUpdateResponse(uint16_t handle, uint8_t identifier, uint8_t dlen, uint8_t data[]);
|
||||
|
||||
|
||||
private:
|
||||
uint16_t _minInterval;
|
||||
uint16_t _maxInterval;
|
||||
uint16_t _supervisionTimeout;
|
||||
uint8_t _pairing_enabled;
|
||||
};
|
||||
|
||||
extern L2CAPSignalingClass& L2CAPSignaling;
|
||||
|
||||
#endif
|
30
lib/ArduinoBLE/src/utility/bitDescriptions.cpp
Normal file
30
lib/ArduinoBLE/src/utility/bitDescriptions.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "bitDescriptions.h"
|
||||
|
||||
|
||||
#define BONDING_BIT 0b00000001
|
||||
#define MITM_BIT 0b00000100
|
||||
#define SC_BIT 0b00001000
|
||||
#define KEYPRESS_BIT 0b00010000
|
||||
#define CT2_BIT 0b00100000
|
||||
|
||||
|
||||
AuthReq::AuthReq(){}
|
||||
AuthReq::AuthReq(uint8_t octet):_octet(octet){}
|
||||
bool AuthReq::Bonding(){ return (_octet & BONDING_BIT)>0;}
|
||||
bool AuthReq::MITM(){ return (_octet & MITM_BIT)>0;}
|
||||
bool AuthReq::SC(){ return (_octet & SC_BIT)>0;}
|
||||
bool AuthReq::KeyPress(){ return (_octet & KEYPRESS_BIT)>0;}
|
||||
bool AuthReq::CT2(){ return (_octet & CT2_BIT)>0;}
|
||||
|
||||
|
||||
void AuthReq::setBonding(bool state) { _octet= state? _octet|BONDING_BIT : _octet&~BONDING_BIT;}
|
||||
void AuthReq::setMITM(bool state) { _octet= state? _octet|MITM_BIT : _octet&~MITM_BIT;}
|
||||
void AuthReq::setSC(bool state){ _octet= state? _octet|SC_BIT : _octet&~SC_BIT;}
|
||||
void AuthReq::setKeyPress(bool state){ _octet= state? _octet|KEYPRESS_BIT : _octet&~KEYPRESS_BIT;}
|
||||
void AuthReq::setCT2(bool state){ _octet= state? _octet|CT2_BIT : _octet&~CT2_BIT;}
|
||||
|
||||
uint8_t _octet;
|
||||
|
||||
|
||||
void AuthReq::setOctet( uint8_t octet){_octet = octet;}
|
||||
uint8_t AuthReq::getOctet() {return _octet;}
|
41
lib/ArduinoBLE/src/utility/bitDescriptions.h
Normal file
41
lib/ArduinoBLE/src/utility/bitDescriptions.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _BIT_DESCRIPTIONS_H_
|
||||
#define _BIT_DESCRIPTIONS_H_
|
||||
#include <Arduino.h>
|
||||
|
||||
class AuthReq{
|
||||
public:
|
||||
AuthReq();
|
||||
AuthReq(uint8_t octet);
|
||||
void setOctet( uint8_t octet);
|
||||
uint8_t getOctet();
|
||||
|
||||
|
||||
// The Bonding_Flags field is a 2-bit field that indicates the type of bonding being requested by the initiating device
|
||||
bool Bonding();
|
||||
// The MITM field is a 1-bit flag that is set to one if the device is requesting MITM protection
|
||||
bool MITM();
|
||||
// The SC field is a 1 bit flag. If LE Secure Connections pairing is supported by the device, then the SC field shall be set to 1, otherwise it shall be set to 0.
|
||||
bool SC();
|
||||
// The keypress field is a 1-bit flag that is used only in the Passkey Entry protocol and shall be ignored in other protocols.
|
||||
bool KeyPress();
|
||||
// The CT2 field is a 1-bit flag that shall be set to 1 upon transmission to indicate support for the h7 function.
|
||||
bool CT2();
|
||||
|
||||
void setBonding(bool state);
|
||||
void setMITM(bool state);
|
||||
void setSC(bool state);
|
||||
void setKeyPress(bool state);
|
||||
void setCT2(bool state);
|
||||
private:
|
||||
uint8_t _octet;
|
||||
};
|
||||
|
||||
enum IOCap {
|
||||
DisplayOnly,
|
||||
DisplayYesNo,
|
||||
KeyboardOnly,
|
||||
NoInputNoOutput,
|
||||
KeyboardDisplay
|
||||
};
|
||||
|
||||
#endif
|
386
lib/ArduinoBLE/src/utility/btct.cpp
Normal file
386
lib/ArduinoBLE/src/utility/btct.cpp
Normal file
@ -0,0 +1,386 @@
|
||||
#include "btct.h"
|
||||
#include <Arduino.h>
|
||||
#include "HCI.h"
|
||||
#include "ArduinoBLE.h"
|
||||
BluetoothCryptoToolbox::BluetoothCryptoToolbox(){}
|
||||
// In step 1, AES-128 with key K is applied to an all-zero input block.
|
||||
// In step 2, K1 is derived through the following operation:
|
||||
// If the most significant bit of L is equal to 0, K1 is the left-shift
|
||||
// of L by 1 bit.
|
||||
// Otherwise, K1 is the exclusive-OR of const_Rb and the left-shift of L
|
||||
// by 1 bit.
|
||||
// In step 3, K2 is derived through the following operation:
|
||||
// If the most significant bit of K1 is equal to 0, K2 is the left-shift
|
||||
// of K1 by 1 bit.
|
||||
// Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of
|
||||
// K1 by 1 bit.
|
||||
// In step 4, (K1,K2) := Generate_Subkey(K) is returned.
|
||||
unsigned char const_Rb[16] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
|
||||
};
|
||||
|
||||
#define DHKEY_LENGTH 32
|
||||
#define N_LEN 16
|
||||
#define ADDR_LEN 6
|
||||
#define LEN_LTK 16
|
||||
#define LEN_MAC_KEY 16
|
||||
|
||||
void BluetoothCryptoToolbox::printBytes(uint8_t bytes[], uint8_t length){
|
||||
#ifdef _BLE_TRACE_
|
||||
for(int i=0; i<length; i++){
|
||||
if(i>0){
|
||||
Serial.print(", 0x");
|
||||
}else{
|
||||
Serial.print("0x");
|
||||
}
|
||||
Serial.print(bytes[i],HEX);
|
||||
}
|
||||
Serial.print('\n');
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int BluetoothCryptoToolbox::f5(uint8_t DHKey[],uint8_t N_master[], uint8_t N_slave[],
|
||||
uint8_t BD_ADDR_master[], uint8_t BD_ADDR_slave[], uint8_t MacKey[], uint8_t LTK[])
|
||||
{
|
||||
uint8_t SALT[16] = {0x6C, 0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
|
||||
uint8_t keyID[4] = {0x62, 0x74, 0x6c, 0x65};
|
||||
uint8_t length[2];
|
||||
length[0] = 0x01;
|
||||
length[1] = 0x00;
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("Starting f5 calculation");
|
||||
Serial.print("Using DHKey: ");
|
||||
printBytes(DHKey, DHKEY_LENGTH);
|
||||
Serial.print("Using N_Master: ");
|
||||
printBytes(N_master, N_LEN);
|
||||
Serial.print("Using N_Slave: ");
|
||||
printBytes(N_slave, N_LEN);
|
||||
|
||||
Serial.println("Using BD_ADDR_MASTER: ");
|
||||
printBytes(BD_ADDR_master, ADDR_LEN);
|
||||
Serial.println("Using BD_ADDR_SLAVE: ");
|
||||
printBytes(BD_ADDR_slave, ADDR_LEN);
|
||||
#endif
|
||||
|
||||
uint8_t T[16];
|
||||
|
||||
struct __attribute__ ((packed)) CmacInput
|
||||
{
|
||||
uint8_t counter;
|
||||
uint8_t keyID[4];
|
||||
uint8_t N1[16];
|
||||
uint8_t N2[16];
|
||||
uint8_t A1[7];
|
||||
uint8_t A2[7];
|
||||
uint8_t length[2];
|
||||
} cmacInput = {0,{0},{0},{0},{0},{0},{0}};
|
||||
cmacInput.counter = 0;
|
||||
memcpy(cmacInput.keyID, keyID, 4);
|
||||
memcpy(cmacInput.N1,N_master,16);
|
||||
memcpy(cmacInput.N2,N_slave,16);
|
||||
memcpy(cmacInput.A1,BD_ADDR_master,7);
|
||||
memcpy(cmacInput.A2,BD_ADDR_slave,7);
|
||||
memcpy(cmacInput.length,length,2);
|
||||
AES_CMAC(SALT, DHKey, 32, T);
|
||||
|
||||
AES_CMAC(T, (uint8_t*)&cmacInput,sizeof(cmacInput), MacKey);
|
||||
cmacInput.counter=1;
|
||||
AES_CMAC(T, (uint8_t*)&cmacInput, sizeof(cmacInput), LTK);
|
||||
|
||||
return 1;
|
||||
}
|
||||
int BluetoothCryptoToolbox::f6(uint8_t W[], uint8_t N1[],uint8_t N2[],uint8_t R[], uint8_t IOCap[], uint8_t A1[], uint8_t A2[], uint8_t Ex[])
|
||||
{
|
||||
struct __attribute__ ((packed)) F6Input
|
||||
{
|
||||
uint8_t N1[16];
|
||||
uint8_t N2[16];
|
||||
uint8_t R[16];
|
||||
uint8_t IOCap[3];
|
||||
uint8_t A1[7];
|
||||
uint8_t A2[7];
|
||||
} f6Input = {{0},{0},{0},{0},{0},{0}};
|
||||
|
||||
memcpy(f6Input.N1, N1, 16);
|
||||
memcpy(f6Input.N2, N2, 16);
|
||||
memcpy(f6Input.R, R, 16);
|
||||
memcpy(f6Input.IOCap, IOCap, 3);
|
||||
memcpy(f6Input.A1, A1, 7);
|
||||
memcpy(f6Input.A2, A2, 7);
|
||||
|
||||
|
||||
AES_CMAC(W, (uint8_t*)&f6Input, sizeof(f6Input),Ex);
|
||||
return 1;
|
||||
}
|
||||
// AES_CMAC from RFC
|
||||
int BluetoothCryptoToolbox::ah(uint8_t k[16], uint8_t r[3], uint8_t* result)
|
||||
{
|
||||
uint8_t r_[16];
|
||||
int i=0;
|
||||
for(i=0; i<16; i++) r_[i] = 0;
|
||||
for(i=0; i<3; i++) r_[i+13] = r[i];
|
||||
uint8_t intermediate[16];
|
||||
AES_128(k,r_,intermediate);
|
||||
for(i=0; i<3; i++){
|
||||
result[i] = intermediate[i+13];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
void BluetoothCryptoToolbox::testAh()
|
||||
{
|
||||
uint8_t irk[16] = {0xec,0x02,0x34,0xa3,0x57,0xc8,0xad,0x05,0x34,0x10,0x10,0xa6,0x0a,0x39,0x7d,0x9b};
|
||||
uint8_t expected_final[3] = {0x0d,0xfb,0xaa};
|
||||
uint8_t ourResult[3];
|
||||
ah(irk, expected_final, ourResult);
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("Expected : ");
|
||||
printBytes(&expected_final[3], 3);
|
||||
Serial.print("Actual : ");
|
||||
printBytes(ourResult, 3);
|
||||
#endif
|
||||
}
|
||||
|
||||
int BluetoothCryptoToolbox::g2(uint8_t U[], uint8_t V[], uint8_t X[], uint8_t Y[], uint8_t out[4])
|
||||
{
|
||||
struct __attribute__ ((packed)) CmacInput {
|
||||
uint8_t U[32];
|
||||
uint8_t V[32];
|
||||
uint8_t Y[16];
|
||||
} cmacInput= {{0},{0},{0}};
|
||||
memcpy(cmacInput.U,U,32);
|
||||
memcpy(cmacInput.V,V,32);
|
||||
memcpy(cmacInput.Y,Y,16);
|
||||
uint8_t intermediate[16];
|
||||
AES_CMAC(X,(uint8_t*)&cmacInput,sizeof(CmacInput),intermediate);
|
||||
memcpy(out,&intermediate[12],4);
|
||||
return 1;
|
||||
}
|
||||
void BluetoothCryptoToolbox::testg2(){
|
||||
uint8_t U[32] = {0x20,0xb0,0x03,0xd2,0xf2,0x97,0xbe,0x2c,0x5e,0x2c,0x83,0xa7,0xe9,0xf9,0xa5,0xb9,0xef,0xf4,0x91,0x11,0xac,0xf4,0xfd,0xdb,0xcc,0x03,0x01,0x48,0x0e,0x35,0x9d,0xe6};
|
||||
uint8_t V[32] = {0x55,0x18,0x8b,0x3d,0x32,0xf6,0xbb,0x9a,0x90,0x0a,0xfc,0xfb,0xee,0xd4,0xe7,0x2a,0x59,0xcb,0x9a,0xc2,0xf1,0x9d,0x7c,0xfb,0x6b,0x4f,0xdd,0x49,0xf4,0x7f,0xc5,0xfd};
|
||||
uint8_t X[16] = {0xd5,0xcb,0x84,0x54,0xd1,0x77,0x73,0x3e,0xff,0xff,0xb2,0xec,0x71,0x2b,0xae,0xab};
|
||||
uint8_t Y[16] = {0xa6,0xe8,0xe7,0xcc,0x25,0xa7,0x5f,0x6e,0x21,0x65,0x83,0xf7,0xff,0x3d,0xc4,0xcf};
|
||||
uint8_t out[4];
|
||||
|
||||
uint32_t expected = 0;
|
||||
g2(U,V,X,Y,out);
|
||||
uint32_t result = 0;
|
||||
for(int i=0; i<4; i++) result += out[i] << 8*i;
|
||||
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("Expected : ");
|
||||
Serial.println(expected);
|
||||
Serial.print("Result : ");
|
||||
Serial.println(result);
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BluetoothCryptoToolbox::AES_CMAC ( unsigned char *key, unsigned char *input, int length,
|
||||
unsigned char *mac )
|
||||
{
|
||||
unsigned char X[16],Y[16], M_last[16], padded[16];
|
||||
unsigned char K1[16], K2[16];
|
||||
int n, i, flag;
|
||||
generateSubkey(key,K1,K2);
|
||||
|
||||
n = (length+15) / 16; /* n is number of rounds */
|
||||
|
||||
if ( n == 0 ) {
|
||||
n = 1;
|
||||
flag = 0;
|
||||
} else {
|
||||
if ( (length%16) == 0 ) { /* last block is a complete block */
|
||||
flag = 1;
|
||||
} else { /* last block is not complete block */
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flag ) { /* last block is complete block */
|
||||
xor_128(&input[16*(n-1)],K1,M_last);
|
||||
} else {
|
||||
padding(&input[16*(n-1)],padded,length%16);
|
||||
xor_128(padded,K2,M_last);
|
||||
}
|
||||
|
||||
for ( i=0; i<16; i++ ) X[i] = 0;
|
||||
for ( i=0; i<n-1; i++ ) {
|
||||
xor_128(X,&input[16*i],Y); /* Y := Mi (+) X */
|
||||
AES_128(key,Y,X); /* X := AES-128(KEY, Y); */
|
||||
}
|
||||
|
||||
xor_128(X,M_last,Y);
|
||||
AES_128(key,Y,X);
|
||||
|
||||
for ( i=0; i<16; i++ ) {
|
||||
mac[i] = X[i];
|
||||
}
|
||||
}
|
||||
// Paddinng function from RFC
|
||||
void BluetoothCryptoToolbox::padding( unsigned char *lastb, unsigned char *pad, int length )
|
||||
{
|
||||
int j;
|
||||
/* original last block */
|
||||
for ( j=0; j<16; j++ ) {
|
||||
if ( j < length ) {
|
||||
pad[j] = lastb[j];
|
||||
} else if ( j == length ) {
|
||||
pad[j] = 0x80;
|
||||
} else {
|
||||
pad[j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate subkey from RFC
|
||||
void BluetoothCryptoToolbox::generateSubkey(uint8_t* key, uint8_t* K1, uint8_t* K2){
|
||||
unsigned char L[16];
|
||||
unsigned char Z[16];
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
|
||||
for ( i=0; i<16; i++ ) Z[i] = 0;
|
||||
|
||||
AES_128(key,Z,L);
|
||||
|
||||
if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */
|
||||
leftshift_onebit(L,K1);
|
||||
} else { /* Else K1 = ( L << 1 ) (+) Rb */
|
||||
|
||||
leftshift_onebit(L,tmp);
|
||||
xor_128(tmp,const_Rb,K1);
|
||||
}
|
||||
|
||||
if ( (K1[0] & 0x80) == 0 ) {
|
||||
leftshift_onebit(K1,K2);
|
||||
} else {
|
||||
leftshift_onebit(K1,tmp);
|
||||
xor_128(tmp,const_Rb,K2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Use BLE AES function - restart bluetooth if crash
|
||||
int BluetoothCryptoToolbox::AES_128(uint8_t* key, uint8_t* data_in, uint8_t* data_out){
|
||||
uint8_t status = 0;
|
||||
int n = 0;
|
||||
int tries = 30;
|
||||
while(HCI.leEncrypt(key,data_in, &status, data_out)!=1&&n<tries){
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.print("AES failed... retrying: ");
|
||||
Serial.println(n);
|
||||
#endif
|
||||
BLE.end();
|
||||
delay(200);
|
||||
BLE.begin();
|
||||
n++;
|
||||
delay(100*n);
|
||||
}
|
||||
if(n==tries){
|
||||
#ifdef _BLE_TRACE_
|
||||
Serial.println("something went wrong with AES.");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// Tests AES CMAC
|
||||
#ifdef _BLE_TRACE_
|
||||
void BluetoothCryptoToolbox::test(){
|
||||
unsigned char L[16];
|
||||
unsigned char Z[16];
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
|
||||
for ( i=0; i<16; i++ ) Z[i] = 0x00;
|
||||
uint8_t k[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
|
||||
|
||||
Serial.println("AES Plaintext:");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(Z[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
uint8_t expected_aes[16] = {0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3, 0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f};
|
||||
|
||||
AES_128(k, Z, L);
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(L[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(expected_aes[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
|
||||
uint8_t k1[16];
|
||||
uint8_t k2[16];
|
||||
generateSubkey(k,k1,k2);
|
||||
uint8_t expected_k1[16] = {0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde};
|
||||
uint8_t expected_k2[16] = {0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b};
|
||||
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(k2[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(expected_k2[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(k1[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(expected_k1[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
|
||||
uint8_t m[40] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11};
|
||||
uint8_t mac[16];
|
||||
uint8_t expected_mac[16] = {0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27};
|
||||
AES_CMAC(k,m,40,mac);
|
||||
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(mac[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
for(int i=0; i<16; i++){
|
||||
Serial.print(" 0x");
|
||||
Serial.print(expected_mac[i],HEX);
|
||||
}
|
||||
Serial.println(".");
|
||||
}
|
||||
#endif //_BLE_TRACE_
|
||||
// From RFC
|
||||
void BluetoothCryptoToolbox::leftshift_onebit(unsigned char *input,unsigned char *output)
|
||||
{
|
||||
int i;
|
||||
unsigned char overflow = 0;
|
||||
|
||||
for ( i=15; i>=0; i-- ) {
|
||||
output[i] = input[i] << 1;
|
||||
output[i] |= overflow;
|
||||
overflow = (input[i] & 0x80)?1:0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// From RFC
|
||||
void BluetoothCryptoToolbox::xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<16; i++)
|
||||
{
|
||||
out[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
BluetoothCryptoToolbox btct;
|
30
lib/ArduinoBLE/src/utility/btct.h
Normal file
30
lib/ArduinoBLE/src/utility/btct.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef _BTCT_H_
|
||||
#define _BTCT_H_
|
||||
#include <Arduino.h>
|
||||
|
||||
// Implementation of functions defined in BTLE standard
|
||||
class BluetoothCryptoToolbox{
|
||||
public:
|
||||
BluetoothCryptoToolbox();
|
||||
void printBytes(uint8_t bytes[], uint8_t length);
|
||||
void generateSubkey(uint8_t* K, uint8_t* K1, uint8_t* K2);
|
||||
void AES_CMAC ( unsigned char *key, unsigned char *input, int length,
|
||||
unsigned char *mac );
|
||||
int f5(uint8_t DHKey[],uint8_t N_master[], uint8_t N_slave[],
|
||||
uint8_t BD_ADDR_master[], uint8_t BD_ADDR_slave[], uint8_t MacKey[], uint8_t LTK[]);
|
||||
int f6(uint8_t W[], uint8_t N1[],uint8_t N2[],uint8_t R[], uint8_t IOCap[], uint8_t A1[], uint8_t A2[], uint8_t Ex[]);
|
||||
int g2(uint8_t U[], uint8_t V[], uint8_t X[], uint8_t Y[], uint8_t out[4]);
|
||||
int ah(uint8_t k[16], uint8_t r[3], uint8_t result[3]);
|
||||
void test();
|
||||
void testF5();
|
||||
void testF6();
|
||||
void testAh();
|
||||
void testg2();
|
||||
private:
|
||||
int AES_128(uint8_t key[], uint8_t data_in[], uint8_t data_out[]);
|
||||
void leftshift_onebit(unsigned char *input,unsigned char *output);
|
||||
void xor_128(unsigned char *a, unsigned char *b, unsigned char *out);
|
||||
void padding ( unsigned char *lastb, unsigned char *pad, int length );
|
||||
};
|
||||
extern BluetoothCryptoToolbox btct;
|
||||
#endif
|
24
lib/ArduinoBLE/src/utility/keyDistribution.cpp
Normal file
24
lib/ArduinoBLE/src/utility/keyDistribution.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "keyDistribution.h"
|
||||
|
||||
KeyDistribution::KeyDistribution():_octet(0){}
|
||||
KeyDistribution::KeyDistribution(uint8_t octet):_octet(octet){}
|
||||
|
||||
#define ENCKEY 0b00000001
|
||||
#define IDKEY 0b00000010
|
||||
#define SIGNKEY 0b00000100
|
||||
#define LINKKEY 0b00001000
|
||||
void KeyDistribution::setOctet( uint8_t octet){_octet = octet;}
|
||||
uint8_t KeyDistribution::getOctet() {return _octet;}
|
||||
// Ignored when SMP is on LE transport
|
||||
bool KeyDistribution::EncKey(){ return (_octet & ENCKEY)>0;}
|
||||
// Device shall distribute IRK using Identity information command followed by its address using Identity address information
|
||||
bool KeyDistribution::IdKey(){ return (_octet & IDKEY)>0;}
|
||||
// Device shall distribute CSRK using signing information command
|
||||
bool KeyDistribution::SignKey(){ return (_octet & SIGNKEY)>0;}
|
||||
// Device would like to derive BR/EDR from LTK
|
||||
bool KeyDistribution::LinkKey(){ return (_octet & LINKKEY)>0;}
|
||||
|
||||
void KeyDistribution::setEncKey(bool state) { _octet= state? _octet|ENCKEY : _octet&~ENCKEY;}
|
||||
void KeyDistribution::setIdKey(bool state) { _octet= state? _octet|IDKEY : _octet&~IDKEY;}
|
||||
void KeyDistribution::setSignKey(bool state){ _octet= state? _octet|SIGNKEY : _octet&~SIGNKEY;}
|
||||
void KeyDistribution::setLinkKey(bool state){ _octet= state? _octet|LINKKEY : _octet&~LINKKEY;}
|
29
lib/ArduinoBLE/src/utility/keyDistribution.h
Normal file
29
lib/ArduinoBLE/src/utility/keyDistribution.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef _KEY_DISTRIBUTION_H_
|
||||
#define _KEY_DISTRIBUTION_H_
|
||||
#include <Arduino.h>
|
||||
|
||||
class KeyDistribution{
|
||||
public:
|
||||
KeyDistribution();
|
||||
KeyDistribution(uint8_t octet);
|
||||
void setOctet( uint8_t octet);
|
||||
uint8_t getOctet();
|
||||
// Ignored when SMP is on LE transport
|
||||
bool EncKey();
|
||||
// Device shall distribute IRK using Identity information command followed by its address using Identity address information
|
||||
bool IdKey();
|
||||
// Device shall distribute CSRK using signing information command
|
||||
bool SignKey();
|
||||
// Device would like to derive BR/EDR from LTK
|
||||
bool LinkKey();
|
||||
|
||||
void setEncKey(bool state);
|
||||
void setIdKey(bool state);
|
||||
void setSignKey(bool state);
|
||||
void setLinkKey(bool state);
|
||||
private:
|
||||
uint8_t _octet;
|
||||
// 1. IRK by the slave2. BD ADDR by the slave3. CSRK by the slave4. IRK by the master5. BD_ADDR by the master6. CSRK by the master
|
||||
};
|
||||
|
||||
#endif
|
@ -44,7 +44,7 @@ lib_deps =
|
||||
; ^1.2.3 means that any 1.x.x version is accpeted.
|
||||
; ~1.2.3 means that any 1.2.x version is accepted.
|
||||
; "@ ~" Accept only backwards compatible bug fixes
|
||||
arduino-libraries/ArduinoBLE @ ^1.4.1
|
||||
; arduino-libraries/ArduinoBLE @ ^1.4.1
|
||||
|
||||
; common - needed SOMETIMES:
|
||||
FS
|
||||
|
252
src/main.cpp
252
src/main.cpp
@ -1,28 +1,98 @@
|
||||
/*
|
||||
https://www.electronicssimplified.in/esp32/esp32-ble-server-and-client-with-arduino-a-complete-guide/
|
||||
https://www.programmingelectronics.com/esp32-ble-client/
|
||||
// https://github.com/ra6070/BLE-TPMS
|
||||
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoBLE.h>
|
||||
// #include <BLEDevice.h>
|
||||
// #include <BLEServer.h>
|
||||
// #include <BLEUtils.h>
|
||||
// #include <BLE2902.h>
|
||||
|
||||
#define bleServerName "garage_000001_accu_0"
|
||||
// #define SERVICE_UUID "0000fbb0-ABCD-1000-8000-00805f9b34fb"
|
||||
#define uS_TO_S_FACTOR 1000000ULL // auxuliary
|
||||
// #define DEBUG
|
||||
|
||||
#define BLE_SERVER_NAME "garage_000001_accu_0"
|
||||
#define MY_BLE_SERVICE "2728" // volts
|
||||
|
||||
#define uS_TO_S_FACTOR 1000000ULL // auxuliary
|
||||
|
||||
|
||||
BLEService myService(MY_BLE_SERVICE);
|
||||
// Advertising parameters should have a global scope. Do NOT define them in 'setup' or in 'loop'
|
||||
uint8_t manufactData[18] = {};
|
||||
|
||||
// 4-byte array to store the converted result.
|
||||
uint8_t byte_array[4];
|
||||
// number to send
|
||||
long long number;
|
||||
|
||||
RTC_DATA_ATTR int boot;
|
||||
|
||||
void int32_to_bytes(int32_t n, uint8_t *bytes)
|
||||
{
|
||||
// The bitwise right shift (>>) moves the bits of 'n' to the right.
|
||||
// The bitwise AND (&) with 0xFF (which is 00000000 00000000 00000000 11111111 in binary)
|
||||
// isolates the lowest 8 bits, which represent one byte.
|
||||
|
||||
// Extract the most significant byte (MSB)
|
||||
bytes[0] = (n >> 24) & 0xFF;
|
||||
|
||||
// Extract the next byte
|
||||
bytes[1] = (n >> 16) & 0xFF;
|
||||
|
||||
// Extract the third byte
|
||||
bytes[2] = (n >> 8) & 0xFF;
|
||||
|
||||
// Extract the least significant byte (LSB)
|
||||
bytes[3] = n & 0xFF;
|
||||
|
||||
|
||||
// /*
|
||||
// Print the result to the Serial Monitor.
|
||||
#ifdef DEBUG
|
||||
Serial.printf("[%s]: The 32-bit integer [%d] converts to the following bytes:\n",__func__,n);
|
||||
|
||||
Serial.print("Byte 1: ");
|
||||
Serial.print(bytes[0]);
|
||||
Serial.print(" (0x");
|
||||
if (bytes[0] < 16) {
|
||||
Serial.print("0"); // Add leading zero for hex values < 0x10
|
||||
}
|
||||
Serial.print(bytes[0], HEX);
|
||||
Serial.println(")");
|
||||
|
||||
Serial.print("Byte 2: ");
|
||||
Serial.print(bytes[1]);
|
||||
Serial.print(" (0x");
|
||||
if (bytes[1] < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(bytes[1], HEX);
|
||||
Serial.println(")");
|
||||
|
||||
Serial.print("Byte 3: ");
|
||||
Serial.print(bytes[2]);
|
||||
Serial.print(" (0x");
|
||||
if (bytes[2] < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(bytes[2], HEX);
|
||||
Serial.println(")");
|
||||
|
||||
Serial.print("Byte 4: ");
|
||||
Serial.print(bytes[3]);
|
||||
Serial.print(" (0x");
|
||||
if (bytes[3] < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(bytes[3], HEX);
|
||||
Serial.println(")");
|
||||
|
||||
Serial.println("--------------------");
|
||||
#endif
|
||||
// */
|
||||
|
||||
}
|
||||
|
||||
|
||||
void do_esp_go_to_sleep()
|
||||
{
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
|
||||
void hibernate(int final_sleeping_time_s)
|
||||
{
|
||||
esp_deep_sleep_disable_rom_logging();
|
||||
@ -37,90 +107,116 @@ void hibernate(int final_sleeping_time_s)
|
||||
do_esp_go_to_sleep();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(5000);
|
||||
Serial.begin(115200);
|
||||
Serial.println("started");
|
||||
|
||||
boot++;
|
||||
pinMode(8, OUTPUT);
|
||||
digitalWrite(8, LOW);
|
||||
|
||||
// // Create the BLE Device
|
||||
// BLEDevice::init(bleServerName);
|
||||
// // Create the BLE Server
|
||||
// BLEServer *pServer = BLEDevice::createServer();
|
||||
// // Create the BLE Service
|
||||
// BLEService *BLEService = pServer->createService(SERVICE_UUID);
|
||||
// // Start the service
|
||||
// BLEService->start();
|
||||
#ifdef DEBUG
|
||||
delay(5000);
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println("\nSTARTED\n");
|
||||
#endif
|
||||
|
||||
// 000180EACA108A78E36D0000E60A00005B00
|
||||
//1
|
||||
// number = boot;
|
||||
number = 12345;
|
||||
number = random(-11000,15000);
|
||||
// number = random(INT_MIN,INT_MAX);
|
||||
if ((number <= INT_MAX) and (number >= INT_MIN))
|
||||
{
|
||||
int32_to_bytes(number, byte_array);
|
||||
manufactData[0] = byte_array[3];
|
||||
manufactData[1] = byte_array[2];
|
||||
manufactData[2] = byte_array[1];
|
||||
manufactData[3] = byte_array[0];
|
||||
}
|
||||
|
||||
// data x1: 5 digits or 4 and minus: -9999...99999 - milivolts
|
||||
// int x1 = random(9000,15000);
|
||||
// u_int32_t x1 = 35588;//random(-9999,99999);
|
||||
u_int32_t x1 = 12345;
|
||||
char x1char[6];
|
||||
snprintf(x1char,sizeof(x1char),"%5d",x1);
|
||||
|
||||
// data x2: 3 numbers or 2 and minus -99...999
|
||||
// int x2 = random(-99,999);
|
||||
int x2 = 123;
|
||||
char x2char[4];
|
||||
snprintf(x2char,sizeof(x2char),"%3d",x2);
|
||||
|
||||
// data x3: 4 numbers or 3 and minus -999...9999
|
||||
// int x3 = random(-999,9999);
|
||||
int x3 = 1234;
|
||||
char x3char[5];
|
||||
snprintf(x3char,sizeof(x3char),"%4d",x3);
|
||||
|
||||
// data x4: 4 numbers or 3 and minus -999...9999
|
||||
// int x4 = random(-999,9999);
|
||||
int x4 = 1234;
|
||||
// int x4 = boot;
|
||||
|
||||
char x4char[5];
|
||||
snprintf(x4char,sizeof(x4char),"%4d",x4);
|
||||
|
||||
char ms[37];
|
||||
snprintf(ms,sizeof(ms),"%-9s%-9s%-9s%-9s",x1char,x2char,x3char,x4char);
|
||||
|
||||
Serial.printf("ms=%s\n",ms);
|
||||
//2
|
||||
// number = -4294967290;
|
||||
number = random(INT_MIN+1,INT_MAX-1);
|
||||
if ((number <= INT_MAX) and (number >= INT_MIN))
|
||||
{
|
||||
int32_to_bytes(number, byte_array);
|
||||
manufactData[4] = byte_array[3];
|
||||
manufactData[5] = byte_array[2];
|
||||
manufactData[6] = byte_array[1];
|
||||
manufactData[7] = byte_array[0];
|
||||
}
|
||||
|
||||
// // Start advertising
|
||||
// BLEAdvertising *pAdvertising2 = BLEDevice::getAdvertising();
|
||||
// BLEAdvertisementData manufacturerdata = BLEAdvertisementData();
|
||||
// manufacturerdata.setManufacturerData(ms);
|
||||
|
||||
// pAdvertising2->setAdvertisementData(manufacturerdata);
|
||||
//3
|
||||
number = random(INT_MIN+1,0);
|
||||
if ((number <= INT_MAX) and (number >= INT_MIN))
|
||||
{
|
||||
int32_to_bytes(number, byte_array);
|
||||
manufactData[8] = byte_array[3];
|
||||
manufactData[9] = byte_array[2];
|
||||
manufactData[10] = byte_array[1];
|
||||
manufactData[11] = byte_array[0];
|
||||
}
|
||||
|
||||
// pServer->getAdvertising()->start();
|
||||
//4
|
||||
number = random(0,INT_MAX-1);
|
||||
if ((number <= INT_MAX) and (number >= INT_MIN))
|
||||
{
|
||||
int32_to_bytes(number, byte_array);
|
||||
manufactData[12] = byte_array[3];
|
||||
manufactData[13] = byte_array[2];
|
||||
manufactData[14] = byte_array[1];
|
||||
manufactData[15] = byte_array[0];
|
||||
}
|
||||
|
||||
long sm2 = millis(); while(millis() < sm2 + 500) {};
|
||||
// BLEDevice::getAdvertising()->stop();
|
||||
//5b - byte, only positive
|
||||
number = random(124,CHAR_MAX);
|
||||
if ((number <= CHAR_MAX) and (number > CHAR_MIN))
|
||||
{
|
||||
manufactData[16] = number;
|
||||
}
|
||||
|
||||
//6b - byte, only positive
|
||||
number = random(CHAR_MIN,CHAR_MAX);
|
||||
if ((number <= CHAR_MAX) and (number > CHAR_MIN))
|
||||
{
|
||||
manufactData[17] = number;
|
||||
}
|
||||
|
||||
|
||||
if (!BLE.begin())
|
||||
{
|
||||
Serial.println("BLE Failed.");
|
||||
return;
|
||||
} else
|
||||
{
|
||||
Serial.println("BLE OK.");
|
||||
#ifdef DEBUG
|
||||
Serial.println("failed to initialize BLE!");
|
||||
#endif
|
||||
hibernate(random(2,7));
|
||||
}
|
||||
BLE.setLocalName(bleServerName);
|
||||
byte data[3] = { 0xA3, 0x09, 0x64};
|
||||
BLE.setManufacturerData(data, 3);
|
||||
|
||||
BLE.addService(myService);
|
||||
// Build scan response data packet
|
||||
BLEAdvertisingData scanData;
|
||||
// Set parameters for scan response packet
|
||||
scanData.setLocalName(BLE_SERVER_NAME);
|
||||
// Copy set parameters in the actual scan response packet
|
||||
BLE.setScanResponseData(scanData);
|
||||
// Build advertising data packet
|
||||
BLEAdvertisingData advData;
|
||||
// Set parameters for advertising packet
|
||||
advData.setManufacturerData(manufactData, sizeof(manufactData));
|
||||
advData.setAdvertisedService(myService);
|
||||
// Copy set parameters in the actual advertising packet
|
||||
BLE.setAdvertisingData(advData);
|
||||
|
||||
BLE.advertise();
|
||||
#ifdef DEBUG
|
||||
Serial.println("advertising ...");
|
||||
#endif
|
||||
long sm2 = millis(); while(millis() < sm2 + 100) {};
|
||||
|
||||
digitalWrite(8, HIGH);
|
||||
// hibernate(random(2,7));
|
||||
hibernate(2);
|
||||
// hibernate(random(23,37));
|
||||
hibernate(3);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
void loop() {}
|
||||
|
Loading…
Reference in New Issue
Block a user