Merge tag '6.0.0' into thunderpack1.2
This commit is contained in:
commit
5f0a372a22
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# Per default everything gets normalized and gets LF line endings on checkout.
|
# Per default everything gets normalized and gets LF line endings on checkout.
|
||||||
* text eol=lf
|
* text eol=lf
|
||||||
|
|
||||||
|
229
.github/workflows/build.yml
vendored
229
.github/workflows/build.yml
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
name: Build CI
|
name: Build CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -10,22 +14,21 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-18.04
|
||||||
steps:
|
steps:
|
||||||
- name: Dump GitHub context
|
- name: Dump GitHub context
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2.2.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
- run: git submodule sync
|
|
||||||
- run: git submodule foreach git remote -v
|
|
||||||
- run: git submodule foreach git fetch --recurse-submodules=no origin +refs/tags/*:refs/tags/*
|
|
||||||
- name: CircuitPython version
|
- name: CircuitPython version
|
||||||
run: git describe --dirty --tags
|
run: |
|
||||||
|
git describe --dirty --tags
|
||||||
|
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
@ -33,8 +36,8 @@ jobs:
|
|||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y eatmydata
|
sudo apt-get install -y eatmydata
|
||||||
sudo eatmydata apt-get install -y gettext librsvg2-bin mingw-w64
|
sudo eatmydata apt-get install -y gettext librsvg2-bin mingw-w64 latexmk texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra
|
||||||
pip install requests sh click setuptools cpp-coveralls "Sphinx<4" sphinx-rtd-theme recommonmark sphinxcontrib-svg2pdfconverter polib pyyaml
|
pip install requests sh click setuptools cpp-coveralls "Sphinx<4" sphinx-rtd-theme recommonmark sphinx-autoapi sphinxcontrib-svg2pdfconverter polib pyyaml astroid isort black awscli
|
||||||
- name: Versions
|
- name: Versions
|
||||||
run: |
|
run: |
|
||||||
gcc --version
|
gcc --version
|
||||||
@ -64,69 +67,103 @@ jobs:
|
|||||||
- name: mpy Tests
|
- name: mpy Tests
|
||||||
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float
|
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float
|
||||||
working-directory: tests
|
working-directory: tests
|
||||||
- name: Docs
|
- name: Stubs
|
||||||
run: sphinx-build -E -W -b html . _build/html
|
run: make stubs -j2
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: stubs
|
||||||
|
path: circuitpython-stubs*
|
||||||
|
- name: Test Documentation Build (HTML)
|
||||||
|
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: docs
|
||||||
|
path: _build/html
|
||||||
|
- name: Test Documentation Build (LaTeX/PDF)
|
||||||
|
run: |
|
||||||
|
make latexpdf
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: docs
|
||||||
|
path: _build/latex
|
||||||
- name: Translations
|
- name: Translations
|
||||||
run: make check-translate
|
run: make check-translate
|
||||||
- name: New boards check
|
- name: New boards check
|
||||||
run: python3 -u ci_new_boards_check.py
|
run: python3 -u ci_new_boards_check.py
|
||||||
working-directory: tools
|
working-directory: tools
|
||||||
|
- name: Duplicate USB VID/PID Check
|
||||||
|
run: python3 -u -m tools.ci_check_duplicate_usb_vid_pid
|
||||||
- name: Build mpy-cross.static-raspbian
|
- name: Build mpy-cross.static-raspbian
|
||||||
run: make -C mpy-cross -j2 -f Makefile.static-raspbian
|
run: make -C mpy-cross -j2 -f Makefile.static-raspbian
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross.static-raspbian
|
name: mpy-cross.static-raspbian
|
||||||
path: mpy-cross/mpy-cross.static-raspbian
|
path: mpy-cross/mpy-cross.static-raspbian
|
||||||
|
|
||||||
- name: Build mpy-cross.static
|
- name: Build mpy-cross.static
|
||||||
run: make -C mpy-cross -j2 -f Makefile.static
|
run: make -C mpy-cross -j2 -f Makefile.static
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross.static-amd64-linux
|
name: mpy-cross.static-amd64-linux
|
||||||
path: mpy-cross/mpy-cross.static
|
path: mpy-cross/mpy-cross.static
|
||||||
|
|
||||||
- name: Build mpy-cross.static-mingw
|
- name: Build mpy-cross.static-mingw
|
||||||
run: make -C mpy-cross -j2 -f Makefile.static-mingw
|
run: make -C mpy-cross -j2 -f Makefile.static-mingw
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross.static-x64-windows
|
name: mpy-cross.static-x64-windows
|
||||||
path: mpy-cross/mpy-cross.static.exe
|
path: mpy-cross/mpy-cross.static.exe
|
||||||
|
- name: Upload mpy-cross builds to S3
|
||||||
|
run: |
|
||||||
|
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static-raspbian s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-raspbian-${{ env.CP_VERSION }} --no-progress --region us-east-1
|
||||||
|
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-amd64-linux-${{ env.CP_VERSION }} --no-progress --region us-east-1
|
||||||
|
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static.exe s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-x64-windows-${{ env.CP_VERSION }}.exe --no-progress --region us-east-1
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||||
|
|
||||||
|
|
||||||
mpy-cross-mac:
|
mpy-cross-mac:
|
||||||
runs-on: macos-latest
|
runs-on: macos-10.15
|
||||||
steps:
|
steps:
|
||||||
- name: Dump GitHub context
|
- name: Dump GitHub context
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- name: Install deps
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew link --force gettext
|
brew install gettext
|
||||||
|
echo >>$GITHUB_PATH /usr/local/opt/gettext/bin
|
||||||
- name: Versions
|
- name: Versions
|
||||||
run: |
|
run: |
|
||||||
gcc --version
|
gcc --version
|
||||||
python3 --version
|
python3 --version
|
||||||
msgfmt --version
|
msgfmt --version
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2.2.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
- run: git submodule sync
|
|
||||||
- run: git submodule foreach git remote -v
|
|
||||||
- run: git submodule foreach git fetch --recurse-submodules=no origin +refs/tags/*:refs/tags/*
|
|
||||||
- name: CircuitPython version
|
- name: CircuitPython version
|
||||||
run: git describe --dirty --tags
|
run: |
|
||||||
|
git describe --dirty --tags
|
||||||
|
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
|
||||||
- name: Build mpy-cross
|
- name: Build mpy-cross
|
||||||
run: make -C mpy-cross -j2
|
run: make -C mpy-cross -j2
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross-macos-catalina
|
name: mpy-cross-macos-catalina
|
||||||
path: mpy-cross/mpy-cross
|
path: mpy-cross/mpy-cross
|
||||||
|
- name: Upload mpy-cross build to S3
|
||||||
|
run: |
|
||||||
|
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-catalina-${{ env.CP_VERSION }} --no-progress --region us-east-1
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||||
|
|
||||||
|
|
||||||
build-arm:
|
build-arm:
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-18.04
|
||||||
needs: test
|
needs: test
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@ -134,6 +171,7 @@ jobs:
|
|||||||
board:
|
board:
|
||||||
- "8086_commander"
|
- "8086_commander"
|
||||||
- "TG-Watch02A"
|
- "TG-Watch02A"
|
||||||
|
- "aloriumtech_evo_m51"
|
||||||
- "aramcon_badge_2019"
|
- "aramcon_badge_2019"
|
||||||
- "arduino_mkr1300"
|
- "arduino_mkr1300"
|
||||||
- "arduino_mkrzero"
|
- "arduino_mkrzero"
|
||||||
@ -141,7 +179,10 @@ jobs:
|
|||||||
- "arduino_nano_33_iot"
|
- "arduino_nano_33_iot"
|
||||||
- "arduino_zero"
|
- "arduino_zero"
|
||||||
- "bast_pro_mini_m0"
|
- "bast_pro_mini_m0"
|
||||||
- "bdmicro_vina_m0"
|
- "bdmicro_vina_d21"
|
||||||
|
- "bdmicro_vina_d51"
|
||||||
|
- "bless_dev_board_multi_sensor"
|
||||||
|
- "blm_badge"
|
||||||
- "capablerobot_usbhub"
|
- "capablerobot_usbhub"
|
||||||
- "catwan_usbstick"
|
- "catwan_usbstick"
|
||||||
- "circuitbrains_basic_m0"
|
- "circuitbrains_basic_m0"
|
||||||
@ -157,6 +198,8 @@ jobs:
|
|||||||
- "datum_imu"
|
- "datum_imu"
|
||||||
- "datum_light"
|
- "datum_light"
|
||||||
- "datum_weather"
|
- "datum_weather"
|
||||||
|
- "dynossat_edu_eps"
|
||||||
|
- "dynossat_edu_obc"
|
||||||
- "electronut_labs_blip"
|
- "electronut_labs_blip"
|
||||||
- "electronut_labs_papyr"
|
- "electronut_labs_papyr"
|
||||||
- "escornabot_makech"
|
- "escornabot_makech"
|
||||||
@ -170,6 +213,7 @@ jobs:
|
|||||||
- "feather_m0_rfm69"
|
- "feather_m0_rfm69"
|
||||||
- "feather_m0_rfm9x"
|
- "feather_m0_rfm9x"
|
||||||
- "feather_m0_supersized"
|
- "feather_m0_supersized"
|
||||||
|
- "feather_m4_can"
|
||||||
- "feather_m4_express"
|
- "feather_m4_express"
|
||||||
- "feather_m7_1011"
|
- "feather_m7_1011"
|
||||||
- "feather_mimxrt1011"
|
- "feather_mimxrt1011"
|
||||||
@ -177,10 +221,13 @@ jobs:
|
|||||||
- "feather_nrf52840_express"
|
- "feather_nrf52840_express"
|
||||||
- "feather_radiofruit_zigbee"
|
- "feather_radiofruit_zigbee"
|
||||||
- "feather_stm32f405_express"
|
- "feather_stm32f405_express"
|
||||||
|
- "fluff_m0"
|
||||||
- "gemma_m0"
|
- "gemma_m0"
|
||||||
- "grandcentral_m4_express"
|
- "grandcentral_m4_express"
|
||||||
- "hallowing_m0_express"
|
- "hallowing_m0_express"
|
||||||
- "hallowing_m4_express"
|
- "hallowing_m4_express"
|
||||||
|
- "hiibot_bluefi"
|
||||||
|
- "ikigaisense_vita"
|
||||||
- "imxrt1010_evk"
|
- "imxrt1010_evk"
|
||||||
- "imxrt1020_evk"
|
- "imxrt1020_evk"
|
||||||
- "imxrt1060_evk"
|
- "imxrt1060_evk"
|
||||||
@ -188,45 +235,64 @@ jobs:
|
|||||||
- "itsybitsy_m4_express"
|
- "itsybitsy_m4_express"
|
||||||
- "itsybitsy_nrf52840_express"
|
- "itsybitsy_nrf52840_express"
|
||||||
- "kicksat-sprite"
|
- "kicksat-sprite"
|
||||||
|
- "loc_ber_m4_base_board"
|
||||||
|
- "makerdiary_m60_keyboard"
|
||||||
|
- "makerdiary_nrf52840_m2_devkit"
|
||||||
- "makerdiary_nrf52840_mdk"
|
- "makerdiary_nrf52840_mdk"
|
||||||
- "makerdiary_nrf52840_mdk_usb_dongle"
|
- "makerdiary_nrf52840_mdk_usb_dongle"
|
||||||
|
- "matrixportal_m4"
|
||||||
- "meowbit_v121"
|
- "meowbit_v121"
|
||||||
- "meowmeow"
|
- "meowmeow"
|
||||||
- "metro_m0_express"
|
- "metro_m0_express"
|
||||||
- "metro_m4_airlift_lite"
|
- "metro_m4_airlift_lite"
|
||||||
- "metro_m4_express"
|
- "metro_m4_express"
|
||||||
|
- "metro_m7_1011"
|
||||||
- "metro_nrf52840_express"
|
- "metro_nrf52840_express"
|
||||||
- "mini_sam_m4"
|
- "mini_sam_m4"
|
||||||
- "monster_m4sk"
|
- "monster_m4sk"
|
||||||
- "ndgarage_ndbit6"
|
- "ndgarage_ndbit6"
|
||||||
|
- "ndgarage_ndbit6_v2"
|
||||||
- "nfc_copy_cat"
|
- "nfc_copy_cat"
|
||||||
|
- "nice_nano"
|
||||||
|
- "nucleo_f746zg"
|
||||||
- "nucleo_f767zi"
|
- "nucleo_f767zi"
|
||||||
- "nucleo_h743zi_2"
|
- "nucleo_h743zi_2"
|
||||||
- "ohs2020_badge"
|
- "ohs2020_badge"
|
||||||
- "openbook_m4"
|
- "openbook_m4"
|
||||||
|
- "openmv_h7"
|
||||||
- "particle_argon"
|
- "particle_argon"
|
||||||
- "particle_boron"
|
- "particle_boron"
|
||||||
- "particle_xenon"
|
- "particle_xenon"
|
||||||
- "pca10056"
|
- "pca10056"
|
||||||
- "pca10059"
|
- "pca10059"
|
||||||
|
- "pca10100"
|
||||||
- "pewpew10"
|
- "pewpew10"
|
||||||
- "pewpew_m4"
|
- "pewpew_m4"
|
||||||
|
- "picoplanet"
|
||||||
- "pirkey_m0"
|
- "pirkey_m0"
|
||||||
|
- "pitaya_go"
|
||||||
- "pyb_nano_v2"
|
- "pyb_nano_v2"
|
||||||
- "pybadge"
|
- "pybadge"
|
||||||
- "pybadge_airlift"
|
- "pybadge_airlift"
|
||||||
- "pyboard_v11"
|
- "pyboard_v11"
|
||||||
- "pycubed"
|
- "pycubed"
|
||||||
|
- "pycubed_mram"
|
||||||
- "pygamer"
|
- "pygamer"
|
||||||
- "pygamer_advance"
|
- "pygamer_advance"
|
||||||
- "pyportal"
|
- "pyportal"
|
||||||
- "pyportal_titano"
|
- "pyportal_titano"
|
||||||
- "pyruler"
|
- "pyruler"
|
||||||
|
- "qtpy_m0"
|
||||||
|
- "qtpy_m0_haxpress"
|
||||||
|
- "raytac_mdbt50q-db-40"
|
||||||
- "robohatmm1_m4"
|
- "robohatmm1_m4"
|
||||||
- "sam32"
|
- "sam32"
|
||||||
|
- "same54_xplained"
|
||||||
|
- "seeeduino_wio_terminal"
|
||||||
- "seeeduino_xiao"
|
- "seeeduino_xiao"
|
||||||
- "serpente"
|
- "serpente"
|
||||||
- "shirtty"
|
- "shirtty"
|
||||||
|
- "simmel"
|
||||||
- "snekboard"
|
- "snekboard"
|
||||||
- "sparkfun_lumidrive"
|
- "sparkfun_lumidrive"
|
||||||
- "sparkfun_nrf52840_mini"
|
- "sparkfun_nrf52840_mini"
|
||||||
@ -241,10 +307,13 @@ jobs:
|
|||||||
- "stm32f411ve_discovery"
|
- "stm32f411ve_discovery"
|
||||||
- "stm32f412zg_discovery"
|
- "stm32f412zg_discovery"
|
||||||
- "stm32f4_discovery"
|
- "stm32f4_discovery"
|
||||||
|
- "stm32f746g_discovery"
|
||||||
- "stringcar_m0_express"
|
- "stringcar_m0_express"
|
||||||
- "teensy40"
|
- "teensy40"
|
||||||
|
- "teensy41"
|
||||||
- "teknikio_bluebird"
|
- "teknikio_bluebird"
|
||||||
- "thunderpack"
|
- "thunderpack"
|
||||||
|
- "tinkeringtech_scoutmakes_azul"
|
||||||
- "trellis_m4_express"
|
- "trellis_m4_express"
|
||||||
- "trinket_m0"
|
- "trinket_m0"
|
||||||
- "trinket_m0_haxpress"
|
- "trinket_m0_haxpress"
|
||||||
@ -272,14 +341,11 @@ jobs:
|
|||||||
gcc --version
|
gcc --version
|
||||||
arm-none-eabi-gcc --version
|
arm-none-eabi-gcc --version
|
||||||
python3 --version
|
python3 --version
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2.2.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
- run: git submodule sync
|
|
||||||
- run: git submodule foreach git remote -v
|
|
||||||
- run: git submodule foreach git fetch --recurse-submodules=no origin +refs/tags/*:refs/tags/*
|
|
||||||
- name: mpy-cross
|
- name: mpy-cross
|
||||||
run: make -C mpy-cross -j2
|
run: make -C mpy-cross -j2
|
||||||
- name: build
|
- name: build
|
||||||
@ -287,7 +353,7 @@ jobs:
|
|||||||
working-directory: tools
|
working-directory: tools
|
||||||
env:
|
env:
|
||||||
BOARDS: ${{ matrix.board }}
|
BOARDS: ${{ matrix.board }}
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.board }}
|
name: ${{ matrix.board }}
|
||||||
path: bin/${{ matrix.board }}
|
path: bin/${{ matrix.board }}
|
||||||
@ -299,7 +365,7 @@ jobs:
|
|||||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||||
|
|
||||||
build-riscv:
|
build-riscv:
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-18.04
|
||||||
needs: test
|
needs: test
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@ -323,9 +389,11 @@ jobs:
|
|||||||
gcc --version
|
gcc --version
|
||||||
riscv64-unknown-elf-gcc --version
|
riscv64-unknown-elf-gcc --version
|
||||||
python3 --version
|
python3 --version
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2.2.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
- name: mpy-cross
|
- name: mpy-cross
|
||||||
run: make -C mpy-cross -j2
|
run: make -C mpy-cross -j2
|
||||||
- name: build
|
- name: build
|
||||||
@ -333,7 +401,98 @@ jobs:
|
|||||||
working-directory: tools
|
working-directory: tools
|
||||||
env:
|
env:
|
||||||
BOARDS: ${{ matrix.board }}
|
BOARDS: ${{ matrix.board }}
|
||||||
- uses: actions/upload-artifact@v1.0.0
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.board }}
|
||||||
|
path: bin/${{ matrix.board }}
|
||||||
|
- name: Upload to S3
|
||||||
|
run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1"
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||||
|
build-xtensa:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: test
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
board:
|
||||||
|
- "adafruit_metro_esp32s2"
|
||||||
|
- "electroniccats_bastwifi"
|
||||||
|
- "espressif_kaluga_1"
|
||||||
|
- "espressif_saola_1_wroom"
|
||||||
|
- "espressif_saola_1_wrover"
|
||||||
|
- "microdev_micro_s2"
|
||||||
|
- "muselab_nanoesp32_s2"
|
||||||
|
- "unexpectedmaker_feathers2"
|
||||||
|
- "unexpectedmaker_feathers2_prerelease"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Python 3.8
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
- uses: actions/checkout@v2.2.0
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
|
- name: CircuitPython version
|
||||||
|
run: git describe --dirty --tags
|
||||||
|
- uses: actions/cache@v1
|
||||||
|
name: Fetch IDF tool cache
|
||||||
|
id: idf-cache
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.idf_tools
|
||||||
|
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/esp32s2/esp-idf/HEAD') }}-20200801
|
||||||
|
- name: Clone IDF submodules
|
||||||
|
run: |
|
||||||
|
(cd $IDF_PATH && git submodule update --init)
|
||||||
|
env:
|
||||||
|
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||||
|
- name: Install IDF tools
|
||||||
|
run: |
|
||||||
|
$IDF_PATH/tools/idf_tools.py --non-interactive install required
|
||||||
|
$IDF_PATH/tools/idf_tools.py --non-interactive install cmake
|
||||||
|
$IDF_PATH/tools/idf_tools.py --non-interactive install-python-env
|
||||||
|
rm -rf $IDF_TOOLS_PATH/dist
|
||||||
|
env:
|
||||||
|
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||||
|
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||||
|
- name: Install CircuitPython deps
|
||||||
|
run: |
|
||||||
|
source $IDF_PATH/export.sh
|
||||||
|
pip install requests sh click setuptools awscli
|
||||||
|
sudo apt-get install -y gettext ninja-build
|
||||||
|
env:
|
||||||
|
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||||
|
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||||
|
- name: Versions
|
||||||
|
run: |
|
||||||
|
source $IDF_PATH/export.sh
|
||||||
|
gcc --version
|
||||||
|
xtensa-esp32s2-elf-gcc --version
|
||||||
|
python3 --version
|
||||||
|
ninja --version
|
||||||
|
cmake --version
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||||
|
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||||
|
- name: mpy-cross
|
||||||
|
run: make -C mpy-cross -j2
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
source $IDF_PATH/export.sh
|
||||||
|
python3 -u build_release_files.py
|
||||||
|
working-directory: tools
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||||
|
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||||
|
BOARDS: ${{ matrix.board }}
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.board }}
|
name: ${{ matrix.board }}
|
||||||
path: bin/${{ matrix.board }}
|
path: bin/${{ matrix.board }}
|
||||||
|
7
.github/workflows/create_website_pr.yml
vendored
7
.github/workflows/create_website_pr.yml
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
name: Update CircuitPython.org
|
name: Update CircuitPython.org
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -23,12 +27,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gcc --version
|
gcc --version
|
||||||
python3 --version
|
python3 --version
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2.2.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||||
- run: git submodule foreach git fetch --recurse-submodules=no origin +refs/tags/*:refs/tags/*
|
|
||||||
- name: CircuitPython version
|
- name: CircuitPython version
|
||||||
run: git describe --dirty --tags
|
run: git describe --dirty --tags
|
||||||
- name: Website
|
- name: Website
|
||||||
|
24
.github/workflows/pre-commit.yml
vendored
Normal file
24
.github/workflows/pre-commit.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright (c) 2019 Anthony Sottile
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
name: pre-commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-python@v1
|
||||||
|
- name: set PY
|
||||||
|
run: echo >>$GITHUB_ENV PY="$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')"
|
||||||
|
- uses: actions/cache@v1
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pre-commit
|
||||||
|
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||||
|
- uses: pre-commit/action@v1.1.0
|
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# Compiled Sources
|
# Compiled Sources
|
||||||
###################
|
###################
|
||||||
*.o
|
*.o
|
||||||
@ -14,6 +18,7 @@
|
|||||||
############
|
############
|
||||||
dist/
|
dist/
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
.eggs
|
||||||
|
|
||||||
# Logs and Databases
|
# Logs and Databases
|
||||||
######################
|
######################
|
||||||
@ -51,6 +56,8 @@ _build
|
|||||||
# Generated rst files
|
# Generated rst files
|
||||||
######################
|
######################
|
||||||
genrst/
|
genrst/
|
||||||
|
/autoapi/
|
||||||
|
/shared-bindings/*/**/*.rst
|
||||||
|
|
||||||
# ctags and similar
|
# ctags and similar
|
||||||
###################
|
###################
|
||||||
@ -73,3 +80,9 @@ TAGS
|
|||||||
*.mo
|
*.mo
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Python Virtual Environments
|
||||||
|
####################
|
||||||
|
.venv
|
||||||
|
.env
|
||||||
|
31
.gitmodules
vendored
31
.gitmodules
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
[submodule "lib/axtls"]
|
[submodule "lib/axtls"]
|
||||||
path = lib/axtls
|
path = lib/axtls
|
||||||
url = https://github.com/pfalcon/axtls
|
url = https://github.com/pfalcon/axtls
|
||||||
@ -122,3 +126,30 @@
|
|||||||
[submodule "lib/protomatter"]
|
[submodule "lib/protomatter"]
|
||||||
path = lib/protomatter
|
path = lib/protomatter
|
||||||
url = https://github.com/adafruit/Adafruit_Protomatter
|
url = https://github.com/adafruit/Adafruit_Protomatter
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_LSM6DS"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_LSM6DS
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_LSM6DS
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_FocalTouch"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_FocalTouch
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_FocalTouch
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_DS3231"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_DS3231
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_DS3231
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_DRV2605"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_DRV2605
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_DRV2605
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_BLE"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_BLE
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_BLE
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_BLE_Apple_Notification_Center
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_RFM9x"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_RFM9x
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_RFM9x.git
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_RFM69"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_RFM69
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_RFM69.git
|
||||||
|
[submodule "ports/esp32s2/esp-idf"]
|
||||||
|
path = ports/esp32s2/esp-idf
|
||||||
|
url = https://github.com/espressif/esp-idf.git
|
||||||
|
112
.mailmap
Normal file
112
.mailmap
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
|
Alexander Steffen <devel.20.webmeister@spamgourmet.com>
|
||||||
|
Alexander Steffen <devel.20.webmeister@spamgourmet.com> <Alexander.Steffen@infineon.com>
|
||||||
|
Alexander Steffen <devel.20.webmeister@spamgourmet.com> <webmeister@users.noreply.github.com>
|
||||||
|
Benjamin Vernoux <bvernoux@gmail.com>
|
||||||
|
Brent Rubell <robots199@me.com>
|
||||||
|
Brent Rubell <robots199@me.com> <brent@xn.home>
|
||||||
|
Brent Rubell <robots199@me.com> <brentru@users.noreply.github.com>
|
||||||
|
Carlos <carlos.santiago.diaz@gmail.com>
|
||||||
|
Chris Packham <judge.packham@gmail.com>
|
||||||
|
Chris Packham <judge.packham@gmail.com> <chris.packham@alliedtelesis.co.nz>
|
||||||
|
Damiano Mazzella <damianomazzella@gmail.com>
|
||||||
|
Damien George <damien.p.george@gmail.com>
|
||||||
|
Dan Halbert <halbert@adafruit.com>
|
||||||
|
Dan Halbert <halbert@adafruit.com> <halbert@halwitz.org>
|
||||||
|
Daniel Pollard <daniel@learnweaver.com>
|
||||||
|
Daniel Pollard <daniel@learnweaver.com> <daniel.pollard@learnweaver.com>
|
||||||
|
Daniel Tralamazza <daniel@tralamazza.com>
|
||||||
|
Daniel Tralamazza <daniel@tralamazza.com> <tralamazza@users.noreply.github.com>
|
||||||
|
David Glaude <david.glaude@gmail.com>
|
||||||
|
David Glaude <david.glaude@gmail.com> <dglaude@users.noreply.github.com>
|
||||||
|
George Waters <gwatersdev@gmail.com>
|
||||||
|
George Waters <gwatersdev@gmail.com> <george@georgeh2os.com>
|
||||||
|
Ha Thach <thach@tinyusb.org>
|
||||||
|
Henrik Sölver <henrik.solver@gmail.com>
|
||||||
|
Ilya Dmitrichenko <errordeveloper@gmail.com>
|
||||||
|
Ilya Dmitrichenko <errordeveloper@gmail.com> <ilya@xively.com>
|
||||||
|
Jason Pecor <14111408+jpecor@users.noreply.github.com>
|
||||||
|
Jeff Epler <jepler@gmail.com>
|
||||||
|
Jeff Epler <jepler@gmail.com> <jeff@adafruit.com>
|
||||||
|
Jeff Epler <jepler@gmail.com> <jepler@de11.u>
|
||||||
|
Jeff Epler <jepler@gmail.com> <jepler@unpythonic.net>
|
||||||
|
Jerry Needell <jerryneedell@gmail.com>
|
||||||
|
Joe Bakalor <jmbakalor@gmail.com>
|
||||||
|
Josh Klar <josh@klar.sh>
|
||||||
|
Josh Klar <josh@klar.sh> <j@iv597.com>
|
||||||
|
Juan Biondi <juanernestobiondi@gmail.com>
|
||||||
|
Juan Biondi <juanernestobiondi@gmail.com> <juanernestobiondi@hotmail.com>
|
||||||
|
KalbeAbbas <kalbeabbas142@gmail.com>
|
||||||
|
KalbeAbbas <kalbeabbas142@gmail.com> <kalbeabbas@142@gmail.com>
|
||||||
|
Kamil Tomaszewski <kamil.tomaszewski@sony.com>
|
||||||
|
Kamil Tomaszewski <kamil.tomaszewski@sony.com> <46525824+kamtom480@users.noreply.github.com>
|
||||||
|
Kattni <kattni@adafruit.com> <kattni@kittyfish.org>
|
||||||
|
Kattni Rembor <kattni@adafruit.com>
|
||||||
|
Kenny <WarriorOfWire@users.noreply.github.com>
|
||||||
|
Kenny <WarriorOfWire@users.noreply.github.com> <3454741+WarriorOfWire@users.noreply.github.com>
|
||||||
|
Kevin Townsend <contact@microbuilder.eu>
|
||||||
|
Kevin Townsend <contact@microbuilder.eu> <microbuilder@users.noreply.github.com>
|
||||||
|
Krzysztof Blazewicz <blazewicz.krzysztof@gmail.com>
|
||||||
|
Krzysztof Blazewicz <blazewicz.krzysztof@gmail.com> <krzysztof.blazewicz@uxeon.com>
|
||||||
|
Li Weiwei <liweiwei@yeweitech.org>
|
||||||
|
Li Weiwei <liweiwei@yeweitech.org> <liweiwei@yeweitech.com>
|
||||||
|
Limor "Ladyada" Fried <limor@ladyada.net>
|
||||||
|
Limor "Ladyada" Fried <limor@ladyada.net> <ladyada>
|
||||||
|
Lucian Copeland <hierophect@gmail.com>
|
||||||
|
Lucian Copeland <hierophect@gmail.com> <hierophect@Lucians-MacBook-Air-2.local>
|
||||||
|
Mark Olsson <post@markolsson.se>
|
||||||
|
Mark Olsson <post@markolsson.se> <mark@markolsson.se>
|
||||||
|
Matt Land <matt-land@users.noreply.github.com>
|
||||||
|
Matt Land <matt-land@users.noreply.github.com> <mland@sparefoot.com>
|
||||||
|
Matt Wozniski <godlygeek+git@gmail.com>
|
||||||
|
Matt Wozniski <godlygeek+git@gmail.com> <mwozniski@bloomberg.net>
|
||||||
|
Melissa LeBlanc-Williams <melissa@adafruit.com>
|
||||||
|
Melissa LeBlanc-Williams <melissa@adafruit.com> <melissa@melissagirl.com>
|
||||||
|
Metallicow <metaliobovinus@gmail.com>
|
||||||
|
Metallicow <metaliobovinus@gmail.com> <edg62702@yahoo.com>
|
||||||
|
Peter Hinch <peter@hinch.me.uk>
|
||||||
|
Peter Hinch <peter@hinch.me.uk> <peterhinch@users.noreply.github.com>
|
||||||
|
Radomir Dopieralski <openstack@sheep.art.pl>
|
||||||
|
Radomir Dopieralski <openstack@sheep.art.pl> <deshipu@users.noreply.github.com>
|
||||||
|
Rafa Gould <rafagoulds@gmail.com>
|
||||||
|
Rafa Gould <rafagoulds@gmail.com> <50337143+rafa-gould@users.noreply.github.com>
|
||||||
|
Ryan Shaw <ryan.shaw@wisetechglobal.com>
|
||||||
|
Ryan Shaw <ryan.shaw@wisetechglobal.com> <ryannathans@hotmail.com>
|
||||||
|
Sabas <s@electroniccats.com>
|
||||||
|
Sabas <s@electroniccats.com> <s@theinventorhouse.org>
|
||||||
|
Sabas <s@electroniccats.com> <sabasjimenez@gmail.com>
|
||||||
|
Scott Shawcroft <scott@adafruit.com>
|
||||||
|
Scott Shawcroft <scott@adafruit.com> <devnull@unpythonic.net>
|
||||||
|
Scott Shawcroft <scott@adafruit.com> <scott.shawcroft@gmail.com>
|
||||||
|
Scott Shawcroft <scott@adafruit.com> <scott@chickadee.tech>
|
||||||
|
Scott Shawcroft <scott@adafruit.com> <scott@tannewt.org>
|
||||||
|
Sebastian Plamauer <oeplse@gmail.com>
|
||||||
|
Sebastian Plamauer <oeplse@gmail.com> <oepse@gmail.com>
|
||||||
|
Senuros <Senuros@users.noreply.github.com>
|
||||||
|
Senuros <Senuros@users.noreply.github.com> <senuros@noreply.github.com>
|
||||||
|
Stewart Colborne <tscolborne@outlook.com>
|
||||||
|
Stewart Colborne <tscolborne@outlook.com> <tscolborne@hotmail.com>
|
||||||
|
TG-Techie <TGTechie01@gmail.com>
|
||||||
|
TG-Techie <TGTechie01@gmail.com> <39284876+TG-Techie@users.noreply.github.com>
|
||||||
|
Thea Flowers <me@thea.codes>
|
||||||
|
Thea Flowers <me@thea.codes> <theaflowers@google.com>
|
||||||
|
Tobias Badertscher <badi@baerospace.ch>
|
||||||
|
Tobias Badertscher <badi@baerospace.ch> <python@baerospace.ch>
|
||||||
|
danicampora <danicampora@gmail.com>
|
||||||
|
danicampora <danicampora@gmail.com> <daniel@wipy.io>
|
||||||
|
dherrada <dylan.herrada@gmail.com>
|
||||||
|
dherrada <dylan.herrada@gmail.com> <33632497+dherrada@users.noreply.github.com>
|
||||||
|
dherrada <dylan.herrada@gmail.com> <=>
|
||||||
|
glennrub <glennbakke@gmail.com>
|
||||||
|
retoc <retoc@users.noreply.github.com>
|
||||||
|
retoc <retoc@users.noreply.github.com> <Retoc@noreply.github.com>
|
||||||
|
siddacious <nospam187+github@gmail.com>
|
||||||
|
siddacious <nospam187+github@gmail.com> <bsiepert@gmail.com>
|
||||||
|
siddacious <nospam187+github@gmail.com> <bsiepert@lbl.gov>
|
||||||
|
sommersoft <sommersoft@gmail.com>
|
||||||
|
sommersoft <sommersoft@gmail.com> <sommersoft@users.noreply.github.com>
|
||||||
|
stijn <stijn@ignitron.net>
|
||||||
|
stijn <stijn@ignitron.net> <stinos@zoho.com>
|
13
.pre-commit-config.yaml
Normal file
13
.pre-commit-config.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v2.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/esp32s2/esp-idf-config/.*|ports/esp32s2/boards/.*/sdkconfig)'
|
||||||
|
- id: trailing-whitespace
|
||||||
|
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)'
|
@ -1,9 +1,20 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# .readthedocs.yml
|
# .readthedocs.yml
|
||||||
# Read the Docs configuration file
|
# Read the Docs configuration file
|
||||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
|
submodules:
|
||||||
|
include:
|
||||||
|
- extmod/ulab
|
||||||
|
|
||||||
|
formats:
|
||||||
|
- pdf
|
||||||
|
|
||||||
python:
|
python:
|
||||||
version: 3
|
version: 3
|
||||||
install:
|
install:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# This configuration file tells Rosie where to find prebuilt .bin files (Travis
|
# This configuration file tells Rosie where to find prebuilt .bin files (Travis
|
||||||
# builds them) and where to find the tests.
|
# builds them) and where to find the tests.
|
||||||
|
|
||||||
|
3
ACKNOWLEDGEMENTS.license
Normal file
3
ACKNOWLEDGEMENTS.license
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
@ -1,3 +1,8 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
-->
|
||||||
|
|
||||||
# Building CircuitPython
|
# Building CircuitPython
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2014 Coraline Ada Ehmke
|
||||||
|
SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
|
||||||
|
|
||||||
|
SPDX-License-Identifier: CC-BY-4.0
|
||||||
|
-->
|
||||||
# Adafruit Community Code of Conduct
|
# Adafruit Community Code of Conduct
|
||||||
|
|
||||||
## Our Pledge
|
## Our Pledge
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
-->
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
Please note that this project is released with a
|
Please note that this project is released with a
|
||||||
[Contributor Code of Conduct](https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.md).
|
[Contributor Code of Conduct](https://github.com/adafruit/circuitpython/blob/main/CODE_OF_CONDUCT.md).
|
||||||
By participating in this project you agree to abide by its terms. Participation
|
By participating in this project you agree to abide by its terms. Participation
|
||||||
covers any forum used to converse about CircuitPython including unofficial and official spaces. Failure to do
|
covers any forum used to converse about CircuitPython including unofficial and official spaces. Failure to do
|
||||||
so will result in corrective actions such as time out or ban from the project.
|
so will result in corrective actions such as time out or ban from the project.
|
||||||
|
26
LICENSES/BSD-3-Clause.txt
Normal file
26
LICENSES/BSD-3-Clause.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Copyright (c) <year> <owner>. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
324
LICENSES/CC-BY-4.0.txt
Normal file
324
LICENSES/CC-BY-4.0.txt
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
Creative Commons Attribution 4.0 International Creative Commons Corporation
|
||||||
|
("Creative Commons") is not a law firm and does not provide legal services
|
||||||
|
or legal advice. Distribution of Creative Commons public licenses does not
|
||||||
|
create a lawyer-client or other relationship. Creative Commons makes its licenses
|
||||||
|
and related information available on an "as-is" basis. Creative Commons gives
|
||||||
|
no warranties regarding its licenses, any material licensed under their terms
|
||||||
|
and conditions, or any related information. Creative Commons disclaims all
|
||||||
|
liability for damages resulting from their use to the fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and conditions
|
||||||
|
that creators and other rights holders may use to share original works of
|
||||||
|
authorship and other material subject to copyright and certain other rights
|
||||||
|
specified in the public license below. The following considerations are for
|
||||||
|
informational purposes only, are not exhaustive, and do not form part of our
|
||||||
|
licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are intended for use by
|
||||||
|
those authorized to give the public permission to use material in ways otherwise
|
||||||
|
restricted by copyright and certain other rights. Our licenses are irrevocable.
|
||||||
|
Licensors should read and understand the terms and conditions of the license
|
||||||
|
they choose before applying it. Licensors should also secure all rights necessary
|
||||||
|
before applying our licenses so that the public can reuse the material as
|
||||||
|
expected. Licensors should clearly mark any material not subject to the license.
|
||||||
|
This includes other CC-licensed material, or material used under an exception
|
||||||
|
or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public licenses, a licensor
|
||||||
|
grants the public permission to use the licensed material under specified
|
||||||
|
terms and conditions. If the licensor's permission is not necessary for any
|
||||||
|
reason–for example, because of any applicable exception or limitation to copyright–then
|
||||||
|
that use is not regulated by the license. Our licenses grant only permissions
|
||||||
|
under copyright and certain other rights that a licensor has authority to
|
||||||
|
grant. Use of the licensed material may still be restricted for other reasons,
|
||||||
|
including because others have copyright or other rights in the material. A
|
||||||
|
licensor may make special requests, such as asking that all changes be marked
|
||||||
|
or described. Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations for the public
|
||||||
|
: wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution
|
||||||
|
4.0 International Public License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree to
|
||||||
|
be bound by the terms and conditions of this Creative Commons Attribution
|
||||||
|
4.0 International Public License ("Public License"). To the extent this Public
|
||||||
|
License may be interpreted as a contract, You are granted the Licensed Rights
|
||||||
|
in consideration of Your acceptance of these terms and conditions, and the
|
||||||
|
Licensor grants You such rights in consideration of benefits the Licensor
|
||||||
|
receives from making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
Section 1 – Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar Rights
|
||||||
|
that is derived from or based upon the Licensed Material and in which the
|
||||||
|
Licensed Material is translated, altered, arranged, transformed, or otherwise
|
||||||
|
modified in a manner requiring permission under the Copyright and Similar
|
||||||
|
Rights held by the Licensor. For purposes of this Public License, where the
|
||||||
|
Licensed Material is a musical work, performance, or sound recording, Adapted
|
||||||
|
Material is always produced where the Licensed Material is synched in timed
|
||||||
|
relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright and Similar
|
||||||
|
Rights in Your contributions to Adapted Material in accordance with the terms
|
||||||
|
and conditions of this Public License.
|
||||||
|
|
||||||
|
c. Copyright and Similar Rights means copyright and/or similar rights closely
|
||||||
|
related to copyright including, without limitation, performance, broadcast,
|
||||||
|
sound recording, and Sui Generis Database Rights, without regard to how the
|
||||||
|
rights are labeled or categorized. For purposes of this Public License, the
|
||||||
|
rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
|
||||||
|
|
||||||
|
d. Effective Technological Measures means those measures that, in the absence
|
||||||
|
of proper authority, may not be circumvented under laws fulfilling obligations
|
||||||
|
under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996,
|
||||||
|
and/or similar international agreements.
|
||||||
|
|
||||||
|
e. Exceptions and Limitations means fair use, fair dealing, and/or any other
|
||||||
|
exception or limitation to Copyright and Similar Rights that applies to Your
|
||||||
|
use of the Licensed Material.
|
||||||
|
|
||||||
|
f. Licensed Material means the artistic or literary work, database, or other
|
||||||
|
material to which the Licensor applied this Public License.
|
||||||
|
|
||||||
|
g. Licensed Rights means the rights granted to You subject to the terms and
|
||||||
|
conditions of this Public License, which are limited to all Copyright and
|
||||||
|
Similar Rights that apply to Your use of the Licensed Material and that the
|
||||||
|
Licensor has authority to license.
|
||||||
|
|
||||||
|
h. Licensor means the individual(s) or entity(ies) granting rights under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
i. Share means to provide material to the public by any means or process that
|
||||||
|
requires permission under the Licensed Rights, such as reproduction, public
|
||||||
|
display, public performance, distribution, dissemination, communication, or
|
||||||
|
importation, and to make material available to the public including in ways
|
||||||
|
that members of the public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
j. Sui Generis Database Rights means rights other than copyright resulting
|
||||||
|
from Directive 96/9/EC of the European Parliament and of the Council of 11
|
||||||
|
March 1996 on the legal protection of databases, as amended and/or succeeded,
|
||||||
|
as well as other essentially equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
k. You means the individual or entity exercising the Licensed Rights under
|
||||||
|
this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
Section 2 – Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License, the Licensor
|
||||||
|
hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive,
|
||||||
|
irrevocable license to exercise the Licensed Rights in the Licensed Material
|
||||||
|
to:
|
||||||
|
|
||||||
|
A. reproduce and Share the Licensed Material, in whole or in part; and
|
||||||
|
|
||||||
|
B. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions
|
||||||
|
and Limitations apply to Your use, this Public License does not apply, and
|
||||||
|
You do not need to comply with its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section 6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The Licensor authorizes
|
||||||
|
You to exercise the Licensed Rights in all media and formats whether now known
|
||||||
|
or hereafter created, and to make technical modifications necessary to do
|
||||||
|
so. The Licensor waives and/or agrees not to assert any right or authority
|
||||||
|
to forbid You from making technical modifications necessary to exercise the
|
||||||
|
Licensed Rights, including technical modifications necessary to circumvent
|
||||||
|
Effective Technological Measures. For purposes of this Public License, simply
|
||||||
|
making modifications authorized by this Section 2(a)(4) never produces Adapted
|
||||||
|
Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed
|
||||||
|
Material automatically receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
B. No downstream restrictions. You may not offer or impose any additional
|
||||||
|
or different terms or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, the Licensed Material if doing so restricts exercise of the Licensed
|
||||||
|
Rights by any recipient of the Licensed Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or may be construed
|
||||||
|
as permission to assert or imply that You are, or that Your use of the Licensed
|
||||||
|
Material is, connected with, or sponsored, endorsed, or granted official status
|
||||||
|
by, the Licensor or others designated to receive attribution as provided in
|
||||||
|
Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not licensed under this
|
||||||
|
Public License, nor are publicity, privacy, and/or other similar personality
|
||||||
|
rights; however, to the extent possible, the Licensor waives and/or agrees
|
||||||
|
not to assert any such rights held by the Licensor to the limited extent necessary
|
||||||
|
to allow You to exercise the Licensed Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to collect royalties
|
||||||
|
from You for the exercise of the Licensed Rights, whether directly or through
|
||||||
|
a collecting society under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly reserves any right
|
||||||
|
to collect such royalties.
|
||||||
|
|
||||||
|
Section 3 – License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the following
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified form), You must:
|
||||||
|
|
||||||
|
A. retain the following if it is supplied by the Licensor with the Licensed
|
||||||
|
Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed Material and any others
|
||||||
|
designated to receive attribution, in any reasonable manner requested by the
|
||||||
|
Licensor (including by pseudonym if designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
|
||||||
|
|
||||||
|
B. indicate if You modified the Licensed Material and retain an indication
|
||||||
|
of any previous modifications; and
|
||||||
|
|
||||||
|
C. indicate the Licensed Material is licensed under this Public License, and
|
||||||
|
include the text of, or the URI or hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner
|
||||||
|
based on the medium, means, and context in which You Share the Licensed Material.
|
||||||
|
For example, it may be reasonable to satisfy the conditions by providing a
|
||||||
|
URI or hyperlink to a resource that includes the required information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the information required
|
||||||
|
by Section 3(a)(1)(A) to the extent reasonably practicable.
|
||||||
|
|
||||||
|
4. If You Share Adapted Material You produce, the Adapter's License You apply
|
||||||
|
must not prevent recipients of the Adapted Material from complying with this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
Section 4 – Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that apply to
|
||||||
|
Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract,
|
||||||
|
reuse, reproduce, and Share all or a substantial portion of the contents of
|
||||||
|
the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database contents in
|
||||||
|
a database in which You have Sui Generis Database Rights, then the database
|
||||||
|
in which You have Sui Generis Database Rights (but not its individual contents)
|
||||||
|
is Adapted Material; and
|
||||||
|
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share all or
|
||||||
|
a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not replace
|
||||||
|
Your obligations under this Public License where the Licensed Rights include
|
||||||
|
other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. Unless otherwise separately undertaken by the Licensor, to the extent possible,
|
||||||
|
the Licensor offers the Licensed Material as-is and as-available, and makes
|
||||||
|
no representations or warranties of any kind concerning the Licensed Material,
|
||||||
|
whether express, implied, statutory, or other. This includes, without limitation,
|
||||||
|
warranties of title, merchantability, fitness for a particular purpose, non-infringement,
|
||||||
|
absence of latent or other defects, accuracy, or the presence or absence of
|
||||||
|
errors, whether or not known or discoverable. Where disclaimers of warranties
|
||||||
|
are not allowed in full or in part, this disclaimer may not apply to You.
|
||||||
|
|
||||||
|
b. To the extent possible, in no event will the Licensor be liable to You
|
||||||
|
on any legal theory (including, without limitation, negligence) or otherwise
|
||||||
|
for any direct, special, indirect, incidental, consequential, punitive, exemplary,
|
||||||
|
or other losses, costs, expenses, or damages arising out of this Public License
|
||||||
|
or use of the Licensed Material, even if the Licensor has been advised of
|
||||||
|
the possibility of such losses, costs, expenses, or damages. Where a limitation
|
||||||
|
of liability is not allowed in full or in part, this limitation may not apply
|
||||||
|
to You.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided above
|
||||||
|
shall be interpreted in a manner that, to the extent possible, most closely
|
||||||
|
approximates an absolute disclaimer and waiver of all liability.
|
||||||
|
|
||||||
|
Section 6 – Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and Similar Rights
|
||||||
|
licensed here. However, if You fail to comply with this Public License, then
|
||||||
|
Your rights under this Public License terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under Section
|
||||||
|
6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided it is cured
|
||||||
|
within 30 days of Your discovery of the violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, this Section 6(b) does not affect any right
|
||||||
|
the Licensor may have to seek remedies for Your violations of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
d. For the avoidance of doubt, the Licensor may also offer the Licensed Material
|
||||||
|
under separate terms or conditions or stop distributing the Licensed Material
|
||||||
|
at any time; however, doing so will not terminate this Public License.
|
||||||
|
|
||||||
|
e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
|
||||||
|
|
||||||
|
Section 7 – Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different terms or
|
||||||
|
conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the Licensed
|
||||||
|
Material not stated herein are separate from and independent of the terms
|
||||||
|
and conditions of this Public License.
|
||||||
|
|
||||||
|
Section 8 – Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and shall not
|
||||||
|
be interpreted to, reduce, limit, restrict, or impose conditions on any use
|
||||||
|
of the Licensed Material that could lawfully be made without permission under
|
||||||
|
this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is deemed
|
||||||
|
unenforceable, it shall be automatically reformed to the minimum extent necessary
|
||||||
|
to make it enforceable. If the provision cannot be reformed, it shall be severed
|
||||||
|
from this Public License without affecting the enforceability of the remaining
|
||||||
|
terms and conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no failure
|
||||||
|
to comply consented to unless expressly agreed to by the Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted as a limitation
|
||||||
|
upon, or waiver of, any privileges and immunities that apply to the Licensor
|
||||||
|
or You, including from the legal processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public licenses. Notwithstanding, Creative
|
||||||
|
Commons may elect to apply one of its public licenses to material it publishes
|
||||||
|
and in those instances will be considered the "Licensor." The text of the
|
||||||
|
Creative Commons public licenses is dedicated to the public domain under the
|
||||||
|
CC0 Public Domain Dedication. Except for the limited purpose of indicating
|
||||||
|
that material is shared under a Creative Commons public license or as otherwise
|
||||||
|
permitted by the Creative Commons policies published at creativecommons.org/policies,
|
||||||
|
Creative Commons does not authorize the use of the trademark "Creative Commons"
|
||||||
|
or any other trademark or logo of Creative Commons without its prior written
|
||||||
|
consent including, without limitation, in connection with any unauthorized
|
||||||
|
modifications to any of its public licenses or any other arrangements, understandings,
|
||||||
|
or agreements concerning use of licensed material. For the avoidance of doubt,
|
||||||
|
this paragraph does not form part of the public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
19
LICENSES/MIT.txt
Normal file
19
LICENSES/MIT.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
MIT License Copyright (c) <year> <copyright holders>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
|
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
90
LICENSES/OFL-1.1.txt
Normal file
90
LICENSES/OFL-1.1.txt
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
Copyright (c) <dates>, <Copyright Holder> (<URL|email>),
|
||||||
|
|
||||||
|
with Reserved Font Name <Reserved Font Name>. This Font Software is licensed
|
||||||
|
under the SIL Open Font License, Version 1.1.
|
||||||
|
|
||||||
|
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||||
|
SIL OPEN FONT LICENSE
|
||||||
|
|
||||||
|
Version 1.1 - 26 February 2007
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide development
|
||||||
|
of collaborative font projects, to support the font creation efforts of academic
|
||||||
|
and linguistic communities, and to provide a free and open framework in which
|
||||||
|
fonts may be shared and improved in partnership with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and redistributed
|
||||||
|
freely as long as they are not sold by themselves. The fonts, including any
|
||||||
|
derivative works, can be bundled, embedded, redistributed and/or sold with
|
||||||
|
any software provided that any reserved names are not used by derivative works.
|
||||||
|
The fonts and derivatives, however, cannot be released under any other type
|
||||||
|
of license. The requirement for fonts to remain under this license does not
|
||||||
|
apply to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
|
||||||
|
"Font Software" refers to the set of files released by the Copyright Holder(s)
|
||||||
|
under this license and clearly marked as such. This may include source files,
|
||||||
|
build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the copyright
|
||||||
|
statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting, or
|
||||||
|
substituting — in part or in whole — any of the components of the Original
|
||||||
|
Version, by changing formats or by porting the Font Software to a new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical writer or
|
||||||
|
other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of the Font Software, to use, study, copy, merge, embed, modify, redistribute,
|
||||||
|
and sell modified and unmodified copies of the Font Software, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components, in Original
|
||||||
|
or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled, redistributed
|
||||||
|
and/or sold with any software, provided that each copy contains the above
|
||||||
|
copyright notice and this license. These can be included either as stand-alone
|
||||||
|
text files, human-readable headers or in the appropriate machine-readable
|
||||||
|
metadata fields within text or binary files as long as those fields can be
|
||||||
|
easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font Name(s)
|
||||||
|
unless explicit written permission is granted by the corresponding Copyright
|
||||||
|
Holder. This restriction only applies to the primary font name as presented
|
||||||
|
to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software
|
||||||
|
shall not be used to promote, endorse or advertise any Modified Version, except
|
||||||
|
to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s)
|
||||||
|
or with their explicit written permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole, must be
|
||||||
|
distributed entirely under this license, and must not be distributed under
|
||||||
|
any other license. The requirement for fonts to remain under this license
|
||||||
|
does not apply to any document created using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
|
||||||
|
This license becomes null and void if any of the above conditions are not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||||
|
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE
|
||||||
|
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL,
|
||||||
|
INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
|
||||||
|
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
20
LICENSES/Unlicense.txt
Normal file
20
LICENSES/Unlicense.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||||
|
this software, either in source code form or as a compiled binary, for any
|
||||||
|
purpose, commercial or non-commercial, and by any means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||||
|
software dedicate any and all copyright interest in the software to the public
|
||||||
|
domain. We make this dedication for the benefit of the public at large and
|
||||||
|
to the detriment of our heirs and successors. We intend this dedication to
|
||||||
|
be an overt act of relinquishment in perpetuity of all present and future
|
||||||
|
rights to this software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||||
|
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information,
|
||||||
|
please refer to <https://unlicense.org/>
|
105
Makefile
105
Makefile
@ -1,3 +1,7 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# Top-level Makefile for documentation builds and miscellaneous tasks.
|
# Top-level Makefile for documentation builds and miscellaneous tasks.
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -36,7 +40,19 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(BASEOPTS)
|
|||||||
# the i18n builder cannot share the environment and doctrees with the others
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
I18NSPHINXOPTS = $(BASEOPTS)
|
I18NSPHINXOPTS = $(BASEOPTS)
|
||||||
|
|
||||||
TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/cxd56 ports/mimxrt10xx ports/nrf ports/stm py shared-bindings shared-module supervisor
|
TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/cxd56 ports/esp32s2 ports/mimxrt10xx ports/nrf ports/stm py shared-bindings shared-module supervisor
|
||||||
|
# Paths to exclude from TRANSLATE_SOURCES
|
||||||
|
# Each must be preceded by "-path"; if any wildcards, enclose in quotes.
|
||||||
|
# Separate by "-o" (Find's "or" operand)
|
||||||
|
TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \
|
||||||
|
-o -path "ports/*/build" \
|
||||||
|
-o -path ports/esp32s2/esp-idf \
|
||||||
|
-o -path ports/cxd56/spresense-exported-sdk \
|
||||||
|
-o -path ports/stm/st_driver \
|
||||||
|
-o -path ports/atmel-samd/asf4 \
|
||||||
|
-o -path ports/mimxrt10xx/sdk \
|
||||||
|
-o -path lib/tinyusb \
|
||||||
|
-o -path lib/lwip \
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext stubs
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext stubs
|
||||||
|
|
||||||
@ -67,9 +83,10 @@ help:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILDDIR)/*
|
rm -rf $(BUILDDIR)/*
|
||||||
|
rm -rf autoapi
|
||||||
rm -rf $(STUBDIR) $(DISTDIR) *.egg-info
|
rm -rf $(STUBDIR) $(DISTDIR) *.egg-info
|
||||||
|
|
||||||
html:
|
html: stubs
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
@ -201,21 +218,95 @@ pseudoxml:
|
|||||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||||
|
|
||||||
# phony target so we always run
|
# phony target so we always run
|
||||||
|
.PHONY: all-source
|
||||||
all-source:
|
all-source:
|
||||||
|
|
||||||
locale/circuitpython.pot: all-source
|
locale/circuitpython.pot: all-source
|
||||||
find $(TRANSLATE_SOURCES) -iname "*.c" -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o circuitpython.pot -p locale
|
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o circuitpython.pot -p locale
|
||||||
|
|
||||||
|
# Historically, `make translate` updated the .pot file and ran msgmerge.
|
||||||
|
# However, this was a frequent source of merge conflicts. Weblate can perform
|
||||||
|
# msgmerge, so make translate merely update the translation template file.
|
||||||
|
.PHONY: translate
|
||||||
translate: locale/circuitpython.pot
|
translate: locale/circuitpython.pot
|
||||||
|
|
||||||
|
# Note that normally we rely on weblate to perform msgmerge. This reduces the
|
||||||
|
# chance of a merge conflict between developer changes (that only add and
|
||||||
|
# remove source strings) and weblate changes (that only add and remove
|
||||||
|
# translated strings from po files). However, in case this is legitimately
|
||||||
|
# needed we preserve a rule to do it.
|
||||||
|
.PHONY: msgmerge
|
||||||
|
msgmerge:
|
||||||
for po in $(shell ls locale/*.po); do msgmerge -U $$po -s --no-fuzzy-matching --add-location=file locale/circuitpython.pot; done
|
for po in $(shell ls locale/*.po); do msgmerge -U $$po -s --no-fuzzy-matching --add-location=file locale/circuitpython.pot; done
|
||||||
|
|
||||||
check-translate: locale/circuitpython.pot $(wildcard locale/*.po)
|
merge-translate:
|
||||||
$(PYTHON) tools/check_translations.py $^
|
git merge HEAD 1>&2 2> /dev/null; test $$? -eq 128
|
||||||
|
rm locale/*~ || true
|
||||||
|
git checkout --theirs -- locale/*
|
||||||
|
make translate
|
||||||
|
|
||||||
|
.PHONY: check-translate
|
||||||
|
check-translate:
|
||||||
|
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o circuitpython.pot.tmp -p locale
|
||||||
|
$(PYTHON) tools/check_translations.py locale/circuitpython.pot.tmp locale/circuitpython.pot; status=$$?; rm -f locale/circuitpython.pot.tmp; exit $$status
|
||||||
|
|
||||||
stubs:
|
stubs:
|
||||||
rst2pyi $(VALIDATE) shared-bindings/ $(STUBDIR)
|
@mkdir -p circuitpython-stubs
|
||||||
python setup.py sdist
|
@$(PYTHON) tools/extract_pyi.py shared-bindings/ $(STUBDIR)
|
||||||
|
@$(PYTHON) tools/extract_pyi.py extmod/ulab/code/ $(STUBDIR)/ulab
|
||||||
|
@$(PYTHON) tools/extract_pyi.py ports/atmel-samd/bindings $(STUBDIR)
|
||||||
|
@$(PYTHON) setup.py -q sdist
|
||||||
|
|
||||||
|
.PHONY: check-stubs
|
||||||
|
check-stubs: stubs
|
||||||
|
MYPYPATH=$(STUBDIR) mypy --strict $(STUBDIR)
|
||||||
|
|
||||||
update-frozen-libraries:
|
update-frozen-libraries:
|
||||||
@echo "Updating all frozen libraries to latest tagged version."
|
@echo "Updating all frozen libraries to latest tagged version."
|
||||||
cd frozen; for library in *; do cd $$library; ../../tools/git-checkout-latest-tag.sh; cd ..; done
|
cd frozen; for library in *; do cd $$library; ../../tools/git-checkout-latest-tag.sh; cd ..; done
|
||||||
|
|
||||||
|
one-of-each: samd21 samd51 esp32s2 litex mimxrt10xx nrf stm
|
||||||
|
|
||||||
|
samd21:
|
||||||
|
$(MAKE) -C ports/atmel-samd BOARD=trinket_m0
|
||||||
|
|
||||||
|
samd51:
|
||||||
|
$(MAKE) -C ports/atmel-samd BOARD=feather_m4_express
|
||||||
|
|
||||||
|
esp32s2:
|
||||||
|
$(MAKE) -C ports/esp32s2 BOARD=espressif_saola_1_wroom
|
||||||
|
|
||||||
|
litex:
|
||||||
|
$(MAKE) -C ports/litex BOARD=fomu
|
||||||
|
|
||||||
|
mimxrt10xx:
|
||||||
|
$(MAKE) -C ports/mimxrt10xx BOARD=feather_mimxrt1011
|
||||||
|
|
||||||
|
nrf:
|
||||||
|
$(MAKE) -C ports/nrf BOARD=feather_nrf52840_express
|
||||||
|
|
||||||
|
stm:
|
||||||
|
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express
|
||||||
|
|
||||||
|
clean-one-of-each: clean-samd21 clean-samd51 clean-esp32s2 clean-litex clean-mimxrt10xx clean-nrf clean-stm
|
||||||
|
|
||||||
|
clean-samd21:
|
||||||
|
$(MAKE) -C ports/atmel-samd BOARD=trinket_m0 clean
|
||||||
|
|
||||||
|
clean-samd51:
|
||||||
|
$(MAKE) -C ports/atmel-samd BOARD=feather_m4_express clean
|
||||||
|
|
||||||
|
clean-esp32s2:
|
||||||
|
$(MAKE) -C ports/esp32s2 BOARD=espressif_saola_1_wroom clean
|
||||||
|
|
||||||
|
clean-litex:
|
||||||
|
$(MAKE) -C ports/litex BOARD=fomu clean
|
||||||
|
|
||||||
|
clean-mimxrt10xx:
|
||||||
|
$(MAKE) -C ports/mimxrt10xx BOARD=feather_mimxrt1011 clean
|
||||||
|
|
||||||
|
clean-nrf:
|
||||||
|
$(MAKE) -C ports/nrf BOARD=feather_nrf52840_express clean
|
||||||
|
|
||||||
|
clean-stm:
|
||||||
|
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express clean
|
||||||
|
15
README.rst
15
README.rst
@ -3,7 +3,7 @@ CircuitPython
|
|||||||
|
|
||||||
.. image:: https://s3.amazonaws.com/adafruit-circuit-python/CircuitPython_Repo_header_logo.png
|
.. image:: https://s3.amazonaws.com/adafruit-circuit-python/CircuitPython_Repo_header_logo.png
|
||||||
|
|
||||||
|Build Status| |Doc Status| |License| |Discord|
|
|Build Status| |Doc Status| |License| |Discord| |Weblate|
|
||||||
|
|
||||||
`circuitpython.org <https://circuitpython.org>`__ \| `Get CircuitPython <#get-circuitpython>`__ \|
|
`circuitpython.org <https://circuitpython.org>`__ \| `Get CircuitPython <#get-circuitpython>`__ \|
|
||||||
`Documentation <#documentation>`__ \| `Contributing <#contributing>`__ \|
|
`Documentation <#documentation>`__ \| `Contributing <#contributing>`__ \|
|
||||||
@ -55,12 +55,12 @@ Contributing
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
See
|
See
|
||||||
`CONTRIBUTING.md <https://github.com/adafruit/circuitpython/blob/master/CONTRIBUTING.md>`__
|
`CONTRIBUTING.md <https://github.com/adafruit/circuitpython/blob/main/CONTRIBUTING.md>`__
|
||||||
for full guidelines but please be aware that by contributing to this
|
for full guidelines but please be aware that by contributing to this
|
||||||
project you are agreeing to the `Code of
|
project you are agreeing to the `Code of
|
||||||
Conduct <https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.md>`__.
|
Conduct <https://github.com/adafruit/circuitpython/blob/main/CODE_OF_CONDUCT.md>`__.
|
||||||
Contributors who follow the `Code of
|
Contributors who follow the `Code of
|
||||||
Conduct <https://github.com/adafruit/circuitpython/blob/master/CODE_OF_CONDUCT.md>`__
|
Conduct <https://github.com/adafruit/circuitpython/blob/main/CODE_OF_CONDUCT.md>`__
|
||||||
are welcome to submit pull requests and they will be promptly reviewed
|
are welcome to submit pull requests and they will be promptly reviewed
|
||||||
by project admins. Please join the
|
by project admins. Please join the
|
||||||
`Discord <https://adafru.it/discord>`__ too.
|
`Discord <https://adafru.it/discord>`__ too.
|
||||||
@ -96,7 +96,6 @@ CircuitPython:
|
|||||||
|
|
||||||
- Supports native USB on all boards, allowing file editing without special tools.
|
- Supports native USB on all boards, allowing file editing without special tools.
|
||||||
- Supports only SAMD21, SAMD51, nRF52840, CXD56, STM32F4 and i.MX RT ports.
|
- Supports only SAMD21, SAMD51, nRF52840, CXD56, STM32F4 and i.MX RT ports.
|
||||||
- Tracks MicroPython's releases (not master).
|
|
||||||
- Floats (aka decimals) are enabled for all builds.
|
- Floats (aka decimals) are enabled for all builds.
|
||||||
- Error messages are translated into 10+ languages.
|
- Error messages are translated into 10+ languages.
|
||||||
- Does not support concurrency within Python (including interrupts and threading). Some concurrency
|
- Does not support concurrency within Python (including interrupts and threading). Some concurrency
|
||||||
@ -211,11 +210,13 @@ The remaining port directories not listed above are in the repo to maintain comp
|
|||||||
|
|
||||||
`back to top <#circuitpython>`__
|
`back to top <#circuitpython>`__
|
||||||
|
|
||||||
.. |Build Status| image:: https://travis-ci.com/adafruit/circuitpython.svg?branch=master
|
.. |Build Status| image:: https://github.com/adafruit/circuitpython/workflows/Build%20CI/badge.svg
|
||||||
:target: https://travis-ci.org/adafruit/circuitpython
|
:target: https://github.com/adafruit/circuitpython/actions?query=branch%3Amain
|
||||||
.. |Doc Status| image:: https://readthedocs.org/projects/circuitpython/badge/?version=latest
|
.. |Doc Status| image:: https://readthedocs.org/projects/circuitpython/badge/?version=latest
|
||||||
:target: http://circuitpython.readthedocs.io/
|
:target: http://circuitpython.readthedocs.io/
|
||||||
.. |Discord| image:: https://img.shields.io/discord/327254708534116352.svg
|
.. |Discord| image:: https://img.shields.io/discord/327254708534116352.svg
|
||||||
:target: https://adafru.it/discord
|
:target: https://adafru.it/discord
|
||||||
.. |License| image:: https://img.shields.io/badge/License-MIT-brightgreen.svg
|
.. |License| image:: https://img.shields.io/badge/License-MIT-brightgreen.svg
|
||||||
:target: https://choosealicense.com/licenses/mit/
|
:target: https://choosealicense.com/licenses/mit/
|
||||||
|
.. |Weblate| image:: https://hosted.weblate.org/widgets/circuitpython/-/svg-badge.svg
|
||||||
|
:target: https://hosted.weblate.org/engage/circuitpython/?utm_source=widget
|
||||||
|
132
conf.py
132
conf.py
@ -13,11 +13,21 @@
|
|||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
import json
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
import sys
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import recommonmark
|
import recommonmark
|
||||||
|
from sphinx.transforms import SphinxTransform
|
||||||
|
from docutils import nodes
|
||||||
|
from sphinx import addnodes
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
@ -32,6 +42,9 @@ master_doc = 'docs/index'
|
|||||||
# Grab the JSON values to use while building the module support matrix
|
# Grab the JSON values to use while building the module support matrix
|
||||||
# in 'shared-bindings/index.rst'
|
# in 'shared-bindings/index.rst'
|
||||||
|
|
||||||
|
# The stubs must be built before we calculate the shared bindings matrix
|
||||||
|
subprocess.check_output(["make", "stubs"])
|
||||||
|
|
||||||
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
|
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
|
||||||
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
|
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
|
||||||
|
|
||||||
@ -55,7 +68,6 @@ extensions = [
|
|||||||
'sphinx.ext.todo',
|
'sphinx.ext.todo',
|
||||||
'sphinx.ext.coverage',
|
'sphinx.ext.coverage',
|
||||||
'rstjinja',
|
'rstjinja',
|
||||||
'c2rst',
|
|
||||||
'recommonmark',
|
'recommonmark',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -66,9 +78,22 @@ templates_path = ['templates']
|
|||||||
source_suffix = {
|
source_suffix = {
|
||||||
'.rst': 'restructuredtext',
|
'.rst': 'restructuredtext',
|
||||||
'.md': 'markdown',
|
'.md': 'markdown',
|
||||||
'.c': ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extensions.append('autoapi.extension')
|
||||||
|
|
||||||
|
autoapi_type = 'python'
|
||||||
|
# Uncomment this if debugging autoapi
|
||||||
|
autoapi_keep_files = True
|
||||||
|
autoapi_dirs = [os.path.join('circuitpython-stubs', x) for x in os.listdir('circuitpython-stubs')]
|
||||||
|
autoapi_add_toctree_entry = False
|
||||||
|
autoapi_options = ['members', 'undoc-members', 'private-members', 'show-inheritance', 'special-members', 'show-module-summary']
|
||||||
|
autoapi_template_dir = 'docs/autoapi/templates'
|
||||||
|
autoapi_python_class_content = "both"
|
||||||
|
autoapi_python_use_implicit_namespaces = True
|
||||||
|
autoapi_root = "shared-bindings"
|
||||||
|
|
||||||
|
redirects_file = 'docs/redirects.txt'
|
||||||
|
|
||||||
# The encoding of source files.
|
# The encoding of source files.
|
||||||
#source_encoding = 'utf-8-sig'
|
#source_encoding = 'utf-8-sig'
|
||||||
@ -78,7 +103,7 @@ source_suffix = {
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'Adafruit CircuitPython'
|
project = 'Adafruit CircuitPython'
|
||||||
copyright = '2014-2018, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)'
|
copyright = '2014-2020, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)'
|
||||||
|
|
||||||
# These are overwritten on ReadTheDocs.
|
# These are overwritten on ReadTheDocs.
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
@ -87,7 +112,25 @@ copyright = '2014-2018, MicroPython & CircuitPython contributors (https://github
|
|||||||
#
|
#
|
||||||
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
|
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
|
||||||
# breakdown, so use the same version identifier for both to avoid confusion.
|
# breakdown, so use the same version identifier for both to avoid confusion.
|
||||||
version = release = '0.0.0'
|
|
||||||
|
final_version = ""
|
||||||
|
git_describe = subprocess.run(
|
||||||
|
["git", "describe", "--dirty", "--tags"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
if git_describe.returncode == 0:
|
||||||
|
git_version = re.search(
|
||||||
|
r"^\d(?:\.\d){0,2}(?:\-(?:alpha|beta|rc)\.\d+){0,1}",
|
||||||
|
str(git_describe.stdout)
|
||||||
|
)
|
||||||
|
if git_version:
|
||||||
|
final_version = git_version[0]
|
||||||
|
else:
|
||||||
|
print("Failed to retrieve git version:", git_describe.stdout)
|
||||||
|
|
||||||
|
version = release = final_version
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
@ -103,8 +146,10 @@ version = release = '0.0.0'
|
|||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
exclude_patterns = ["**/build*",
|
exclude_patterns = ["**/build*",
|
||||||
".git",
|
".git",
|
||||||
|
".env",
|
||||||
".venv",
|
".venv",
|
||||||
".direnv",
|
".direnv",
|
||||||
|
"docs/autoapi",
|
||||||
"docs/README.md",
|
"docs/README.md",
|
||||||
"drivers",
|
"drivers",
|
||||||
"examples",
|
"examples",
|
||||||
@ -127,6 +172,8 @@ exclude_patterns = ["**/build*",
|
|||||||
"ports/atmel-samd/tools",
|
"ports/atmel-samd/tools",
|
||||||
"ports/cxd56/mkspk",
|
"ports/cxd56/mkspk",
|
||||||
"ports/cxd56/spresense-exported-sdk",
|
"ports/cxd56/spresense-exported-sdk",
|
||||||
|
"ports/esp32s2/esp-idf",
|
||||||
|
"ports/esp32s2/peripherals",
|
||||||
"ports/litex/hw",
|
"ports/litex/hw",
|
||||||
"ports/minimal",
|
"ports/minimal",
|
||||||
"ports/mimxrt10xx/peripherals",
|
"ports/mimxrt10xx/peripherals",
|
||||||
@ -361,5 +408,78 @@ intersphinx_mapping = {"cpython": ('https://docs.python.org/3/', None),
|
|||||||
"bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),
|
"bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),
|
||||||
"register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)}
|
"register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)}
|
||||||
|
|
||||||
|
# Adapted from sphinxcontrib-redirects
|
||||||
|
from sphinx.builders import html as builders
|
||||||
|
|
||||||
|
TEMPLATE = """<html>
|
||||||
|
<head><meta http-equiv="refresh" content="0; url=%s"/></head>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def generate_redirects(app):
|
||||||
|
path = os.path.join(app.srcdir, app.config.redirects_file)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
logging.error("Could not find redirects file at '%s'" % path)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(app.builder, builders.StandaloneHTMLBuilder):
|
||||||
|
logging.warn("The 'sphinxcontib-redirects' plugin is only supported "
|
||||||
|
"by the 'html' builder and subclasses. Skipping...")
|
||||||
|
logging.warn(f"Builder is {app.builder.name} ({type(app.builder)})")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(path) as redirects:
|
||||||
|
for line in redirects.readlines():
|
||||||
|
from_path, to_path = line.rstrip().split(' ')
|
||||||
|
|
||||||
|
logging.debug("Redirecting '%s' to '%s'" % (from_path, to_path))
|
||||||
|
|
||||||
|
from_path = os.path.splitext(from_path)[0] + ".html"
|
||||||
|
to_path_prefix = '..%s' % os.path.sep * (
|
||||||
|
len(from_path.split(os.path.sep)) - 1)
|
||||||
|
to_path = to_path_prefix + to_path
|
||||||
|
|
||||||
|
redirected_filename = os.path.join(app.builder.outdir, from_path)
|
||||||
|
redirected_directory = os.path.dirname(redirected_filename)
|
||||||
|
if not os.path.exists(redirected_directory):
|
||||||
|
os.makedirs(redirected_directory)
|
||||||
|
|
||||||
|
with open(redirected_filename, 'w') as f:
|
||||||
|
f.write(TEMPLATE % urllib.parse.quote(to_path, '#/'))
|
||||||
|
|
||||||
|
|
||||||
|
class CoreModuleTransform(SphinxTransform):
|
||||||
|
default_priority = 870
|
||||||
|
|
||||||
|
def _convert_first_paragraph_into_title(self):
|
||||||
|
title = self.document.next_node(nodes.title)
|
||||||
|
paragraph = self.document.next_node(nodes.paragraph)
|
||||||
|
if not title or not paragraph:
|
||||||
|
return
|
||||||
|
if isinstance(paragraph[0], nodes.paragraph):
|
||||||
|
paragraph = paragraph[0]
|
||||||
|
if all(isinstance(child, nodes.Text) for child in paragraph.children):
|
||||||
|
for child in paragraph.children:
|
||||||
|
title.append(nodes.Text(" \u2013 "))
|
||||||
|
title.append(child)
|
||||||
|
paragraph.parent.remove(paragraph)
|
||||||
|
|
||||||
|
def _enable_linking_to_nonclass_targets(self):
|
||||||
|
for desc in self.document.traverse(addnodes.desc):
|
||||||
|
for xref in desc.traverse(addnodes.pending_xref):
|
||||||
|
if xref.attributes.get("reftype") == "class":
|
||||||
|
xref.attributes.pop("refspecific", None)
|
||||||
|
|
||||||
|
def apply(self, **kwargs):
|
||||||
|
docname = self.env.docname
|
||||||
|
if docname.startswith(autoapi_root) and docname.endswith("/index"):
|
||||||
|
self._convert_first_paragraph_into_title()
|
||||||
|
self._enable_linking_to_nonclass_targets()
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.add_css_file("customstyle.css")
|
app.add_css_file("customstyle.css")
|
||||||
|
app.add_config_value('redirects_file', 'redirects', 'env')
|
||||||
|
app.connect('builder-inited', generate_redirects)
|
||||||
|
app.add_transform(CoreModuleTransform)
|
||||||
|
957
devices/ble_hci/common-hal/_bleio/Adapter.c
Normal file
957
devices/ble_hci/common-hal/_bleio/Adapter.c
Normal file
@ -0,0 +1,957 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "hci.h"
|
||||||
|
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "supervisor/shared/safe_mode.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "supervisor/usb.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
#include "shared-bindings/_bleio/Address.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
#include "shared-bindings/_bleio/ScanEntry.h"
|
||||||
|
#include "shared-bindings/time/__init__.h"
|
||||||
|
|
||||||
|
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||||
|
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
|
||||||
|
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME) * (RESOLUTION)) / 1000000)
|
||||||
|
// 0.625 msecs (625 usecs)
|
||||||
|
#define ADV_INTERVAL_UNIT_FLOAT_SECS (0.000625)
|
||||||
|
// Microseconds is the base unit. The macros above know that.
|
||||||
|
#define UNIT_0_625_MS (625)
|
||||||
|
#define UNIT_1_25_MS (1250)
|
||||||
|
#define UNIT_10_MS (10000)
|
||||||
|
|
||||||
|
#define MAX_ADVERTISEMENT_SIZE (31)
|
||||||
|
|
||||||
|
// TODO make this settable from Python.
|
||||||
|
#define DEFAULT_TX_POWER 0 // 0 dBm
|
||||||
|
#define MAX_ANONYMOUS_ADV_TIMEOUT_SECS (60*15)
|
||||||
|
#define MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS (180)
|
||||||
|
|
||||||
|
#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
|
||||||
|
#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
|
||||||
|
#define BLE_SLAVE_LATENCY 0
|
||||||
|
#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
|
||||||
|
|
||||||
|
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||||
|
|
||||||
|
STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||||
|
// Create Generic Access UUID, Service, and Characteristics.
|
||||||
|
|
||||||
|
// Generic Access Service setup.
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *generic_access_service_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
generic_access_service_uuid->base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(generic_access_service_uuid, 0x1800, NULL);
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *device_name_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
device_name_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(device_name_characteristic_uuid, 0x2A00, NULL);
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *appearance_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
appearance_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(appearance_characteristic_uuid, 0x2A01, NULL);
|
||||||
|
|
||||||
|
// Not implemented:
|
||||||
|
// Peripheral Preferred Connection Parameters
|
||||||
|
// Central Address Resolution
|
||||||
|
|
||||||
|
bleio_service_obj_t *generic_access_service = m_new_obj(bleio_service_obj_t);
|
||||||
|
generic_access_service->base.type = &bleio_service_type;
|
||||||
|
common_hal_bleio_service_construct(generic_access_service, generic_access_service_uuid, false);
|
||||||
|
|
||||||
|
adapter->device_name_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||||
|
adapter->device_name_characteristic->base.type = &bleio_characteristic_type;
|
||||||
|
|
||||||
|
char generic_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 'n', 'n', 'n', 'n' };
|
||||||
|
mp_buffer_info_t generic_name_bufinfo = {
|
||||||
|
.buf = generic_name,
|
||||||
|
.len = sizeof(generic_name),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Will be added to service by constructor.
|
||||||
|
common_hal_bleio_characteristic_construct(
|
||||||
|
adapter->device_name_characteristic,
|
||||||
|
generic_access_service,
|
||||||
|
BLE_GATT_HANDLE_INVALID,
|
||||||
|
device_name_characteristic_uuid,
|
||||||
|
CHAR_PROP_READ,
|
||||||
|
SECURITY_MODE_OPEN,
|
||||||
|
SECURITY_MODE_NO_ACCESS,
|
||||||
|
248, // max length, from Bluetooth spec
|
||||||
|
false, // not fixed length
|
||||||
|
&generic_name_bufinfo
|
||||||
|
);
|
||||||
|
|
||||||
|
uint16_t zero_16 = 0;
|
||||||
|
mp_buffer_info_t zero_16_value = {
|
||||||
|
.buf = &zero_16,
|
||||||
|
.len = sizeof(zero_16),
|
||||||
|
};
|
||||||
|
|
||||||
|
adapter->appearance_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||||
|
adapter->appearance_characteristic->base.type = &bleio_characteristic_type;
|
||||||
|
|
||||||
|
common_hal_bleio_characteristic_construct(
|
||||||
|
adapter->appearance_characteristic,
|
||||||
|
generic_access_service,
|
||||||
|
BLE_GATT_HANDLE_INVALID,
|
||||||
|
appearance_characteristic_uuid,
|
||||||
|
CHAR_PROP_READ,
|
||||||
|
SECURITY_MODE_OPEN,
|
||||||
|
SECURITY_MODE_NO_ACCESS,
|
||||||
|
2, // max length, from Bluetooth spec
|
||||||
|
true, // fixed length
|
||||||
|
&zero_16_value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generic Attribute Service setup.
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *generic_attribute_service_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
generic_attribute_service_uuid->base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(generic_attribute_service_uuid, 0x1801, NULL);
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *service_changed_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
service_changed_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(service_changed_characteristic_uuid, 0x2A05, NULL);
|
||||||
|
|
||||||
|
bleio_service_obj_t *generic_attribute_service = m_new_obj(bleio_service_obj_t);
|
||||||
|
generic_attribute_service->base.type = &bleio_service_type;
|
||||||
|
common_hal_bleio_service_construct(generic_attribute_service, generic_attribute_service_uuid, false);
|
||||||
|
|
||||||
|
adapter->service_changed_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||||
|
adapter->service_changed_characteristic->base.type = &bleio_characteristic_type;
|
||||||
|
|
||||||
|
uint32_t zero_32 = 0;
|
||||||
|
mp_buffer_info_t zero_32_value = {
|
||||||
|
.buf = &zero_32,
|
||||||
|
.len = sizeof(zero_32),
|
||||||
|
};
|
||||||
|
|
||||||
|
common_hal_bleio_characteristic_construct(
|
||||||
|
adapter->service_changed_characteristic,
|
||||||
|
generic_attribute_service,
|
||||||
|
BLE_GATT_HANDLE_INVALID,
|
||||||
|
service_changed_characteristic_uuid,
|
||||||
|
CHAR_PROP_INDICATE,
|
||||||
|
SECURITY_MODE_OPEN,
|
||||||
|
SECURITY_MODE_NO_ACCESS,
|
||||||
|
4, // max length, from Bluetooth spec
|
||||||
|
true, // fixed length
|
||||||
|
&zero_32_value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STATIC void check_enabled(bleio_adapter_obj_t *adapter) {
|
||||||
|
if (!common_hal_bleio_adapter_get_enabled(adapter)) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Adapter not enabled"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
||||||
|
// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in;
|
||||||
|
|
||||||
|
// // For debugging.
|
||||||
|
// // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||||
|
|
||||||
|
// switch (ble_evt->header.evt_id) {
|
||||||
|
// case BLE_GAP_EVT_CONNECTED: {
|
||||||
|
// // Find an empty connection. One must always be available because the SD has the same
|
||||||
|
// // total connection limit.
|
||||||
|
// bleio_connection_internal_t *connection;
|
||||||
|
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
// connection = &bleio_connections[i];
|
||||||
|
// if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Central has connected.
|
||||||
|
// ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected;
|
||||||
|
|
||||||
|
// connection->conn_handle = ble_evt->evt.gap_evt.conn_handle;
|
||||||
|
// connection->connection_obj = mp_const_none;
|
||||||
|
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
// connection->mtu = 0;
|
||||||
|
|
||||||
|
// ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection);
|
||||||
|
// self->connection_objs = NULL;
|
||||||
|
|
||||||
|
// // Save the current connection parameters.
|
||||||
|
// memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t));
|
||||||
|
|
||||||
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
|
// ble_gap_conn_params_t *cp = &connected->conn_params;
|
||||||
|
// mp_printf(&mp_plat_print, "conn params: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// // See if connection interval set by Central is out of range.
|
||||||
|
// // If so, negotiate our preferred range.
|
||||||
|
// ble_gap_conn_params_t conn_params;
|
||||||
|
// sd_ble_gap_ppcp_get(&conn_params);
|
||||||
|
// if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval ||
|
||||||
|
// conn_params.min_conn_interval > connected->conn_params.max_conn_interval) {
|
||||||
|
// sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
|
||||||
|
// }
|
||||||
|
// self->current_advertising_data = NULL;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case BLE_GAP_EVT_DISCONNECTED: {
|
||||||
|
// // Find the connection that was disconnected.
|
||||||
|
// bleio_connection_internal_t *connection;
|
||||||
|
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
// connection = &bleio_connections[i];
|
||||||
|
// if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ble_drv_remove_event_handler(connection_on_ble_evt, connection);
|
||||||
|
// connection->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||||
|
// connection->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
// if (connection->connection_obj != mp_const_none) {
|
||||||
|
// bleio_connection_obj_t* obj = connection->connection_obj;
|
||||||
|
// obj->connection = NULL;
|
||||||
|
// obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason;
|
||||||
|
// }
|
||||||
|
// self->connection_objs = NULL;
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_ADV_SET_TERMINATED:
|
||||||
|
// self->current_advertising_data = NULL;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// // For debugging.
|
||||||
|
// // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id);
|
||||||
|
// return false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// Get various values and limits set by the adapter.
|
||||||
|
// Set event mask.
|
||||||
|
STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
||||||
|
|
||||||
|
const size_t len = sizeof(default_ble_name);
|
||||||
|
|
||||||
|
bt_addr_t addr;
|
||||||
|
hci_check_error(hci_read_bd_addr(&addr));
|
||||||
|
|
||||||
|
default_ble_name[len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
|
||||||
|
default_ble_name[len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
|
||||||
|
default_ble_name[len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
|
||||||
|
default_ble_name[len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
|
||||||
|
self->name = mp_obj_new_str(default_ble_name, len);
|
||||||
|
|
||||||
|
// Get version information.
|
||||||
|
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
|
||||||
|
&self->manufacturer, &self->lmp_subversion) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not read HCI version"));
|
||||||
|
}
|
||||||
|
// Get supported features.
|
||||||
|
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not read BLE features"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled desired events.
|
||||||
|
// Most importantly, includes:
|
||||||
|
// BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61)
|
||||||
|
if (hci_set_event_mask(0x3FFFFFFFFFFFFFFF) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not set event mask"));
|
||||||
|
}
|
||||||
|
// The default events for LE are:
|
||||||
|
// BT_EVT_MASK_LE_CONN_COMPLETE, BT_EVT_MASK_LE_ADVERTISING_REPORT,
|
||||||
|
// BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE, BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE
|
||||||
|
// BT_EVT_MASK_LE_LTK_REQUEST.
|
||||||
|
// That's all we need right now, so we don't bother to set the LE event mask.
|
||||||
|
|
||||||
|
// Get ACL buffer info.
|
||||||
|
uint16_t le_max_len;
|
||||||
|
uint8_t le_max_num;
|
||||||
|
if (hci_le_read_buffer_size(&le_max_len, &le_max_num) == HCI_OK) {
|
||||||
|
self->max_acl_buffer_len = le_max_len;
|
||||||
|
self->max_acl_num_buffers = le_max_num;
|
||||||
|
} else {
|
||||||
|
// LE Read Buffer Size not available; use the general Read Buffer Size.
|
||||||
|
uint16_t acl_max_len;
|
||||||
|
uint8_t sco_max_len;
|
||||||
|
uint16_t acl_max_num;
|
||||||
|
uint16_t sco_max_num;
|
||||||
|
if (hci_read_buffer_size(&acl_max_len, &sco_max_len, &acl_max_num, &sco_max_num) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not read BLE buffer info"));
|
||||||
|
}
|
||||||
|
self->max_acl_buffer_len = acl_max_len;
|
||||||
|
self->max_acl_num_buffers = acl_max_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get max advertising length if extended advertising is supported.
|
||||||
|
if (BT_FEAT_LE_EXT_ADV(self->features)) {
|
||||||
|
uint16_t max_adv_data_len;
|
||||||
|
if (hci_le_read_maximum_advertising_data_length(&max_adv_data_len) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not get max advertising length"));
|
||||||
|
}
|
||||||
|
self->max_adv_data_len = max_adv_data_len;
|
||||||
|
} else {
|
||||||
|
self->max_adv_data_len = MAX_ADVERTISEMENT_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_construct_hci_uart(bleio_adapter_obj_t *self, busio_uart_obj_t *uart, digitalio_digitalinout_obj_t *rts, digitalio_digitalinout_obj_t *cts) {
|
||||||
|
self->allocated = true;
|
||||||
|
self->hci_uart = uart;
|
||||||
|
self->rts_digitalinout = rts;
|
||||||
|
self->cts_digitalinout = cts;
|
||||||
|
|
||||||
|
// Advertising-related fields are initialized by common_hal_bleio_adapter_set_enabled().
|
||||||
|
self->enabled = false;
|
||||||
|
|
||||||
|
common_hal_bleio_adapter_set_enabled(self, true);
|
||||||
|
bleio_adapter_hci_init(self);
|
||||||
|
common_hal_bleio_adapter_set_name(self, default_ble_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) {
|
||||||
|
const bool is_enabled = common_hal_bleio_adapter_get_enabled(self);
|
||||||
|
|
||||||
|
// Don't enable or disable twice
|
||||||
|
if (is_enabled == enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->enabled = enabled;
|
||||||
|
|
||||||
|
// We must poll for input from the HCI adapter.
|
||||||
|
// TODO Can we instead trigger an interrupt on UART input traffic?
|
||||||
|
if (enabled) {
|
||||||
|
supervisor_enable_tick();
|
||||||
|
} else {
|
||||||
|
supervisor_disable_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabling or disabling: stop any current activity; reset to known state.
|
||||||
|
hci_reset();
|
||||||
|
self->now_advertising = false;
|
||||||
|
self->extended_advertising = false;
|
||||||
|
self->circuitpython_advertising = false;
|
||||||
|
self->advertising_timeout_msecs = 0;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
// Reset list of known attributes.
|
||||||
|
// Indices into the list are handles. Handle 0x0000 designates an invalid handle,
|
||||||
|
// so store None there to skip it.
|
||||||
|
self->attributes = mp_obj_new_list(0, NULL);
|
||||||
|
bleio_adapter_add_attribute(self, mp_const_none);
|
||||||
|
add_generic_services(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
|
||||||
|
return self->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
bt_addr_t addr;
|
||||||
|
hci_check_error(hci_read_bd_addr(&addr));
|
||||||
|
|
||||||
|
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
|
||||||
|
address->base.type = &bleio_address_type;
|
||||||
|
|
||||||
|
common_hal_bleio_address_construct(address, addr.val, BT_ADDR_LE_PUBLIC);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) {
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
if (!mp_get_buffer(address->bytes, &bufinfo, MP_BUFFER_READ)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hci_le_set_random_address(bufinfo.buf) == HCI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
|
||||||
|
return self->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name) {
|
||||||
|
self->name = mp_obj_new_str(name, strlen(name));
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
mp_get_buffer_raise(self->name, &bufinfo, MP_BUFFER_READ);
|
||||||
|
bleio_characteristic_set_local_value(self->device_name_characteristic, &bufinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) {
|
||||||
|
// bleio_scanresults_obj_t *scan_results = (bleio_scanresults_obj_t*)scan_results_in;
|
||||||
|
|
||||||
|
// if (ble_evt->header.evt_id == BLE_GAP_EVT_TIMEOUT &&
|
||||||
|
// ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) {
|
||||||
|
// shared_module_bleio_scanresults_set_done(scan_results, true);
|
||||||
|
// ble_drv_remove_event_handler(scan_on_ble_evt, scan_results);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report;
|
||||||
|
|
||||||
|
// shared_module_bleio_scanresults_append(scan_results,
|
||||||
|
// supervisor_ticks_ms64(),
|
||||||
|
// report->type.connectable,
|
||||||
|
// report->type.scan_response,
|
||||||
|
// report->rssi,
|
||||||
|
// report->peer_addr.addr,
|
||||||
|
// report->peer_addr.addr_type,
|
||||||
|
// report->data.p_data,
|
||||||
|
// report->data.len);
|
||||||
|
|
||||||
|
// const uint32_t err_code = sd_ble_gap_scan_start(NULL, scan_results->common_hal_data);
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// // TODO: Pass the error into the scan results so it can throw an exception.
|
||||||
|
// scan_results->done = true;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) {
|
||||||
|
// TODO
|
||||||
|
mp_raise_NotImplementedError(NULL);
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
if (self->scan_results != NULL) {
|
||||||
|
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan."));
|
||||||
|
}
|
||||||
|
self->scan_results = NULL;
|
||||||
|
}
|
||||||
|
self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi);
|
||||||
|
|
||||||
|
// size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX;
|
||||||
|
// uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size, false);
|
||||||
|
// ble_data_t * sd_data = (ble_data_t *) raw_data;
|
||||||
|
// self->scan_results->common_hal_data = sd_data;
|
||||||
|
// sd_data->len = max_packet_size;
|
||||||
|
// sd_data->p_data = raw_data + sizeof(ble_data_t);
|
||||||
|
|
||||||
|
// ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results);
|
||||||
|
|
||||||
|
// uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS);
|
||||||
|
// if (timeout <= 0.0001) {
|
||||||
|
// nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ble_gap_scan_params_t scan_params = {
|
||||||
|
// .extended = extended,
|
||||||
|
// .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS),
|
||||||
|
// .timeout = nrf_timeout,
|
||||||
|
// .window = SEC_TO_UNITS(window, UNIT_0_625_MS),
|
||||||
|
// .scan_phys = BLE_GAP_PHY_1MBPS,
|
||||||
|
// .active = active
|
||||||
|
// };
|
||||||
|
// uint32_t err_code;
|
||||||
|
// vm_used_ble = true;
|
||||||
|
// err_code = sd_ble_gap_scan_start(&scan_params, sd_data);
|
||||||
|
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// self->scan_results = NULL;
|
||||||
|
// ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results);
|
||||||
|
// check_nrf_error(err_code);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(self->scan_results);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
|
||||||
|
// TODO
|
||||||
|
mp_raise_NotImplementedError(NULL);
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
// If not already scanning, no problem.
|
||||||
|
if (hci_le_set_scan_enable(BT_HCI_LE_SCAN_DISABLE, BT_HCI_LE_SCAN_FILTER_DUP_DISABLE) == HCI_OK) {
|
||||||
|
shared_module_bleio_scanresults_set_done(self->scan_results, true);
|
||||||
|
self->scan_results = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef struct {
|
||||||
|
// uint16_t conn_handle;
|
||||||
|
// volatile bool done;
|
||||||
|
// } connect_info_t;
|
||||||
|
|
||||||
|
// STATIC bool connect_on_ble_evt(ble_evt_t *ble_evt, void *info_in) {
|
||||||
|
// connect_info_t *info = (connect_info_t*)info_in;
|
||||||
|
|
||||||
|
// switch (ble_evt->header.evt_id) {
|
||||||
|
// case BLE_GAP_EVT_CONNECTED:
|
||||||
|
// info->conn_handle = ble_evt->evt.gap_evt.conn_handle;
|
||||||
|
// info->done = true;
|
||||||
|
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_TIMEOUT:
|
||||||
|
// // Handle will be invalid.
|
||||||
|
// info->done = true;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// // For debugging.
|
||||||
|
// // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
|
||||||
|
// return false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) {
|
||||||
|
// TODO
|
||||||
|
mp_raise_NotImplementedError(NULL);
|
||||||
|
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
// ble_gap_addr_t addr;
|
||||||
|
|
||||||
|
// addr.addr_type = address->type;
|
||||||
|
// mp_buffer_info_t address_buf_info;
|
||||||
|
// mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
|
||||||
|
// memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
|
||||||
|
|
||||||
|
// ble_gap_scan_params_t scan_params = {
|
||||||
|
// .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||||
|
// .window = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||||
|
// .scan_phys = BLE_GAP_PHY_1MBPS,
|
||||||
|
// // timeout of 0 means no timeout
|
||||||
|
// .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// ble_gap_conn_params_t conn_params = {
|
||||||
|
// .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS),
|
||||||
|
// .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS),
|
||||||
|
// .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS),
|
||||||
|
// .slave_latency = 0, // number of conn events
|
||||||
|
// };
|
||||||
|
|
||||||
|
// connect_info_t event_info;
|
||||||
|
// ble_drv_add_event_handler(connect_on_ble_evt, &event_info);
|
||||||
|
// event_info.done = false;
|
||||||
|
|
||||||
|
vm_used_ble = true;
|
||||||
|
// uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
|
||||||
|
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// ble_drv_remove_event_handler(connect_on_ble_evt, &event_info);
|
||||||
|
// check_nrf_error(err_code);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (!event_info.done) {
|
||||||
|
// RUN_BACKGROUND_TASKS;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ble_drv_remove_event_handler(connect_on_ble_evt, &event_info);
|
||||||
|
|
||||||
|
// uint16_t conn_handle = event_info.conn_handle;
|
||||||
|
// if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
|
// mp_raise_bleio_BluetoothError(translate("Failed to connect: timeout"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Negotiate for better PHY, larger MTU and data lengths since we are the central. These are
|
||||||
|
// // nice-to-haves so ignore any errors.
|
||||||
|
// ble_gap_phys_t const phys = {
|
||||||
|
// .rx_phys = BLE_GAP_PHY_AUTO,
|
||||||
|
// .tx_phys = BLE_GAP_PHY_AUTO,
|
||||||
|
// };
|
||||||
|
// sd_ble_gap_phy_update(conn_handle, &phys);
|
||||||
|
// sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX);
|
||||||
|
// sd_ble_gap_data_length_update(conn_handle, NULL, NULL);
|
||||||
|
|
||||||
|
// Make the connection object and return it.
|
||||||
|
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
// bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||||
|
// if (connection->conn_handle == conn_handle) {
|
||||||
|
// return bleio_connection_new_from_internal(connection);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error"));
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void check_data_fit(size_t data_len, bool connectable) {
|
||||||
|
if (data_len > MAX_ADVERTISEMENT_SIZE) {
|
||||||
|
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
||||||
|
// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in;
|
||||||
|
|
||||||
|
// switch (ble_evt->header.evt_id) {
|
||||||
|
// case BLE_GAP_EVT_ADV_SET_TERMINATED:
|
||||||
|
// common_hal_bleio_adapter_stop_advertising(self);
|
||||||
|
// ble_drv_remove_event_handler(advertising_on_ble_evt, self_in);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// // For debugging.
|
||||||
|
// // mp_printf(&mp_plat_print, "Unhandled advertising event: 0x%04x\n", ble_evt->header.evt_id);
|
||||||
|
// return false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
if (self->now_advertising) {
|
||||||
|
if (self->circuitpython_advertising) {
|
||||||
|
common_hal_bleio_adapter_stop_advertising(self);
|
||||||
|
} else {
|
||||||
|
// User-requested advertising.
|
||||||
|
// TODO allow multiple advertisements.
|
||||||
|
// Already advertising. Can't advertise twice.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peer address, which we don't use (no directed advertising).
|
||||||
|
bt_addr_le_t empty_addr = { 0 };
|
||||||
|
|
||||||
|
bool extended =
|
||||||
|
advertising_data_len > self->max_adv_data_len || scan_response_data_len > self->max_adv_data_len;
|
||||||
|
|
||||||
|
if (extended) {
|
||||||
|
if (!BT_FEAT_LE_EXT_ADV(self->features)) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Data length needs extended advertising, but this adapter does not support it"));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t props = 0;
|
||||||
|
if (connectable) {
|
||||||
|
props |= BT_HCI_LE_ADV_PROP_CONN;
|
||||||
|
}
|
||||||
|
if (scan_response_data_len > 0) {
|
||||||
|
props |= BT_HCI_LE_ADV_PROP_SCAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advertising interval.
|
||||||
|
uint32_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS);
|
||||||
|
|
||||||
|
hci_check_error(
|
||||||
|
hci_le_set_extended_advertising_parameters(
|
||||||
|
0, // handle
|
||||||
|
props, // adv properties
|
||||||
|
interval_units, // min interval
|
||||||
|
interval_units, // max interval
|
||||||
|
0b111, // channel map: channels 37, 38, 39
|
||||||
|
anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC,
|
||||||
|
&empty_addr, // peer_addr,
|
||||||
|
0x00, // filter policy: no filter
|
||||||
|
DEFAULT_TX_POWER,
|
||||||
|
BT_HCI_LE_EXT_SCAN_PHY_1M, // Secondary PHY to use
|
||||||
|
0x00, // AUX_ADV_IND shall be sent prior to next adv event
|
||||||
|
BT_HCI_LE_EXT_SCAN_PHY_1M, // Secondary PHY to use
|
||||||
|
0x00, // Advertising SID
|
||||||
|
0x00 // Scan req notify disable
|
||||||
|
));
|
||||||
|
|
||||||
|
// We can use the duration mechanism provided, instead of our own.
|
||||||
|
self->advertising_timeout_msecs = 0;
|
||||||
|
|
||||||
|
uint8_t handle[1] = { 0 };
|
||||||
|
uint16_t duration_10msec[1] = { timeout * 100 };
|
||||||
|
uint8_t max_ext_adv_evts[1] = { 0 };
|
||||||
|
hci_check_error(
|
||||||
|
hci_le_set_extended_advertising_enable(
|
||||||
|
BT_HCI_LE_ADV_ENABLE,
|
||||||
|
1, // one advertising set.
|
||||||
|
handle,
|
||||||
|
duration_10msec,
|
||||||
|
max_ext_adv_evts
|
||||||
|
));
|
||||||
|
|
||||||
|
self->extended_advertising = true;
|
||||||
|
} else {
|
||||||
|
// Legacy advertising (not extended).
|
||||||
|
|
||||||
|
uint8_t adv_type;
|
||||||
|
if (connectable) {
|
||||||
|
// Connectable, scannable, undirected.
|
||||||
|
adv_type = BT_HCI_ADV_IND;
|
||||||
|
} else if (scan_response_data_len > 0) {
|
||||||
|
// Unconnectable, scannable, undirected.
|
||||||
|
adv_type = BT_HCI_ADV_SCAN_IND;
|
||||||
|
} else {
|
||||||
|
// Unconnectable, unscannable, undirected.
|
||||||
|
adv_type = BT_HCI_ADV_NONCONN_IND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advertising interval.
|
||||||
|
uint16_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS);
|
||||||
|
|
||||||
|
hci_check_error(
|
||||||
|
hci_le_set_advertising_parameters(
|
||||||
|
interval_units, // min interval
|
||||||
|
interval_units, // max interval
|
||||||
|
adv_type,
|
||||||
|
anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC,
|
||||||
|
&empty_addr,
|
||||||
|
0b111, // channel map: channels 37, 38, 39
|
||||||
|
0x00 // filter policy: no filter
|
||||||
|
));
|
||||||
|
|
||||||
|
// The HCI commands expect MAX_ADVERTISEMENT_SIZE (31)octets,
|
||||||
|
// even though the actual data length may be shorter.
|
||||||
|
uint8_t full_data[MAX_ADVERTISEMENT_SIZE] = { 0 };
|
||||||
|
memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len));
|
||||||
|
hci_check_error(hci_le_set_advertising_data(advertising_data_len, full_data));
|
||||||
|
memset(full_data, 0, sizeof(full_data));
|
||||||
|
if (scan_response_data_len > 0) {
|
||||||
|
memcpy(full_data, scan_response_data, MIN(sizeof(full_data), scan_response_data_len));
|
||||||
|
hci_check_error(hci_le_set_scan_response_data(scan_response_data_len, full_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// No duration mechanism is provided for legacy advertising, so we need to do our own.
|
||||||
|
self->advertising_timeout_msecs = timeout * 1000;
|
||||||
|
self->advertising_start_ticks = supervisor_ticks_ms64();
|
||||||
|
|
||||||
|
// Start advertising.
|
||||||
|
hci_check_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_ENABLE));
|
||||||
|
self->extended_advertising = false;
|
||||||
|
} // end legacy advertising setup
|
||||||
|
|
||||||
|
vm_used_ble = true;
|
||||||
|
self->now_advertising = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
// interval value has already been validated.
|
||||||
|
|
||||||
|
check_data_fit(advertising_data_bufinfo->len, connectable);
|
||||||
|
check_data_fit(scan_response_data_bufinfo->len, connectable);
|
||||||
|
|
||||||
|
if (advertising_data_bufinfo->len > MAX_ADVERTISEMENT_SIZE && scan_response_data_bufinfo->len > 0) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anonymous mode requires a timeout so that we don't continue to broadcast
|
||||||
|
// the same data while cycling the MAC address -- otherwise, what's the
|
||||||
|
// point of randomizing the MAC address?
|
||||||
|
if (timeout == 0 && anonymous) {
|
||||||
|
timeout = MAX_ANONYMOUS_ADV_TIMEOUT_SECS;
|
||||||
|
} else {
|
||||||
|
if (timeout > MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"),
|
||||||
|
MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t result =_common_hal_bleio_adapter_start_advertising(
|
||||||
|
self, connectable, anonymous, timeout, interval,
|
||||||
|
advertising_data_bufinfo->buf,
|
||||||
|
advertising_data_bufinfo->len,
|
||||||
|
scan_response_data_bufinfo->buf,
|
||||||
|
scan_response_data_bufinfo->len);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Already advertising"));
|
||||||
|
}
|
||||||
|
self->circuitpython_advertising = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
self->now_advertising = false;
|
||||||
|
self->extended_advertising = false;
|
||||||
|
self->circuitpython_advertising = false;
|
||||||
|
|
||||||
|
int result = hci_le_set_advertising_enable(BT_HCI_LE_ADV_DISABLE);
|
||||||
|
// OK if we're already stopped. There seems to be an ESP32 HCI bug:
|
||||||
|
// If advertising is already off, then LE_SET_ADV_ENABLE does not return a response.
|
||||||
|
if (result != HCI_RESPONSE_TIMEOUT) {
|
||||||
|
hci_check_error(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO startup CircuitPython advertising again.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that something stopped advertising, such as a connection happening.
|
||||||
|
//Don't ask the adapter to stop.
|
||||||
|
void bleio_adapter_advertising_was_stopped(bleio_adapter_obj_t *self) {
|
||||||
|
self->now_advertising = false;
|
||||||
|
self->extended_advertising = false;
|
||||||
|
self->circuitpython_advertising = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
return self->now_advertising;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||||
|
if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
if (self->connection_objs != NULL) {
|
||||||
|
return self->connection_objs;
|
||||||
|
}
|
||||||
|
size_t total_connected = 0;
|
||||||
|
mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||||
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||||
|
if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
if (connection->connection_obj == mp_const_none) {
|
||||||
|
connection->connection_obj = bleio_connection_new_from_internal(connection);
|
||||||
|
}
|
||||||
|
items[total_connected] = connection->connection_obj;
|
||||||
|
total_connected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self->connection_objs = mp_obj_new_tuple(total_connected, items);
|
||||||
|
return self->connection_objs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
|
||||||
|
// TODO
|
||||||
|
mp_raise_NotImplementedError(NULL);
|
||||||
|
check_enabled(self);
|
||||||
|
|
||||||
|
//FIX bonding_erase_storage();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute) {
|
||||||
|
check_enabled(adapter);
|
||||||
|
|
||||||
|
// The handle is the index of this attribute in the attributes list.
|
||||||
|
uint16_t handle = (uint16_t) adapter->attributes->len;
|
||||||
|
mp_obj_list_append(adapter->attributes, attribute);
|
||||||
|
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
|
||||||
|
adapter->last_added_service_handle = handle;
|
||||||
|
}
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||||
|
adapter->last_added_characteristic_handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle) {
|
||||||
|
check_enabled(adapter);
|
||||||
|
|
||||||
|
if (handle == 0 || handle >= adapter->attributes->len) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
return adapter->attributes->items[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
|
||||||
|
check_enabled(adapter);
|
||||||
|
|
||||||
|
return adapter->attributes->len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {
|
||||||
|
gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t));
|
||||||
|
gc_collect_root((void**)bleio_connections, sizeof(bleio_connections) / sizeof(size_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_adapter_reset(bleio_adapter_obj_t* adapter) {
|
||||||
|
|
||||||
|
if (!common_hal_bleio_adapter_get_enabled(adapter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapter will be reset.
|
||||||
|
common_hal_bleio_adapter_set_enabled(adapter, false);
|
||||||
|
|
||||||
|
adapter->connection_objs = NULL;
|
||||||
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||||
|
// Disconnect all connections with Python state cleanly. Keep any supervisor-only connections.
|
||||||
|
if (connection->connection_obj != mp_const_none &&
|
||||||
|
connection->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
common_hal_bleio_connection_disconnect(connection);
|
||||||
|
}
|
||||||
|
connection->connection_obj = mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_adapter_background(bleio_adapter_obj_t* adapter) {
|
||||||
|
if (!common_hal_bleio_adapter_get_enabled(adapter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adapter->advertising_timeout_msecs > 0 &&
|
||||||
|
supervisor_ticks_ms64() - adapter->advertising_start_ticks > adapter->advertising_timeout_msecs) {
|
||||||
|
adapter->advertising_timeout_msecs = 0;
|
||||||
|
common_hal_bleio_adapter_stop_advertising(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t result = hci_poll_for_incoming_pkt();
|
||||||
|
if (result != HCI_OK) {
|
||||||
|
mp_printf(&mp_plat_print, "bad hci_poll_for_incoming_pkt() result in background: %d\n", result);
|
||||||
|
}
|
||||||
|
}
|
99
devices/ble_hci/common-hal/_bleio/Adapter.h
Normal file
99
devices/ble_hci/common-hal/_bleio/Adapter.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/objtuple.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
#include "shared-bindings/_bleio/ScanResults.h"
|
||||||
|
#include "shared-bindings/busio/UART.h"
|
||||||
|
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||||
|
|
||||||
|
#ifndef BLEIO_TOTAL_CONNECTION_COUNT
|
||||||
|
#define BLEIO_TOTAL_CONNECTION_COUNT 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||||
|
|
||||||
|
typedef struct _bleio_adapter_obj_t {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
bleio_scanresults_obj_t *scan_results;
|
||||||
|
mp_obj_t name;
|
||||||
|
mp_obj_tuple_t *connection_objs;
|
||||||
|
busio_uart_obj_t* hci_uart;
|
||||||
|
digitalio_digitalinout_obj_t *rts_digitalinout;
|
||||||
|
digitalio_digitalinout_obj_t *cts_digitalinout;
|
||||||
|
bool allocated; // True when in use.
|
||||||
|
bool now_advertising;
|
||||||
|
bool extended_advertising;
|
||||||
|
bool circuitpython_advertising;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
// HCI adapter version info.
|
||||||
|
uint8_t hci_version;
|
||||||
|
uint8_t lmp_version;
|
||||||
|
uint16_t hci_revision;
|
||||||
|
uint16_t manufacturer;
|
||||||
|
uint16_t lmp_subversion;
|
||||||
|
|
||||||
|
// Used to monitor advertising timeout for legacy avertising.
|
||||||
|
uint64_t advertising_start_ticks;
|
||||||
|
uint64_t advertising_timeout_msecs; // If zero, do not check.
|
||||||
|
|
||||||
|
// Generic services characteristics.
|
||||||
|
bleio_characteristic_obj_t *device_name_characteristic;
|
||||||
|
bleio_characteristic_obj_t *appearance_characteristic;
|
||||||
|
bleio_characteristic_obj_t * service_changed_characteristic;
|
||||||
|
|
||||||
|
uint16_t max_acl_buffer_len;
|
||||||
|
uint16_t max_acl_num_buffers;
|
||||||
|
uint16_t max_adv_data_len;
|
||||||
|
uint8_t features[8]; // Supported BLE features.
|
||||||
|
|
||||||
|
// All the local attributes for this device. The index into the list
|
||||||
|
// corresponds to the handle.
|
||||||
|
mp_obj_list_t *attributes;
|
||||||
|
// Handle for last added service. Characteristics can only be added immediately after
|
||||||
|
// the service they belong to. This vets that.
|
||||||
|
uint16_t last_added_service_handle;
|
||||||
|
uint16_t last_added_characteristic_handle;
|
||||||
|
} bleio_adapter_obj_t;
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute);
|
||||||
|
void bleio_adapter_advertising_was_stopped(bleio_adapter_obj_t *self);
|
||||||
|
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle);
|
||||||
|
uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter);
|
||||||
|
void bleio_adapter_background(bleio_adapter_obj_t* adapter);
|
||||||
|
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter);
|
||||||
|
void bleio_adapter_reset(bleio_adapter_obj_t* adapter);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H
|
49
devices/ble_hci/common-hal/_bleio/Attribute.c
Normal file
49
devices/ble_hci/common-hal/_bleio/Attribute.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/Attribute.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute) {
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||||
|
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute);
|
||||||
|
return characteristic->uuid;
|
||||||
|
}
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) {
|
||||||
|
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute);
|
||||||
|
return descriptor->uuid;
|
||||||
|
}
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
|
||||||
|
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute);
|
||||||
|
return service->uuid;
|
||||||
|
}
|
||||||
|
mp_raise_RuntimeError(translate("Invalid BLE attribute"));
|
||||||
|
}
|
35
devices/ble_hci/common-hal/_bleio/Attribute.h
Normal file
35
devices/ble_hci/common-hal/_bleio/Attribute.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H
|
||||||
|
|
||||||
|
#include "shared-module/_bleio/Attribute.h"
|
||||||
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H
|
228
devices/ble_hci/common-hal/_bleio/Characteristic.c
Normal file
228
devices/ble_hci/common-hal/_bleio/Characteristic.c
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
|
||||||
|
#include "common-hal/_bleio/Adapter.h"
|
||||||
|
#include "common-hal/_bleio/att.h"
|
||||||
|
|
||||||
|
#define CCCD_NOTIFY 0x1
|
||||||
|
#define CCCD_INDICATE 0x2
|
||||||
|
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
|
self->service = service;
|
||||||
|
self->uuid = uuid;
|
||||||
|
self->decl_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
|
self->props = props;
|
||||||
|
self->read_perm = read_perm;
|
||||||
|
self->write_perm = write_perm;
|
||||||
|
self->descriptor_list = mp_obj_new_list(0, NULL);
|
||||||
|
self->observer = mp_const_none;
|
||||||
|
self->user_desc = NULL;
|
||||||
|
self->cccd = NULL;
|
||||||
|
self->sccd = NULL;
|
||||||
|
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
|
const mp_int_t max_length_max = 512;
|
||||||
|
if (max_length < 0 || max_length > max_length_max) {
|
||||||
|
mp_raise_ValueError(translate("max_length must be <= 512"));
|
||||||
|
}
|
||||||
|
self->max_length = max_length;
|
||||||
|
self->fixed_length = fixed_length;
|
||||||
|
|
||||||
|
if (service->is_remote) {
|
||||||
|
self->handle = handle;
|
||||||
|
} else {
|
||||||
|
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
|
||||||
|
return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
|
||||||
|
return self->service;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) {
|
||||||
|
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||||
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
|
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
|
//FIX read remote chars
|
||||||
|
//uint8_t rsp[MAX(len, 512)];
|
||||||
|
//FIX improve att_read_req to write into our requested buffer.
|
||||||
|
// return att_read_req(conn_handle, self->handle, rsp);
|
||||||
|
return 0; //FIX
|
||||||
|
} else {
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const size_t actual_length = MIN(len, bufinfo.len);
|
||||||
|
memcpy(buf, bufinfo.buf, actual_length);
|
||||||
|
return actual_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
|
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||||
|
mp_raise_ValueError(translate("Value length != required fixed length"));
|
||||||
|
}
|
||||||
|
if (bufinfo->len > self->max_length) {
|
||||||
|
mp_raise_ValueError(translate("Value length > max_length"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||||
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
|
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
|
if (self->props & CHAR_PROP_WRITE) {
|
||||||
|
//FIX writing remote chars
|
||||||
|
//uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||||
|
//att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp);
|
||||||
|
} else if (self->props & CHAR_PROP_WRITE_NO_RESPONSE) {
|
||||||
|
//att_write_cmd(conn_handle, self->handle, bufinfo->buff, bufinfo->len);
|
||||||
|
} else {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Characteristic not writable"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Always write the value locally even if no connections are active.
|
||||||
|
bleio_characteristic_set_local_value(self, bufinfo);
|
||||||
|
// Notify or indicate all active connections.
|
||||||
|
|
||||||
|
uint16_t cccd_value = 0;
|
||||||
|
mp_buffer_info_t cccd_bufinfo = {
|
||||||
|
.buf = &cccd_value,
|
||||||
|
.len = sizeof(cccd_value),
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool notify = self->props & CHAR_PROP_NOTIFY;
|
||||||
|
const bool indicate = self->props & CHAR_PROP_INDICATE;
|
||||||
|
// Read the CCCD value, if there is one.
|
||||||
|
if ((notify | indicate) && self->cccd != NULL) {
|
||||||
|
common_hal_bleio_descriptor_get_value(self->cccd, cccd_bufinfo.buf, cccd_bufinfo.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's possible that both notify and indicate are set.
|
||||||
|
if (notify && (cccd_value & CCCD_NOTIFY)) {
|
||||||
|
att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
|
}
|
||||||
|
if (indicate && (cccd_value & CCCD_INDICATE)) {
|
||||||
|
att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
|
||||||
|
return self->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) {
|
||||||
|
return self->props;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
||||||
|
if (self->handle != common_hal_bleio_adapter_obj.last_added_characteristic_handle) {
|
||||||
|
mp_raise_bleio_BluetoothError(
|
||||||
|
translate("Descriptor can only be added to most recently added characteristic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor));
|
||||||
|
// Include this descriptor in the service handle's range.
|
||||||
|
self->service->end_handle = descriptor->handle;
|
||||||
|
|
||||||
|
mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list),
|
||||||
|
MP_OBJ_FROM_PTR(descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
||||||
|
if (self->cccd == NULL) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
|
mp_raise_bleio_RoleError(translate("Can't set CCCD on local Characteristic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
|
common_hal_bleio_check_connected(conn_handle);
|
||||||
|
|
||||||
|
uint16_t cccd_value =
|
||||||
|
(notify ? CCCD_NOTIFY : 0) |
|
||||||
|
(indicate ? CCCD_INDICATE : 0);
|
||||||
|
|
||||||
|
//FIX do remote
|
||||||
|
(void) cccd_value;
|
||||||
|
// uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||||
|
// if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) {
|
||||||
|
// mp_raise_bleio_BluetoothError(translate("Could not write CCCD"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
|
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bufinfo->len > self->max_length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||||
|
|
||||||
|
if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) {
|
||||||
|
bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||||
|
} else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) {
|
||||||
|
bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) {
|
||||||
|
self->observer = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) {
|
||||||
|
self->observer = mp_const_none;
|
||||||
|
}
|
63
devices/ble_hci/common-hal/_bleio/Characteristic.h
Normal file
63
devices/ble_hci/common-hal/_bleio/Characteristic.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/Attribute.h"
|
||||||
|
#include "common-hal/_bleio/Descriptor.h"
|
||||||
|
#include "shared-module/_bleio/Characteristic.h"
|
||||||
|
#include "common-hal/_bleio/Service.h"
|
||||||
|
#include "common-hal/_bleio/UUID.h"
|
||||||
|
|
||||||
|
typedef struct _bleio_characteristic_obj {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// Will be MP_OBJ_NULL before being assigned to a Service.
|
||||||
|
bleio_service_obj_t *service;
|
||||||
|
bleio_uuid_obj_t *uuid;
|
||||||
|
mp_obj_t value;
|
||||||
|
mp_obj_t observer;
|
||||||
|
mp_obj_list_t *descriptor_list;
|
||||||
|
uint16_t max_length;
|
||||||
|
bool fixed_length;
|
||||||
|
uint16_t decl_handle;
|
||||||
|
uint16_t handle; // Should be decl_handle+1.
|
||||||
|
bleio_characteristic_properties_t props;
|
||||||
|
bleio_attribute_security_mode_t read_perm;
|
||||||
|
bleio_attribute_security_mode_t write_perm;
|
||||||
|
bleio_descriptor_obj_t *descriptor_linked_list;
|
||||||
|
bleio_descriptor_obj_t *user_desc;
|
||||||
|
bleio_descriptor_obj_t *cccd;
|
||||||
|
bleio_descriptor_obj_t *sccd;
|
||||||
|
} bleio_characteristic_obj_t;
|
||||||
|
|
||||||
|
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
|
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer);
|
||||||
|
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H
|
104
devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c
Normal file
104
devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "lib/utils/interrupt_char.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
||||||
|
|
||||||
|
// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped.
|
||||||
|
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||||
|
ringbuf_put_n(&self->ringbuf, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
|
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assumes that timeout and buffer_size have been validated before call.
|
||||||
|
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
|
||||||
|
bleio_characteristic_obj_t *characteristic,
|
||||||
|
mp_float_t timeout,
|
||||||
|
size_t buffer_size) {
|
||||||
|
|
||||||
|
self->characteristic = characteristic;
|
||||||
|
self->timeout_ms = timeout * 1000;
|
||||||
|
// This is a macro.
|
||||||
|
// true means long-lived, so it won't be moved.
|
||||||
|
ringbuf_alloc(&self->ringbuf, buffer_size, true);
|
||||||
|
|
||||||
|
bleio_characteristic_set_observer(characteristic, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
||||||
|
uint64_t start_ticks = supervisor_ticks_ms64();
|
||||||
|
|
||||||
|
// Wait for all bytes received or timeout
|
||||||
|
while ( (ringbuf_num_filled(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
// Allow user to break out of a timeout with a KeyboardInterrupt.
|
||||||
|
if ( mp_hal_is_interrupted() ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);
|
||||||
|
return num_bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
|
||||||
|
uint16_t count = ringbuf_num_filled(&self->ringbuf);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
|
||||||
|
ringbuf_clear(&self->ringbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
|
||||||
|
return self->characteristic == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
|
||||||
|
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
|
||||||
|
bleio_characteristic_clear_observer(self->characteristic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) {
|
||||||
|
return self->characteristic != NULL &&
|
||||||
|
self->characteristic->service != NULL &&
|
||||||
|
(!self->characteristic->service->is_remote ||
|
||||||
|
(self->characteristic->service->connection != MP_OBJ_NULL &&
|
||||||
|
common_hal_bleio_connection_get_connected(self->characteristic->service->connection)));
|
||||||
|
}
|
43
devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h
Normal file
43
devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H
|
||||||
|
|
||||||
|
#include "py/ringbuf.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
bleio_characteristic_obj_t *characteristic;
|
||||||
|
uint32_t timeout_ms;
|
||||||
|
// Ring buffer storing consecutive incoming values.
|
||||||
|
ringbuf_t ringbuf;
|
||||||
|
} bleio_characteristic_buffer_obj_t;
|
||||||
|
|
||||||
|
void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H
|
772
devices/ble_hci/common-hal/_bleio/Connection.c
Normal file
772
devices/ble_hci/common-hal/_bleio/Connection.c
Normal file
@ -0,0 +1,772 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
|
||||||
|
#include "att.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "lib/utils/interrupt_char.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/objlist.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
|
#include "py/qstr.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
#include "shared-bindings/_bleio/Attribute.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
|
#define BLE_ADV_LENGTH_FIELD_SIZE 1
|
||||||
|
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
|
||||||
|
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
|
||||||
|
|
||||||
|
// static const ble_gap_sec_params_t pairing_sec_params = {
|
||||||
|
// .bond = 1,
|
||||||
|
// .mitm = 0,
|
||||||
|
// .lesc = 0,
|
||||||
|
// .keypress = 0,
|
||||||
|
// .oob = 0,
|
||||||
|
// .io_caps = BLE_GAP_IO_CAPS_NONE,
|
||||||
|
// .min_key_size = 7,
|
||||||
|
// .max_key_size = 16,
|
||||||
|
// .kdist_own = { .enc = 1, .id = 1},
|
||||||
|
// .kdist_peer = { .enc = 1, .id = 1},
|
||||||
|
// };
|
||||||
|
|
||||||
|
#define CONNECTION_DEBUG (1)
|
||||||
|
#if CONNECTION_DEBUG
|
||||||
|
#define CONNECTION_DEBUG_PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define CONNECTION_DEBUG_PRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static volatile bool m_discovery_in_process;
|
||||||
|
static volatile bool m_discovery_successful;
|
||||||
|
|
||||||
|
//FIX static bleio_service_obj_t *m_char_discovery_service;
|
||||||
|
//FIX static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
|
||||||
|
|
||||||
|
// bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
||||||
|
// bleio_connection_internal_t *self = (bleio_connection_internal_t*)self_in;
|
||||||
|
|
||||||
|
// if (BLE_GAP_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GAP_EVT_LAST &&
|
||||||
|
// ble_evt->evt.gap_evt.conn_handle != self->conn_handle) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if (BLE_GATTS_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GATTS_EVT_LAST &&
|
||||||
|
// ble_evt->evt.gatts_evt.conn_handle != self->conn_handle) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch (ble_evt->header.evt_id) {
|
||||||
|
// case BLE_GAP_EVT_DISCONNECTED:
|
||||||
|
// // Adapter.c does the work for this event.
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
|
||||||
|
// ble_gap_phys_t const phys = {
|
||||||
|
// .rx_phys = BLE_GAP_PHY_AUTO,
|
||||||
|
// .tx_phys = BLE_GAP_PHY_AUTO,
|
||||||
|
// };
|
||||||
|
// sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_PHY_UPDATE: { // 0x22
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
|
||||||
|
// // SoftDevice will respond to a length update request.
|
||||||
|
// sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_DATA_LENGTH_UPDATE: { // 0x24
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
|
||||||
|
// ble_gatts_evt_exchange_mtu_request_t *request =
|
||||||
|
// &ble_evt->evt.gatts_evt.params.exchange_mtu_request;
|
||||||
|
|
||||||
|
// uint16_t new_mtu = BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||||
|
// if (request->client_rx_mtu < new_mtu) {
|
||||||
|
// new_mtu = request->client_rx_mtu;
|
||||||
|
// }
|
||||||
|
// if (new_mtu < BLE_GATT_ATT_MTU_DEFAULT) {
|
||||||
|
// new_mtu = BLE_GATT_ATT_MTU_DEFAULT;
|
||||||
|
// }
|
||||||
|
// if (self->mtu > 0) {
|
||||||
|
// new_mtu = self->mtu;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// self->mtu = new_mtu;
|
||||||
|
// sd_ble_gatts_exchange_mtu_reply(self->conn_handle, new_mtu);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: {
|
||||||
|
// ble_gattc_evt_exchange_mtu_rsp_t *response =
|
||||||
|
// &ble_evt->evt.gattc_evt.params.exchange_mtu_rsp;
|
||||||
|
|
||||||
|
// self->mtu = response->server_rx_mtu;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GATTS_EVT_WRITE:
|
||||||
|
// // A client wrote a value.
|
||||||
|
// // If we are bonded and it's a CCCD (UUID 0x2902), store the CCCD value.
|
||||||
|
// if (self->conn_handle != BLE_CONN_HANDLE_INVALID &&
|
||||||
|
// self->pair_status == PAIR_PAIRED &&
|
||||||
|
// ble_evt->evt.gatts_evt.params.write.uuid.type == BLE_UUID_TYPE_BLE &&
|
||||||
|
// ble_evt->evt.gatts_evt.params.write.uuid.uuid == 0x2902) {
|
||||||
|
// //
|
||||||
|
// // Save sys_attr data (CCCD state) in bonding area at
|
||||||
|
// // next opportunity, but also remember time of this
|
||||||
|
// // request, so we can consolidate closely-spaced requests.
|
||||||
|
// self->do_bond_cccds = true;
|
||||||
|
// self->do_bond_cccds_request_time = supervisor_ticks_ms64();
|
||||||
|
// }
|
||||||
|
// // Return false so other handlers get this event as well.
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// case BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||||
|
// sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
|
// // Use read authorization to snoop on all reads when doing verbose debugging.
|
||||||
|
// case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: {
|
||||||
|
|
||||||
|
// ble_gatts_evt_rw_authorize_request_t *request =
|
||||||
|
// &ble_evt->evt.gatts_evt.params.authorize_request;
|
||||||
|
|
||||||
|
// mp_printf(&mp_plat_print, "Read %x offset %d ", request->request.read.handle, request->request.read.offset);
|
||||||
|
// uint8_t value_bytes[22];
|
||||||
|
// ble_gatts_value_t value;
|
||||||
|
// value.offset = request->request.read.offset;
|
||||||
|
// value.len = 22;
|
||||||
|
// value.p_value = value_bytes;
|
||||||
|
|
||||||
|
// sd_ble_gatts_value_get(self->conn_handle, request->request.read.handle, &value);
|
||||||
|
// size_t len = value.len;
|
||||||
|
// if (len > 22) {
|
||||||
|
// len = 22;
|
||||||
|
// }
|
||||||
|
// for (uint8_t i = 0; i < len; i++) {
|
||||||
|
// mp_printf(&mp_plat_print, " %02x", value_bytes[i]);
|
||||||
|
// }
|
||||||
|
// mp_printf(&mp_plat_print, "\n");
|
||||||
|
// ble_gatts_rw_authorize_reply_params_t reply;
|
||||||
|
// reply.type = request->type;
|
||||||
|
// reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
|
||||||
|
// reply.params.read.update = false;
|
||||||
|
// reply.params.read.offset = request->request.read.offset;
|
||||||
|
// sd_ble_gatts_rw_authorize_reply(self->conn_handle, &reply);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// case BLE_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55
|
||||||
|
// break;
|
||||||
|
// case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
|
||||||
|
// self->conn_params_updating = true;
|
||||||
|
// ble_gap_evt_conn_param_update_request_t *request =
|
||||||
|
// &ble_evt->evt.gap_evt.params.conn_param_update_request;
|
||||||
|
// sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case BLE_GAP_EVT_CONN_PARAM_UPDATE: { // 0x12
|
||||||
|
// ble_gap_evt_conn_param_update_t *result =
|
||||||
|
// &ble_evt->evt.gap_evt.params.conn_param_update;
|
||||||
|
|
||||||
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
|
// ble_gap_conn_params_t *cp = &ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
|
||||||
|
// mp_printf(&mp_plat_print, "conn params updated: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// memcpy(&self->conn_params, &result->conn_params, sizeof(ble_gap_conn_params_t));
|
||||||
|
// self->conn_params_updating = false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case BLE_GAP_EVT_SEC_PARAMS_REQUEST: {
|
||||||
|
// // First time pairing.
|
||||||
|
// // 1. Either we or peer initiate the process
|
||||||
|
// // 2. Peer asks for security parameters using BLE_GAP_EVT_SEC_PARAMS_REQUEST.
|
||||||
|
// // 3. Pair Key exchange ("just works" implemented now; TODO: out-of-band key pairing)
|
||||||
|
// // 4. Connection is secured: BLE_GAP_EVT_CONN_SEC_UPDATE
|
||||||
|
// // 5. Long-term Keys exchanged: BLE_GAP_EVT_AUTH_STATUS
|
||||||
|
|
||||||
|
// bonding_clear_keys(&self->bonding_keys);
|
||||||
|
// self->ediv = EDIV_INVALID;
|
||||||
|
// ble_gap_sec_keyset_t keyset = {
|
||||||
|
// .keys_own = {
|
||||||
|
// .p_enc_key = &self->bonding_keys.own_enc,
|
||||||
|
// .p_id_key = NULL,
|
||||||
|
// .p_sign_key = NULL,
|
||||||
|
// .p_pk = NULL
|
||||||
|
// },
|
||||||
|
|
||||||
|
// .keys_peer = {
|
||||||
|
// .p_enc_key = &self->bonding_keys.peer_enc,
|
||||||
|
// .p_id_key = &self->bonding_keys.peer_id,
|
||||||
|
// .p_sign_key = NULL,
|
||||||
|
// .p_pk = NULL
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS,
|
||||||
|
// self->is_central ? NULL : &pairing_sec_params,
|
||||||
|
// &keyset);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
|
||||||
|
// // TODO for LESC pairing:
|
||||||
|
// // sd_ble_gap_lesc_dhkey_reply(...);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_AUTH_STATUS: { // 0x19
|
||||||
|
// // Key exchange completed.
|
||||||
|
// ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status;
|
||||||
|
// self->sec_status = status->auth_status;
|
||||||
|
// if (status->auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
||||||
|
// self->ediv = self->bonding_keys.own_enc.master_id.ediv;
|
||||||
|
// self->pair_status = PAIR_PAIRED;
|
||||||
|
// // Save keys in bonding area at next opportunity.
|
||||||
|
// self->do_bond_keys = true;
|
||||||
|
// } else {
|
||||||
|
// // Inform busy-waiter pairing has failed.
|
||||||
|
// self->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_SEC_INFO_REQUEST: { // 0x14
|
||||||
|
// // Peer asks for the stored keys.
|
||||||
|
// // - load key and return if bonded previously.
|
||||||
|
// // - Else return NULL --> Initiate key exchange
|
||||||
|
// ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request;
|
||||||
|
// (void) sec_info_request;
|
||||||
|
// if ( bonding_load_keys(self->is_central, sec_info_request->master_id.ediv, &self->bonding_keys) ) {
|
||||||
|
// sd_ble_gap_sec_info_reply(
|
||||||
|
// self->conn_handle,
|
||||||
|
// &self->bonding_keys.own_enc.enc_info,
|
||||||
|
// &self->bonding_keys.peer_id.id_info,
|
||||||
|
// NULL);
|
||||||
|
// self->ediv = self->bonding_keys.own_enc.master_id.ediv;
|
||||||
|
// } else {
|
||||||
|
// // We don't have stored keys. Ask for keys.
|
||||||
|
// sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case BLE_GAP_EVT_CONN_SEC_UPDATE: { // 0x1a
|
||||||
|
// // We get this both on first-time pairing and on subsequent pairings using stored keys.
|
||||||
|
// ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec;
|
||||||
|
// if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) {
|
||||||
|
// // Security setup did not succeed:
|
||||||
|
// // mode 0, level 0 means no access
|
||||||
|
// // mode 1, level 1 means open link
|
||||||
|
// // mode >=1 and/or level >=1 means encryption is set up
|
||||||
|
// self->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
// } else {
|
||||||
|
// if (bonding_load_cccd_info(self->is_central, self->conn_handle, self->ediv)) {
|
||||||
|
// // Did an sd_ble_gatts_sys_attr_set() with the stored sys_attr values.
|
||||||
|
// } else {
|
||||||
|
// // No matching bonding found, so use fresh system attributes.
|
||||||
|
// sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
|
||||||
|
// }
|
||||||
|
// self->pair_status = PAIR_PAIRED;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void bleio_connection_clear(bleio_connection_internal_t *self) {
|
||||||
|
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->remote_service_list));
|
||||||
|
|
||||||
|
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||||
|
self->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
self->is_central = false;
|
||||||
|
//FIX bonding_clear_keys(&self->bonding_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) {
|
||||||
|
if (self->connection == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self->connection->pair_status == PAIR_PAIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) {
|
||||||
|
if (self->connection == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) {
|
||||||
|
hci_disconnect(self->conn_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) {
|
||||||
|
self->pair_status = PAIR_WAITING;
|
||||||
|
|
||||||
|
//FIX check_nrf_error(sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params));
|
||||||
|
|
||||||
|
while (self->pair_status == PAIR_WAITING && !mp_hal_is_interrupted()) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
}
|
||||||
|
if (mp_hal_is_interrupted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//FIX check_sec_status(self->sec_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) {
|
||||||
|
while (self->conn_params_updating && !mp_hal_is_interrupted()) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
}
|
||||||
|
//FIX return 1.25f * self->conn_params.min_conn_interval;
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current negotiated MTU length, minus overhead.
|
||||||
|
mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) {
|
||||||
|
return (self->mtu == 0 ? BT_ATT_DEFAULT_LE_MTU : self->mtu) - 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) {
|
||||||
|
// self->conn_params_updating = true;
|
||||||
|
// uint16_t interval = new_interval / 1.25f;
|
||||||
|
// self->conn_params.min_conn_interval = interval;
|
||||||
|
// self->conn_params.max_conn_interval = interval;
|
||||||
|
// uint32_t status = NRF_ERROR_BUSY;
|
||||||
|
// while (status == NRF_ERROR_BUSY) {
|
||||||
|
// status = sd_ble_gap_conn_param_update(self->conn_handle, &self->conn_params);
|
||||||
|
// RUN_BACKGROUND_TASKS;
|
||||||
|
// }
|
||||||
|
// check_nrf_error(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// service_uuid may be NULL, to discover all services.
|
||||||
|
// STATIC bool discover_next_services(bleio_connection_internal_t* connection, uint16_t start_handle, ble_uuid_t *service_uuid) {
|
||||||
|
// m_discovery_successful = false;
|
||||||
|
// m_discovery_in_process = true;
|
||||||
|
|
||||||
|
// uint32_t nrf_err = NRF_ERROR_BUSY;
|
||||||
|
// while (nrf_err == NRF_ERROR_BUSY) {
|
||||||
|
// nrf_err = sd_ble_gattc_primary_services_discover(connection->conn_handle, start_handle, service_uuid);
|
||||||
|
// }
|
||||||
|
// check_nrf_error(nrf_err);
|
||||||
|
|
||||||
|
// // Wait for a discovery event.
|
||||||
|
// while (m_discovery_in_process) {
|
||||||
|
// MICROPY_VM_HOOK_LOOP;
|
||||||
|
// }
|
||||||
|
// return m_discovery_successful;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC bool discover_next_characteristics(bleio_connection_internal_t* connection, bleio_service_obj_t *service, uint16_t start_handle) {
|
||||||
|
// m_char_discovery_service = service;
|
||||||
|
|
||||||
|
// ble_gattc_handle_range_t handle_range;
|
||||||
|
// handle_range.start_handle = start_handle;
|
||||||
|
// handle_range.end_handle = service->end_handle;
|
||||||
|
|
||||||
|
// m_discovery_successful = false;
|
||||||
|
// m_discovery_in_process = true;
|
||||||
|
|
||||||
|
// uint32_t err_code = sd_ble_gattc_characteristics_discover(connection->conn_handle, &handle_range);
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Wait for a discovery event.
|
||||||
|
// while (m_discovery_in_process) {
|
||||||
|
// MICROPY_VM_HOOK_LOOP;
|
||||||
|
// }
|
||||||
|
// return m_discovery_successful;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC bool discover_next_descriptors(bleio_connection_internal_t* connection, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
|
||||||
|
// m_desc_discovery_characteristic = characteristic;
|
||||||
|
|
||||||
|
// ble_gattc_handle_range_t handle_range;
|
||||||
|
// handle_range.start_handle = start_handle;
|
||||||
|
// handle_range.end_handle = end_handle;
|
||||||
|
|
||||||
|
// m_discovery_successful = false;
|
||||||
|
// m_discovery_in_process = true;
|
||||||
|
|
||||||
|
// uint32_t err_code = sd_ble_gattc_descriptors_discover(connection->conn_handle, &handle_range);
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Wait for a discovery event.
|
||||||
|
// while (m_discovery_in_process) {
|
||||||
|
// MICROPY_VM_HOOK_LOOP;
|
||||||
|
// }
|
||||||
|
// return m_discovery_successful;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) {
|
||||||
|
// for (size_t i = 0; i < response->count; ++i) {
|
||||||
|
// ble_gattc_service_t *gattc_service = &response->services[i];
|
||||||
|
|
||||||
|
// bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
|
||||||
|
// service->base.type = &bleio_service_type;
|
||||||
|
|
||||||
|
// // Initialize several fields at once.
|
||||||
|
// bleio_service_from_connection(service, bleio_connection_new_from_internal(connection));
|
||||||
|
|
||||||
|
// service->is_remote = true;
|
||||||
|
// service->start_handle = gattc_service->handle_range.start_handle;
|
||||||
|
// service->end_handle = gattc_service->handle_range.end_handle;
|
||||||
|
// service->handle = gattc_service->handle_range.start_handle;
|
||||||
|
|
||||||
|
// if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||||
|
// // Known service UUID.
|
||||||
|
// bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
// uuid->base.type = &bleio_uuid_type;
|
||||||
|
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
|
||||||
|
// service->uuid = uuid;
|
||||||
|
// } else {
|
||||||
|
// // The discovery response contained a 128-bit UUID that has not yet been registered with the
|
||||||
|
// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
|
||||||
|
// // For now, just set the UUID to NULL.
|
||||||
|
// service->uuid = NULL;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list),
|
||||||
|
// MP_OBJ_FROM_PTR(service));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (response->count > 0) {
|
||||||
|
// m_discovery_successful = true;
|
||||||
|
// }
|
||||||
|
// m_discovery_in_process = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_connection_internal_t* connection) {
|
||||||
|
// for (size_t i = 0; i < response->count; ++i) {
|
||||||
|
// ble_gattc_char_t *gattc_char = &response->chars[i];
|
||||||
|
|
||||||
|
// bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||||
|
// characteristic->base.type = &bleio_characteristic_type;
|
||||||
|
|
||||||
|
// bleio_uuid_obj_t *uuid = NULL;
|
||||||
|
|
||||||
|
// if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||||
|
// // Known characteristic UUID.
|
||||||
|
// uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
// uuid->base.type = &bleio_uuid_type;
|
||||||
|
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
|
||||||
|
// } else {
|
||||||
|
// // The discovery response contained a 128-bit UUID that has not yet been registered with the
|
||||||
|
// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
|
||||||
|
// // For now, just leave the UUID as NULL.
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bleio_characteristic_properties_t props =
|
||||||
|
// (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) |
|
||||||
|
// (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) |
|
||||||
|
// (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) |
|
||||||
|
// (gattc_char->char_props.read ? CHAR_PROP_READ : 0) |
|
||||||
|
// (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) |
|
||||||
|
// (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0);
|
||||||
|
|
||||||
|
// // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
|
||||||
|
// common_hal_bleio_characteristic_construct(
|
||||||
|
// characteristic, m_char_discovery_service, gattc_char->handle_value, uuid,
|
||||||
|
// props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||||
|
// GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
||||||
|
// NULL);
|
||||||
|
|
||||||
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list),
|
||||||
|
// MP_OBJ_FROM_PTR(characteristic));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (response->count > 0) {
|
||||||
|
// m_discovery_successful = true;
|
||||||
|
// }
|
||||||
|
// m_discovery_in_process = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_connection_internal_t* connection) {
|
||||||
|
// for (size_t i = 0; i < response->count; ++i) {
|
||||||
|
// ble_gattc_desc_t *gattc_desc = &response->descs[i];
|
||||||
|
|
||||||
|
// // Remember handles for certain well-known descriptors.
|
||||||
|
// switch (gattc_desc->uuid.uuid) {
|
||||||
|
// case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
|
||||||
|
// m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG:
|
||||||
|
// m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC:
|
||||||
|
// m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors,
|
||||||
|
// // so ignore those.
|
||||||
|
// // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
|
||||||
|
// descriptor->base.type = &bleio_descriptor_type;
|
||||||
|
|
||||||
|
// bleio_uuid_obj_t *uuid = NULL;
|
||||||
|
|
||||||
|
// if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||||
|
// // Known descriptor UUID.
|
||||||
|
// uuid = m_new_obj(bleio_uuid_obj_t);
|
||||||
|
// uuid->base.type = &bleio_uuid_type;
|
||||||
|
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid);
|
||||||
|
// } else {
|
||||||
|
// // The discovery response contained a 128-bit UUID that has not yet been registered with the
|
||||||
|
// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
|
||||||
|
// // For now, just leave the UUID as NULL.
|
||||||
|
// }
|
||||||
|
|
||||||
|
// common_hal_bleio_descriptor_construct(
|
||||||
|
// descriptor, m_desc_discovery_characteristic, uuid,
|
||||||
|
// SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||||
|
// GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
||||||
|
// descriptor->handle = gattc_desc->handle;
|
||||||
|
|
||||||
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(m_desc_discovery_characteristic->descriptor_list),
|
||||||
|
// MP_OBJ_FROM_PTR(descriptor));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (response->count > 0) {
|
||||||
|
// m_discovery_successful = true;
|
||||||
|
// }
|
||||||
|
// m_discovery_in_process = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC bool discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t payload) {
|
||||||
|
// bleio_connection_internal_t* connection = MP_OBJ_TO_PTR(payload);
|
||||||
|
// switch (ble_evt->header.evt_id) {
|
||||||
|
// case BLE_GAP_EVT_DISCONNECTED:
|
||||||
|
// m_discovery_successful = false;
|
||||||
|
// m_discovery_in_process = false;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||||
|
// on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, connection);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||||
|
// on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, connection);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||||
|
// on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, connection);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// // CONNECTION_DEBUG_PRINTF(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id);
|
||||||
|
// return false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t service_uuids_whitelist) {
|
||||||
|
// ble_drv_add_event_handler(discovery_on_ble_evt, self);
|
||||||
|
|
||||||
|
// // Start over with an empty list.
|
||||||
|
// self->remote_service_list = mp_obj_new_list(0, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
// if (service_uuids_whitelist == mp_const_none) {
|
||||||
|
// // List of service UUID's not given, so discover all available services.
|
||||||
|
|
||||||
|
// uint16_t next_service_start_handle = BLE_GATT_HANDLE_START;
|
||||||
|
|
||||||
|
// while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) {
|
||||||
|
// // discover_next_services() appends to remote_services_list.
|
||||||
|
|
||||||
|
// // Get the most recently discovered service, and then ask for services
|
||||||
|
// // whose handles start after the last attribute handle inside that service.
|
||||||
|
// // There must be at least one if discover_next_services() returned true.
|
||||||
|
// const bleio_service_obj_t *service =
|
||||||
|
// self->remote_service_list->items[self->remote_service_list->len - 1];
|
||||||
|
// next_service_start_handle = service->end_handle + 1;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// mp_obj_iter_buf_t iter_buf;
|
||||||
|
// mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf);
|
||||||
|
// mp_obj_t uuid_obj;
|
||||||
|
// while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||||
|
// if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
||||||
|
// mp_raise_TypeError(translate("non-UUID found in service_uuids_whitelist"));
|
||||||
|
// }
|
||||||
|
// bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
|
||||||
|
|
||||||
|
// ble_uuid_t nrf_uuid;
|
||||||
|
// bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid);
|
||||||
|
|
||||||
|
// // Service might or might not be discovered; that's ok. Caller has to check
|
||||||
|
// // Central.remote_services to find out.
|
||||||
|
// // We only need to call this once for each service to discover.
|
||||||
|
// discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// for (size_t i = 0; i < self->remote_service_list->len; i++) {
|
||||||
|
// bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->remote_service_list->items[i]);
|
||||||
|
// // Skip the service if it had an unknown (unregistered) UUID.
|
||||||
|
// if (service->uuid == NULL) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uint16_t next_char_start_handle = service->start_handle;
|
||||||
|
|
||||||
|
// // Stop when we go past the end of the range of handles for this service or
|
||||||
|
// // discovery call returns nothing.
|
||||||
|
// // discover_next_characteristics() appends to the characteristic_list.
|
||||||
|
// while (next_char_start_handle <= service->end_handle &&
|
||||||
|
// discover_next_characteristics(self, service, next_char_start_handle)) {
|
||||||
|
|
||||||
|
|
||||||
|
// // Get the most recently discovered characteristic, and then ask for characteristics
|
||||||
|
// // whose handles start after the last attribute handle inside that characteristic.
|
||||||
|
// const bleio_characteristic_obj_t *characteristic =
|
||||||
|
// MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]);
|
||||||
|
|
||||||
|
// next_char_start_handle = characteristic->handle + 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Got characteristics for this service. Now discover descriptors for each characteristic.
|
||||||
|
// size_t char_list_len = service->characteristic_list->len;
|
||||||
|
// for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) {
|
||||||
|
// bleio_characteristic_obj_t *characteristic =
|
||||||
|
// MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]);
|
||||||
|
// const bool last_characteristic = char_idx == char_list_len - 1;
|
||||||
|
// bleio_characteristic_obj_t *next_characteristic = last_characteristic
|
||||||
|
// ? NULL
|
||||||
|
// : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]);
|
||||||
|
|
||||||
|
// // Skip the characteristic if it had an unknown (unregistered) UUID.
|
||||||
|
// if (characteristic->uuid == NULL) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uint16_t next_desc_start_handle = characteristic->handle + 1;
|
||||||
|
|
||||||
|
// // Don't run past the end of this service or the beginning of the next characteristic.
|
||||||
|
// uint16_t next_desc_end_handle = next_characteristic == NULL
|
||||||
|
// ? service->end_handle
|
||||||
|
// : next_characteristic->handle - 1;
|
||||||
|
|
||||||
|
// // Stop when we go past the end of the range of handles for this service or
|
||||||
|
// // discovery call returns nothing.
|
||||||
|
// // discover_next_descriptors() appends to the descriptor_linked_list.
|
||||||
|
// while (next_desc_start_handle <= service->end_handle &&
|
||||||
|
// next_desc_start_handle <= next_desc_end_handle &&
|
||||||
|
// discover_next_descriptors(self, characteristic,
|
||||||
|
// next_desc_start_handle, next_desc_end_handle)) {
|
||||||
|
// // Get the most recently discovered descriptor, and then ask for descriptors
|
||||||
|
// // whose handles start after that descriptor's handle.
|
||||||
|
// // There must be at least one if discover_next_descriptors() returned true.
|
||||||
|
// const bleio_descriptor_obj_t *descriptor =
|
||||||
|
// characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1];
|
||||||
|
// next_desc_start_handle = descriptor->handle + 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // This event handler is no longer needed.
|
||||||
|
// ble_drv_remove_event_handler(discovery_on_ble_evt, self);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) {
|
||||||
|
//FIX discover_remote_services(self->connection, service_uuids_whitelist);
|
||||||
|
bleio_connection_ensure_connected(self);
|
||||||
|
// Convert to a tuple and then clear the list so the callee will take ownership.
|
||||||
|
mp_obj_tuple_t *services_tuple =
|
||||||
|
mp_obj_new_tuple(self->connection->remote_service_list->len,
|
||||||
|
self->connection->remote_service_list->items);
|
||||||
|
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list));
|
||||||
|
return services_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
|
||||||
|
if (self == NULL || self->connection == NULL) {
|
||||||
|
return BLE_CONN_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
return self->connection->conn_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* internal) {
|
||||||
|
if (internal->connection_obj != mp_const_none) {
|
||||||
|
return internal->connection_obj;
|
||||||
|
}
|
||||||
|
bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t);
|
||||||
|
connection->base.type = &bleio_connection_type;
|
||||||
|
connection->connection = internal;
|
||||||
|
internal->connection_obj = connection;
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the connection that uses the given conn_handle. Return NULL if not found.
|
||||||
|
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) {
|
||||||
|
bleio_connection_internal_t *connection;
|
||||||
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
|
connection = &bleio_connections[i];
|
||||||
|
if (connection->conn_handle == conn_handle) {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
89
devices/ble_hci/common-hal/_bleio/Connection.h
Normal file
89
devices/ble_hci/common-hal/_bleio/Connection.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/objlist.h"
|
||||||
|
|
||||||
|
#include "common-hal/_bleio/__init__.h"
|
||||||
|
#include "shared-module/_bleio/Address.h"
|
||||||
|
#include "common-hal/_bleio/Service.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PAIR_NOT_PAIRED,
|
||||||
|
PAIR_WAITING,
|
||||||
|
PAIR_PAIRED,
|
||||||
|
} pair_status_t;
|
||||||
|
|
||||||
|
// We split the Connection object into two so that the internal mechanics can live outside of the
|
||||||
|
// VM. If it were one object, then we'd risk user code seeing a connection object of theirs be
|
||||||
|
// reused.
|
||||||
|
typedef struct {
|
||||||
|
uint16_t conn_handle;
|
||||||
|
bool is_central;
|
||||||
|
// Remote services discovered when this peripheral is acting as a client.
|
||||||
|
mp_obj_list_t *remote_service_list;
|
||||||
|
// The advertising data and scan response buffers are held by us, not by the SD, so we must
|
||||||
|
// maintain them and not change it. If we need to change the contents during advertising,
|
||||||
|
// there are tricks to get the SD to notice (see DevZone - TBS).
|
||||||
|
bonding_keys_t bonding_keys;
|
||||||
|
// EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing.
|
||||||
|
uint16_t ediv;
|
||||||
|
volatile pair_status_t pair_status;
|
||||||
|
uint8_t sec_status; // Internal security status.
|
||||||
|
mp_obj_t connection_obj;
|
||||||
|
//REMOVE ble_gap_conn_params_t conn_params;
|
||||||
|
volatile bool conn_params_updating;
|
||||||
|
uint16_t mtu;
|
||||||
|
// Request that CCCD values for this connection be saved, using sys_attr values.
|
||||||
|
volatile bool do_bond_cccds;
|
||||||
|
// Request that security key info for this connection be saved.
|
||||||
|
volatile bool do_bond_keys;
|
||||||
|
// Time of setting do_bond_ccds: we delay a bit to consolidate multiple CCCD changes
|
||||||
|
// into one write. Time is currently in ticks_ms.
|
||||||
|
uint64_t do_bond_cccds_request_time;
|
||||||
|
//FIX from att.c
|
||||||
|
uint8_t role;
|
||||||
|
bt_addr_le_t addr;
|
||||||
|
} bleio_connection_internal_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
bleio_connection_internal_t* connection;
|
||||||
|
// The HCI disconnect reason.
|
||||||
|
uint8_t disconnect_reason;
|
||||||
|
} bleio_connection_obj_t;
|
||||||
|
|
||||||
|
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self);
|
||||||
|
mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* connection);
|
||||||
|
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H
|
114
devices/ble_hci/common-hal/_bleio/Descriptor.c
Normal file
114
devices/ble_hci/common-hal/_bleio/Descriptor.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
|
||||||
|
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
|
self->characteristic = characteristic;
|
||||||
|
self->uuid = uuid;
|
||||||
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
|
self->read_perm = read_perm;
|
||||||
|
self->write_perm = write_perm;
|
||||||
|
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
|
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||||
|
if (max_length < 0 || max_length > max_length_max) {
|
||||||
|
mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
|
||||||
|
max_length_max, fixed_length ? "True" : "False");
|
||||||
|
}
|
||||||
|
self->max_length = max_length;
|
||||||
|
self->fixed_length = fixed_length;
|
||||||
|
|
||||||
|
common_hal_bleio_descriptor_set_value(self, initial_value_bufinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
|
||||||
|
return self->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) {
|
||||||
|
return self->characteristic;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) {
|
||||||
|
// Do GATT operations only if this descriptor has been registered
|
||||||
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
||||||
|
//uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
||||||
|
//FIX have att_read_req fill in a buffer
|
||||||
|
//uint8_t rsp[MAX(len, 512)];
|
||||||
|
//return att_read_req(conn_handle, self->handle, rsp, len);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const size_t actual_length = MIN(len, bufinfo.len);
|
||||||
|
memcpy(buf, bufinfo.buf, actual_length);
|
||||||
|
return actual_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
|
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||||
|
mp_raise_ValueError(translate("Value length != required fixed length"));
|
||||||
|
}
|
||||||
|
if (bufinfo->len > self->max_length) {
|
||||||
|
mp_raise_ValueError(translate("Value length > max_length"));
|
||||||
|
}
|
||||||
|
|
||||||
|
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||||
|
|
||||||
|
// Do GATT operations only if this descriptor has been registered.
|
||||||
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
||||||
|
//FIX
|
||||||
|
// uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
|
// att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp);
|
||||||
|
} else {
|
||||||
|
// Always write the value locally even if no connections are active.
|
||||||
|
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bufinfo->len > self->max_length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
devices/ble_hci/common-hal/_bleio/Descriptor.h
Normal file
53
devices/ble_hci/common-hal/_bleio/Descriptor.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "common-hal/_bleio/UUID.h"
|
||||||
|
|
||||||
|
// Forward declare characteristic because it includes a Descriptor.
|
||||||
|
struct _bleio_characteristic_obj;
|
||||||
|
|
||||||
|
typedef struct _bleio_descriptor_obj {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// Will be MP_OBJ_NULL before being assigned to a Characteristic.
|
||||||
|
struct _bleio_characteristic_obj *characteristic;
|
||||||
|
bleio_uuid_obj_t *uuid;
|
||||||
|
mp_obj_t value;
|
||||||
|
uint16_t max_length;
|
||||||
|
bool fixed_length;
|
||||||
|
uint16_t handle;
|
||||||
|
bleio_attribute_security_mode_t read_perm;
|
||||||
|
bleio_attribute_security_mode_t write_perm;
|
||||||
|
struct _bleio_descriptor_obj* next;
|
||||||
|
} bleio_descriptor_obj_t;
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H
|
265
devices/ble_hci/common-hal/_bleio/PacketBuffer.c
Normal file
265
devices/ble_hci/common-hal/_bleio/PacketBuffer.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "lib/utils/interrupt_char.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
|
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||||
|
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
|
||||||
|
// This shouldn't happen.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Push all the data onto the ring buffer.
|
||||||
|
// Make room for the new value by dropping the oldest packets first.
|
||||||
|
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||||
|
uint16_t packet_length;
|
||||||
|
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||||
|
for (uint16_t i = 0; i < packet_length; i++) {
|
||||||
|
ringbuf_get(&self->ringbuf);
|
||||||
|
}
|
||||||
|
// set an overflow flag?
|
||||||
|
}
|
||||||
|
ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
||||||
|
ringbuf_put_n(&self->ringbuf, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
|
||||||
|
// Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
|
||||||
|
// transmission (when packet_queued is true) and the other is `pending` and can still be
|
||||||
|
// modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
|
||||||
|
// of the lower level link and ATT layers.
|
||||||
|
self->packet_queued = false;
|
||||||
|
if (self->pending_size > 0) {
|
||||||
|
mp_buffer_info_t bufinfo = {
|
||||||
|
.buf = self->outgoing[self->pending_index],
|
||||||
|
.len = self->pending_size,
|
||||||
|
};
|
||||||
|
common_hal_bleio_characteristic_set_value(self->characteristic, &bufinfo);
|
||||||
|
|
||||||
|
self->pending_size = 0;
|
||||||
|
self->pending_index = (self->pending_index + 1) % 2;
|
||||||
|
self->packet_queued = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
|
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_packet_buffer_construct(
|
||||||
|
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
|
||||||
|
size_t buffer_size) {
|
||||||
|
|
||||||
|
self->characteristic = characteristic;
|
||||||
|
self->client = self->characteristic->service->is_remote;
|
||||||
|
bleio_characteristic_properties_t incoming =
|
||||||
|
self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
|
||||||
|
bleio_characteristic_properties_t outgoing =
|
||||||
|
self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
|
||||||
|
|
||||||
|
if (self->client) {
|
||||||
|
// Swap if we're the client.
|
||||||
|
bleio_characteristic_properties_t temp = incoming;
|
||||||
|
incoming = outgoing;
|
||||||
|
outgoing = temp;
|
||||||
|
self->conn_handle = bleio_connection_get_conn_handle(MP_OBJ_TO_PTR(self->characteristic->service->connection));
|
||||||
|
} else {
|
||||||
|
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incoming) {
|
||||||
|
if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + characteristic->max_length), false)) {
|
||||||
|
mp_raise_ValueError(translate("Buffer too large and unable to allocate"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outgoing) {
|
||||||
|
self->packet_queued = false;
|
||||||
|
self->pending_index = 0;
|
||||||
|
self->pending_size = 0;
|
||||||
|
self->outgoing[0] = m_malloc(characteristic->max_length, false);
|
||||||
|
self->outgoing[1] = m_malloc(characteristic->max_length, false);
|
||||||
|
} else {
|
||||||
|
self->outgoing[0] = NULL;
|
||||||
|
self->outgoing[1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_characteristic_set_observer(self->characteristic, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
|
||||||
|
if (ringbuf_num_filled(&self->ringbuf) < 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy received data.
|
||||||
|
// Get packet length, which is in first two bytes of packet.
|
||||||
|
uint16_t packet_length;
|
||||||
|
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||||
|
|
||||||
|
mp_int_t ret;
|
||||||
|
if (packet_length > len) {
|
||||||
|
// Packet is longer than requested. Return negative of overrun value.
|
||||||
|
ret = len - packet_length;
|
||||||
|
// Discard the packet if it's too large. Don't fill data.
|
||||||
|
while (packet_length--) {
|
||||||
|
(void) ringbuf_get(&self->ringbuf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Read as much as possible, but might be shorter than len.
|
||||||
|
ringbuf_get_n(&self->ringbuf, data, packet_length);
|
||||||
|
ret = packet_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t* header, size_t header_len) {
|
||||||
|
if (self->outgoing[0] == NULL) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Writes not supported on Characteristic"));
|
||||||
|
}
|
||||||
|
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint16_t outgoing_packet_length = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
|
||||||
|
|
||||||
|
if (len + header_len > outgoing_packet_length) {
|
||||||
|
// Supplied data will not fit in a single BLE packet.
|
||||||
|
mp_raise_ValueError(translate("Total data to write is larger than outgoing_packet_length"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len + self->pending_size > outgoing_packet_length) {
|
||||||
|
// No room to append len bytes to packet. Wait until we get a free buffer,
|
||||||
|
// and keep checking that we haven't been disconnected.
|
||||||
|
while (self->pending_size != 0 && self->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_bytes_written = 0;
|
||||||
|
|
||||||
|
uint8_t* pending = self->outgoing[self->pending_index];
|
||||||
|
|
||||||
|
if (self->pending_size == 0) {
|
||||||
|
memcpy(pending, header, header_len);
|
||||||
|
self->pending_size += header_len;
|
||||||
|
num_bytes_written += header_len;
|
||||||
|
}
|
||||||
|
memcpy(pending + self->pending_size, data, len);
|
||||||
|
self->pending_size += len;
|
||||||
|
num_bytes_written += len;
|
||||||
|
|
||||||
|
// If no writes are queued then sneak in this data.
|
||||||
|
if (!self->packet_queued) {
|
||||||
|
queue_next_write(self);
|
||||||
|
}
|
||||||
|
return num_bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self) {
|
||||||
|
// If this PacketBuffer is coming from a remote service via NOTIFY or INDICATE
|
||||||
|
// the maximum size is what can be sent in one
|
||||||
|
// BLE packet. But we must be connected to know that value.
|
||||||
|
//
|
||||||
|
// Otherwise it can be as long as the characteristic
|
||||||
|
// will permit, whether or not we're connected.
|
||||||
|
|
||||||
|
if (self->characteristic == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->characteristic->service != NULL &&
|
||||||
|
self->characteristic->service->is_remote &&
|
||||||
|
(common_hal_bleio_characteristic_get_properties(self->characteristic) &
|
||||||
|
(CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) {
|
||||||
|
// We are talking to a remote service, and data is arriving via NOTIFY or INDICATE.
|
||||||
|
if (self->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
|
||||||
|
if (connection) {
|
||||||
|
return MIN(common_hal_bleio_connection_get_max_packet_length(connection),
|
||||||
|
self->characteristic->max_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There's no current connection, so we don't know the MTU, and
|
||||||
|
// we can't tell what the largest incoming packet length would be.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return self->characteristic->max_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self) {
|
||||||
|
// If we are sending data via NOTIFY or INDICATE, the maximum size
|
||||||
|
// is what can be sent in one BLE packet. But we must be connected
|
||||||
|
// to know that value.
|
||||||
|
//
|
||||||
|
// Otherwise it can be as long as the characteristic
|
||||||
|
// will permit, whether or not we're connected.
|
||||||
|
|
||||||
|
if (self->characteristic == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->characteristic->service != NULL &&
|
||||||
|
!self->characteristic->service->is_remote &&
|
||||||
|
(common_hal_bleio_characteristic_get_properties(self->characteristic) &
|
||||||
|
(CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) {
|
||||||
|
// We are sending to a client, via NOTIFY or INDICATE.
|
||||||
|
if (self->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
|
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
|
||||||
|
if (connection) {
|
||||||
|
return MIN(common_hal_bleio_connection_get_max_packet_length(connection),
|
||||||
|
self->characteristic->max_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There's no current connection, so we don't know the MTU, and
|
||||||
|
// we can't tell what the largest outgoing packet length would be.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return self->characteristic->max_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
|
||||||
|
return self->characteristic == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
|
||||||
|
if (!common_hal_bleio_packet_buffer_deinited(self)) {
|
||||||
|
bleio_characteristic_clear_observer(self->characteristic);
|
||||||
|
}
|
||||||
|
}
|
53
devices/ble_hci/common-hal/_bleio/PacketBuffer.h
Normal file
53
devices/ble_hci/common-hal/_bleio/PacketBuffer.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H
|
||||||
|
|
||||||
|
#include "py/ringbuf.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
bleio_characteristic_obj_t *characteristic;
|
||||||
|
// Ring buffer storing consecutive incoming values.
|
||||||
|
ringbuf_t ringbuf;
|
||||||
|
// Two outgoing buffers to alternate between. One will be queued for transmission by the SD and
|
||||||
|
// the other is waiting to be queued and can be extended.
|
||||||
|
uint8_t* outgoing[2];
|
||||||
|
volatile uint16_t pending_size;
|
||||||
|
// We remember the conn_handle so we can do a NOTIFY/INDICATE to a client.
|
||||||
|
// We can find out the conn_handle on a Characteristic write or a CCCD write (but not a read).
|
||||||
|
volatile uint16_t conn_handle;
|
||||||
|
uint8_t pending_index;
|
||||||
|
uint8_t write_type;
|
||||||
|
bool client;
|
||||||
|
bool packet_queued;
|
||||||
|
} bleio_packet_buffer_obj_t;
|
||||||
|
|
||||||
|
void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H
|
129
devices/ble_hci/common-hal/_bleio/Service.c
Normal file
129
devices/ble_hci/common-hal/_bleio/Service.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
|
||||||
|
uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) {
|
||||||
|
self->uuid = uuid;
|
||||||
|
self->characteristic_list = characteristic_list;
|
||||||
|
self->is_remote = false;
|
||||||
|
self->connection = NULL;
|
||||||
|
self->is_secondary = is_secondary;
|
||||||
|
|
||||||
|
vm_used_ble = true;
|
||||||
|
|
||||||
|
self->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(self));
|
||||||
|
self->start_handle = self->handle;
|
||||||
|
self->end_handle = self->handle;
|
||||||
|
if (self->handle == BLE_GATT_HANDLE_INVALID) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
||||||
|
if (_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
||||||
|
mp_obj_new_list(0, NULL)) != 0) {
|
||||||
|
mp_raise_RuntimeError(translate("Failed to add service"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) {
|
||||||
|
self->handle = 0xFFFF;
|
||||||
|
self->uuid = NULL;
|
||||||
|
self->characteristic_list = mp_obj_new_list(0, NULL);
|
||||||
|
self->is_remote = true;
|
||||||
|
self->is_secondary = false;
|
||||||
|
self->connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
|
||||||
|
return self->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) {
|
||||||
|
return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
|
||||||
|
return self->is_remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
|
||||||
|
return self->is_secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
||||||
|
bleio_characteristic_obj_t *characteristic,
|
||||||
|
mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
|
|
||||||
|
if (self->handle != common_hal_bleio_adapter_obj.last_added_service_handle) {
|
||||||
|
mp_raise_bleio_BluetoothError(
|
||||||
|
translate("Characteristic can only be added to most recently added service"));
|
||||||
|
}
|
||||||
|
characteristic->decl_handle = bleio_adapter_add_attribute(
|
||||||
|
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
||||||
|
// This is the value handle.
|
||||||
|
characteristic->handle = bleio_adapter_add_attribute(
|
||||||
|
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
||||||
|
|
||||||
|
self->end_handle = characteristic->handle;
|
||||||
|
|
||||||
|
if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) {
|
||||||
|
// We need a CCCD if this characteristic is doing notify or indicate.
|
||||||
|
bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t);
|
||||||
|
cccd->base.type = &bleio_descriptor_type;
|
||||||
|
|
||||||
|
uint16_t zero = 0;
|
||||||
|
mp_buffer_info_t zero_cccd_value = {
|
||||||
|
.buf = &zero,
|
||||||
|
.len = sizeof(zero),
|
||||||
|
};
|
||||||
|
|
||||||
|
common_hal_bleio_descriptor_construct(
|
||||||
|
cccd,
|
||||||
|
characteristic,
|
||||||
|
&cccd_uuid, // 0x2902
|
||||||
|
SECURITY_MODE_OPEN, // CCCD read perm
|
||||||
|
characteristic->read_perm, // Make CCCD write perm match characteristic read perm.
|
||||||
|
2, // 2 bytes
|
||||||
|
true, // fixed length
|
||||||
|
&zero_cccd_value // Initial value is 0.
|
||||||
|
);
|
||||||
|
|
||||||
|
// Adds CCCD to attribute table, and also extends self->end_handle to include the CCCD.
|
||||||
|
common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
||||||
|
characteristic->cccd = cccd;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
||||||
|
}
|
54
devices/ble_hci/common-hal/_bleio/Service.h
Normal file
54
devices/ble_hci/common-hal/_bleio/Service.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H
|
||||||
|
|
||||||
|
#include "py/objlist.h"
|
||||||
|
#include "common-hal/_bleio/UUID.h"
|
||||||
|
|
||||||
|
typedef struct bleio_service_obj {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// Handle for the local service.
|
||||||
|
uint16_t handle;
|
||||||
|
// True if created during discovery.
|
||||||
|
bool is_remote;
|
||||||
|
bool is_secondary;
|
||||||
|
bleio_uuid_obj_t *uuid;
|
||||||
|
// The connection object is set only when this is a remote service.
|
||||||
|
// A local service doesn't know the connection.
|
||||||
|
mp_obj_t connection;
|
||||||
|
mp_obj_list_t *characteristic_list;
|
||||||
|
// Range of attribute handles of this service.
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
struct bleio_service_obj* next;
|
||||||
|
} bleio_service_obj_t;
|
||||||
|
|
||||||
|
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H
|
75
devices/ble_hci/common-hal/_bleio/UUID.c
Normal file
75
devices/ble_hci/common-hal/_bleio/UUID.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "common-hal/_bleio/UUID.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
|
||||||
|
// If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID.
|
||||||
|
// If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where
|
||||||
|
// the 16-bit part goes. Those 16 bits are passed in uuid16.
|
||||||
|
void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) {
|
||||||
|
self->size = uuid128 == NULL ? 16 : 128;
|
||||||
|
self->uuid16 = uuid16;
|
||||||
|
if (uuid128) {
|
||||||
|
memcpy(self->uuid128, uuid128, 16);
|
||||||
|
self->uuid128[12] = uuid16 & 0xff;
|
||||||
|
self->uuid128[13] = uuid16 >> 8;
|
||||||
|
} else {
|
||||||
|
memset(self->uuid128, 0, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) {
|
||||||
|
return self->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) {
|
||||||
|
return self->uuid16;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) {
|
||||||
|
memcpy(uuid128, self->uuid128, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) {
|
||||||
|
if (self->size == 16) {
|
||||||
|
buf[0] = self->uuid16 & 0xff;
|
||||||
|
buf[1] = self->uuid16 >> 8;
|
||||||
|
} else {
|
||||||
|
common_hal_bleio_uuid_get_uuid128(self, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a uui16 only if this is a standard uuid. Otherwise return BLE_UUID_UNKNOWN.
|
||||||
|
uint16_t bleio_uuid_get_uuid16_or_unknown(bleio_uuid_obj_t *uuid) {
|
||||||
|
return uuid->size == 16 ? uuid->uuid16 : BLE_UUID_UNKNOWN;
|
||||||
|
}
|
58
devices/ble_hci/common-hal/_bleio/UUID.h
Normal file
58
devices/ble_hci/common-hal/_bleio/UUID.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
// Types returned by attribute table lookups. These are UUIDs.
|
||||||
|
typedef enum {
|
||||||
|
BLE_UUID_UNKNOWN = 0x0000,
|
||||||
|
BLE_UUID_SERVICE_PRIMARY = 0x2800,
|
||||||
|
BLE_UUID_SERVICE_SECONDARY = 0x2801,
|
||||||
|
BLE_UUID_SERVICE_INCLUDE = 0x2802, // not yet implemented by us
|
||||||
|
BLE_UUID_CHARACTERISTIC = 0x2803,
|
||||||
|
BLE_UUID_CHAR_EXTENDED_PROPS = 0x2900, // not yet implemented by us
|
||||||
|
BLE_UUID_CHAR_USER_DESC = 0x2901, // not yet implemented by us
|
||||||
|
BLE_UUID_CCCD = 0x2902,
|
||||||
|
BLE_UUID_SCCD = 0x2903, // not yet implemented by us
|
||||||
|
BLE_UUID_CHAR_PRESENTATION_FMT = 0x2904, // not yet implemented by us
|
||||||
|
BLE_UUID_CHAR_AGGREGATE_FMT = 0x2905, // not yet implemented by us
|
||||||
|
} ble_standard_uuid;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
uint8_t size;
|
||||||
|
uint16_t uuid16;
|
||||||
|
uint8_t uuid128[16];
|
||||||
|
} bleio_uuid_obj_t;
|
||||||
|
|
||||||
|
uint16_t bleio_uuid_get_uuid16_or_unknown(bleio_uuid_obj_t *uuid);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H
|
112
devices/ble_hci/common-hal/_bleio/__init__.c
Normal file
112
devices/ble_hci/common-hal/_bleio/__init__.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
|
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
#include "supervisor/shared/bluetooth.h"
|
||||||
|
|
||||||
|
// UUID shared by all cccd's.
|
||||||
|
bleio_uuid_obj_t cccd_uuid;
|
||||||
|
|
||||||
|
bool vm_used_ble;
|
||||||
|
|
||||||
|
// void check_sec_status(uint8_t sec_status) {
|
||||||
|
// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch (sec_status) {
|
||||||
|
// case BLE_GAP_SEC_STATUS_UNSPECIFIED:
|
||||||
|
// mp_raise_bleio_SecurityError(translate("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored."));
|
||||||
|
// return;
|
||||||
|
// default:
|
||||||
|
// mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Turn off BLE on a reset or reload.
|
||||||
|
void bleio_reset() {
|
||||||
|
// Create a UUID object for all CCCD's.
|
||||||
|
cccd_uuid.base.type = &bleio_uuid_type;
|
||||||
|
common_hal_bleio_uuid_construct(&cccd_uuid, BLE_UUID_CCCD, NULL);
|
||||||
|
|
||||||
|
bleio_hci_reset();
|
||||||
|
|
||||||
|
if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bleio_adapter_reset(&common_hal_bleio_adapter_obj);
|
||||||
|
if (!vm_used_ble) {
|
||||||
|
// No user-code BLE operations were done, so we can maintain the supervisor state.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
|
||||||
|
common_hal_bleio_adapter_obj.allocated = false;
|
||||||
|
|
||||||
|
bleio_set_adapter(mp_const_none);
|
||||||
|
|
||||||
|
//FIX bonding_reset();
|
||||||
|
supervisor_start_bluetooth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The singleton _bleio.Adapter object, bound to _bleio.adapter
|
||||||
|
bleio_adapter_obj_t common_hal_bleio_adapter_obj = {
|
||||||
|
.base = {
|
||||||
|
.type = &bleio_adapter_type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) {
|
||||||
|
if (common_hal_bleio_adapter_obj.allocated) {
|
||||||
|
mp_raise_RuntimeError(translate("Too many Adapters"));
|
||||||
|
}
|
||||||
|
return &common_hal_bleio_adapter_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_check_connected(uint16_t conn_handle) {
|
||||||
|
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
|
mp_raise_ConnectionError(translate("Not connected"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bleio_gc_collect(void) {
|
||||||
|
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bleio_background(void) {
|
||||||
|
bleio_adapter_background(&common_hal_bleio_adapter_obj);
|
||||||
|
}
|
62
devices/ble_hci/common-hal/_bleio/__init__.h
Normal file
62
devices/ble_hci/common-hal/_bleio/__init__.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
||||||
|
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
|
||||||
|
#include "att.h"
|
||||||
|
#include "hci.h"
|
||||||
|
|
||||||
|
void bleio_background(void);
|
||||||
|
void bleio_reset(void);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// ble_gap_enc_key_t own_enc;
|
||||||
|
// ble_gap_enc_key_t peer_enc;
|
||||||
|
// ble_gap_id_key_t peer_id;
|
||||||
|
} bonding_keys_t;
|
||||||
|
|
||||||
|
// We assume variable length data.
|
||||||
|
// 20 bytes max (23 - 3).
|
||||||
|
#define GATT_MAX_DATA_LENGTH (BT_ATT_DEFAULT_LE_MTU - 3)
|
||||||
|
|
||||||
|
//FIX
|
||||||
|
#define BLE_GATT_HANDLE_INVALID 0x0000
|
||||||
|
#define BLE_CONN_HANDLE_INVALID 0xFFFF
|
||||||
|
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */
|
||||||
|
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */
|
||||||
|
|
||||||
|
// Track if the user code modified the BLE state to know if we need to undo it on reload.
|
||||||
|
extern bool vm_used_ble;
|
||||||
|
|
||||||
|
// UUID shared by all CCCD's.
|
||||||
|
extern bleio_uuid_obj_t cccd_uuid;
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
1788
devices/ble_hci/common-hal/_bleio/att.c
Normal file
1788
devices/ble_hci/common-hal/_bleio/att.c
Normal file
File diff suppressed because it is too large
Load Diff
57
devices/ble_hci/common-hal/_bleio/att.h
Normal file
57
devices/ble_hci/common-hal/_bleio/att.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Derived from ArduinoBLE.
|
||||||
|
// Copyright 2020 Dan Halbert for Adafruit Industries
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H
|
||||||
|
#define MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hci_include/addr.h"
|
||||||
|
#include "hci_include/att.h"
|
||||||
|
#include "hci_include/att_internal.h"
|
||||||
|
|
||||||
|
void bleio_att_reset(void);
|
||||||
|
|
||||||
|
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||||
|
bool att_address_is_connected(bt_addr_le_t *addr);
|
||||||
|
bool att_connect_to_address(bt_addr_le_t *addr);
|
||||||
|
bool att_disconnect(uint16_t conn_handle);
|
||||||
|
bool att_disconnect_all(void);
|
||||||
|
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
||||||
|
bool att_exchange_mtu(uint16_t conn_handle);
|
||||||
|
bool att_handle_is_connected(uint16_t handle);
|
||||||
|
bool att_indicate(uint16_t handle, const uint8_t* value, int length);
|
||||||
|
bool att_is_connected(void);
|
||||||
|
bool att_notify(uint16_t handle, const uint8_t* value, int length);
|
||||||
|
int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]);
|
||||||
|
int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]);
|
||||||
|
uint16_t att_conn_handle(bt_addr_le_t *addr);
|
||||||
|
uint16_t att_mtu(uint16_t handle);
|
||||||
|
void att_add_connection(uint16_t handle, uint8_t role, bt_addr_le_t *peer_addr, uint16_t interval, uint16_t latency, uint16_t supervision_timeout, uint8_t master_clock_accuracy);
|
||||||
|
void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]);
|
||||||
|
void att_remove_connection(uint16_t conn_handle, uint8_t reason);
|
||||||
|
void att_set_max_mtu(uint16_t max_mtu);
|
||||||
|
void att_set_timeout(unsigned long timeout);
|
||||||
|
void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H
|
806
devices/ble_hci/common-hal/_bleio/hci.c
Normal file
806
devices/ble_hci/common-hal/_bleio/hci.c
Normal file
@ -0,0 +1,806 @@
|
|||||||
|
// This file is derived from the ArduinoBLE library. Its header is below.
|
||||||
|
/*
|
||||||
|
This file is part of the ArduinoBLE library.
|
||||||
|
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||||
|
|
||||||
|
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 "att.h"
|
||||||
|
#include "hci.h"
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
// Zephyr include files to define HCI communication values and structs.
|
||||||
|
#include "hci_include/hci.h"
|
||||||
|
#include "hci_include/hci_err.h"
|
||||||
|
#include "hci_include/l2cap_internal.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "py/mphal.h" //*****************************
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "common-hal/_bleio/Adapter.h"
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
|
||||||
|
// Set to 1 for extensive HCI packet logging.
|
||||||
|
#define HCI_DEBUG 0
|
||||||
|
|
||||||
|
// HCI H4 protocol packet types: first byte in the packet.
|
||||||
|
#define H4_CMD 0x01
|
||||||
|
#define H4_ACL 0x02
|
||||||
|
#define H4_SCO 0x03
|
||||||
|
#define H4_EVT 0x04
|
||||||
|
|
||||||
|
#define CTS_TIMEOUT_MSECS (1000)
|
||||||
|
#define RESPONSE_TIMEOUT_MSECS (1000)
|
||||||
|
|
||||||
|
// These are the headers of the full packets that are sent over the serial interface.
|
||||||
|
// They all have a one-byte type-field at the front, one of the H4_xxx packet types.
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint8_t pkt_type;
|
||||||
|
uint16_t opcode;
|
||||||
|
uint8_t param_len;
|
||||||
|
uint8_t params[];
|
||||||
|
} h4_hci_cmd_pkt_t;
|
||||||
|
|
||||||
|
#define ACL_DATA_PB_FIRST_NON_FLUSH 0
|
||||||
|
#define ACL_DATA_PB_MIDDLE 1
|
||||||
|
#define ACL_DATA_PB_FIRST_FLUSH 2
|
||||||
|
#define ACL_DATA_PB_FULL 3
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint8_t pkt_type;
|
||||||
|
uint16_t handle : 12;
|
||||||
|
uint8_t pb: 2; // Packet boundary flag: ACL_DATA_PB values.
|
||||||
|
uint8_t bc: 2; // Broadcast flag: always 0b00 for BLE.
|
||||||
|
uint16_t data_len; // length of data[] in this packet.
|
||||||
|
uint8_t data[];
|
||||||
|
} h4_hci_acl_pkt_t;
|
||||||
|
|
||||||
|
// The ACL data in an h4_hci_acl_pkt_t may be fragmented across
|
||||||
|
// multiple ACL_DATA packets, and need to be recombined. This is the
|
||||||
|
// structure of the combined packet or the first fragment.
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint16_t acl_data_len; // Length of acl_data. Does not include this header.
|
||||||
|
uint16_t cid; // Channel ID.
|
||||||
|
uint8_t acl_data[]; // Length is acl_data_len of full packet.
|
||||||
|
} acl_data_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint8_t pkt_type;
|
||||||
|
uint8_t evt;
|
||||||
|
uint8_t param_len;
|
||||||
|
uint8_t params[];
|
||||||
|
} h4_hci_evt_pkt_t;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Static storage:
|
||||||
|
|
||||||
|
//FIX size
|
||||||
|
#define RX_BUFFER_SIZE (3 + 255)
|
||||||
|
#define ACL_DATA_BUFFER_SIZE (255)
|
||||||
|
|
||||||
|
STATIC uint8_t rx_buffer[RX_BUFFER_SIZE];
|
||||||
|
STATIC size_t rx_idx;
|
||||||
|
|
||||||
|
STATIC uint8_t acl_data_buffer[ACL_DATA_BUFFER_SIZE];
|
||||||
|
STATIC size_t acl_data_len;
|
||||||
|
|
||||||
|
STATIC size_t num_command_packets_allowed;
|
||||||
|
STATIC volatile size_t pending_pkt;
|
||||||
|
|
||||||
|
// Results from parsing a command response packet.
|
||||||
|
STATIC bool cmd_response_received;
|
||||||
|
STATIC uint16_t cmd_response_opcode;
|
||||||
|
STATIC uint8_t cmd_response_status;
|
||||||
|
STATIC size_t cmd_response_len;
|
||||||
|
STATIC uint8_t* cmd_response_data;
|
||||||
|
|
||||||
|
STATIC volatile bool hci_poll_in_progress = false;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if HCI_DEBUG
|
||||||
|
#include "hci_debug.c"
|
||||||
|
#endif // HCI_DEBUG
|
||||||
|
|
||||||
|
STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) {
|
||||||
|
h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t*) pkt_data;
|
||||||
|
|
||||||
|
if (pkt->pb != ACL_DATA_PB_MIDDLE) {
|
||||||
|
// This is the start of a fragmented acl_data packet or is a full packet.
|
||||||
|
memcpy(acl_data_buffer, pkt->data, pkt->data_len);
|
||||||
|
acl_data_len = pkt->data_len;
|
||||||
|
} else {
|
||||||
|
// This is a middle or end fragment of acl data.
|
||||||
|
// Append to the accumulated data so far.
|
||||||
|
memcpy(&acl_data_buffer[acl_data_len], pkt->data, pkt->data_len);
|
||||||
|
acl_data_len += pkt->data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
acl_data_t *acl = (acl_data_t *) &acl_data_buffer;
|
||||||
|
if (acl_data_len != sizeof(acl) + acl->acl_data_len) {
|
||||||
|
// We don't have the full packet yet.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acl->cid == BT_L2CAP_CID_ATT) {
|
||||||
|
att_process_data(pkt->handle, acl->acl_data_len, acl->acl_data);
|
||||||
|
}
|
||||||
|
// } else if (aclHdr->cid == BT_L2CAP_CID_LE_SIG) {
|
||||||
|
// L2CAPSignaling.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &rx_buffer[1 + sizeof(HCIACLHdr)]);
|
||||||
|
// } else {
|
||||||
|
// struct __attribute__ ((packed)) {
|
||||||
|
// uint8_t op;
|
||||||
|
// uint8_t id;
|
||||||
|
// uint16_t length;
|
||||||
|
// uint16_t reason;
|
||||||
|
// uint16_t localCid;
|
||||||
|
// uint16_t remoteCid;
|
||||||
|
// } l2capRejectCid= { 0x01, 0x00, 0x006, 0x0002, aclHdr->cid, 0x0000 };
|
||||||
|
|
||||||
|
// sendAclPkt(aclHdr->handle & 0x0fff, 0x0005, sizeof(l2capRejectCid), &l2capRejectCid);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process number of completed packets. Reduce number of pending packets by reported
|
||||||
|
// number of completed.
|
||||||
|
STATIC void process_num_comp_pkts(uint16_t handle, uint16_t num_pkts) {
|
||||||
|
if (num_pkts && pending_pkt > num_pkts) {
|
||||||
|
pending_pkt -= num_pkts;
|
||||||
|
} else {
|
||||||
|
pending_pkt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
|
||||||
|
{
|
||||||
|
h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t*) pkt_data;
|
||||||
|
|
||||||
|
switch (pkt->evt) {
|
||||||
|
case BT_HCI_EVT_DISCONN_COMPLETE: {
|
||||||
|
struct bt_hci_evt_disconn_complete *disconn_complete =
|
||||||
|
(struct bt_hci_evt_disconn_complete*) pkt->params;
|
||||||
|
(void) disconn_complete;
|
||||||
|
|
||||||
|
att_remove_connection(disconn_complete->handle, disconn_complete->reason);
|
||||||
|
//FIX L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BT_HCI_EVT_CMD_COMPLETE: {
|
||||||
|
struct cmd_complete_with_status {
|
||||||
|
struct bt_hci_evt_cmd_complete cmd_complete;
|
||||||
|
struct bt_hci_evt_cc_status cc_status;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct cmd_complete_with_status *evt = (struct cmd_complete_with_status *) pkt->params;
|
||||||
|
|
||||||
|
num_command_packets_allowed = evt->cmd_complete.ncmd;
|
||||||
|
|
||||||
|
cmd_response_received = true;
|
||||||
|
cmd_response_opcode = evt->cmd_complete.opcode;
|
||||||
|
cmd_response_status = evt->cc_status.status;
|
||||||
|
// All the bytes following cmd_complete, -including- the status byte, which is
|
||||||
|
// included in all the _bt_hci_rp_* structs.
|
||||||
|
cmd_response_data = (uint8_t *) &evt->cc_status;
|
||||||
|
// Includes status byte.
|
||||||
|
cmd_response_len = pkt->param_len - sizeof_field(struct cmd_complete_with_status, cmd_complete);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BT_HCI_EVT_CMD_STATUS: {
|
||||||
|
struct bt_hci_evt_cmd_status *evt = (struct bt_hci_evt_cmd_status *) pkt->params;
|
||||||
|
|
||||||
|
num_command_packets_allowed = evt->ncmd;
|
||||||
|
|
||||||
|
cmd_response_received = true;
|
||||||
|
cmd_response_opcode = evt->opcode;
|
||||||
|
cmd_response_status = evt->status;
|
||||||
|
cmd_response_data = NULL;
|
||||||
|
cmd_response_len = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BT_HCI_EVT_NUM_COMPLETED_PACKETS: {
|
||||||
|
struct bt_hci_evt_num_completed_packets *evt =
|
||||||
|
(struct bt_hci_evt_num_completed_packets *) pkt->params;
|
||||||
|
|
||||||
|
// Start at zero-th pair: (conn handle, num completed packets).
|
||||||
|
struct bt_hci_handle_count *handle_and_count = &(evt->h[0]);
|
||||||
|
for (uint8_t i = 0; i < evt->num_handles; i++) {
|
||||||
|
process_num_comp_pkts(handle_and_count->handle, handle_and_count->count);
|
||||||
|
handle_and_count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BT_HCI_EVT_LE_META_EVENT: {
|
||||||
|
struct bt_hci_evt_le_meta_event *meta_evt = (struct bt_hci_evt_le_meta_event *) pkt->params;
|
||||||
|
uint8_t *le_evt = pkt->params + sizeof (struct bt_hci_evt_le_meta_event);
|
||||||
|
|
||||||
|
if (meta_evt->subevent == BT_HCI_EVT_LE_CONN_COMPLETE) {
|
||||||
|
// Advertising stops when connection occurs.
|
||||||
|
// We don't tell the adapter to stop, because stopping advertising
|
||||||
|
// when it's already stopped seems to exercise a bug in the ESP32 HCI code:
|
||||||
|
// It doesn't return a response.
|
||||||
|
bleio_adapter_advertising_was_stopped(&common_hal_bleio_adapter_obj);
|
||||||
|
|
||||||
|
struct bt_hci_evt_le_conn_complete *le_conn_complete =
|
||||||
|
(struct bt_hci_evt_le_conn_complete *) le_evt;
|
||||||
|
|
||||||
|
if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) {
|
||||||
|
att_add_connection(
|
||||||
|
le_conn_complete->handle,
|
||||||
|
le_conn_complete->role,
|
||||||
|
&le_conn_complete->peer_addr,
|
||||||
|
le_conn_complete->interval,
|
||||||
|
le_conn_complete->latency,
|
||||||
|
le_conn_complete->supv_timeout,
|
||||||
|
le_conn_complete->clock_accuracy);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (meta_evt->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
|
||||||
|
struct bt_hci_evt_le_advertising_info *le_advertising_info =
|
||||||
|
(struct bt_hci_evt_le_advertising_info *) le_evt;
|
||||||
|
if (le_advertising_info->evt_type == BT_HCI_ADV_DIRECT_IND) {
|
||||||
|
//FIX
|
||||||
|
// last byte is RSSI
|
||||||
|
// GAP.handleLeAdvertisingReport(leAdvertisingReport->type,
|
||||||
|
// leAdvertisingReport->peerBdaddrType,
|
||||||
|
// leAdvertisingReport->peerBdaddr,
|
||||||
|
// leAdvertisingReport->eirLength,
|
||||||
|
// leAdvertisingReport->eirData,
|
||||||
|
// rssi); //FIX, don't separate
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
#if HCI_DEBUG
|
||||||
|
mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_hci_reset(void) {
|
||||||
|
rx_idx = 0;
|
||||||
|
pending_pkt = 0;
|
||||||
|
hci_poll_in_progress = false;
|
||||||
|
bleio_att_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_poll_for_incoming_pkt(void) {
|
||||||
|
common_hal_mcu_disable_interrupts();
|
||||||
|
if (hci_poll_in_progress) {
|
||||||
|
common_hal_mcu_enable_interrupts();
|
||||||
|
return HCI_OK;
|
||||||
|
}
|
||||||
|
hci_poll_in_progress = true;
|
||||||
|
common_hal_mcu_enable_interrupts();
|
||||||
|
|
||||||
|
// Assert RTS low to say we're ready to read data.
|
||||||
|
common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false);
|
||||||
|
|
||||||
|
int errcode = 0;
|
||||||
|
bool packet_is_complete = false;
|
||||||
|
|
||||||
|
// Read bytes until we run out. There may be more than one packet in the input buffer.
|
||||||
|
while (!packet_is_complete &&
|
||||||
|
common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart) > 0) {
|
||||||
|
|
||||||
|
// Read just one character a a time, so we don't accidentally get part of a second
|
||||||
|
// packet.
|
||||||
|
size_t num_read =
|
||||||
|
common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode);
|
||||||
|
if (num_read == 0) {
|
||||||
|
return HCI_OK;
|
||||||
|
}
|
||||||
|
if (errcode) {
|
||||||
|
if (errcode == EAGAIN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hci_poll_in_progress = false;
|
||||||
|
mp_printf(&mp_plat_print, "HCI_READ_ERROR, errcode: %x\n", errcode);
|
||||||
|
return HCI_READ_ERROR;
|
||||||
|
}
|
||||||
|
rx_idx++;
|
||||||
|
if (rx_idx >= sizeof(rx_buffer)) {
|
||||||
|
// Incoming packet is too large. Should not happen.
|
||||||
|
return HCI_READ_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rx_buffer[0]) {
|
||||||
|
case H4_ACL:
|
||||||
|
if (rx_idx >= sizeof(h4_hci_acl_pkt_t)) {
|
||||||
|
const size_t total_len =
|
||||||
|
sizeof(h4_hci_acl_pkt_t) + ((h4_hci_acl_pkt_t *) rx_buffer)->data_len;
|
||||||
|
if (rx_idx == total_len) {
|
||||||
|
packet_is_complete = true;
|
||||||
|
}
|
||||||
|
if (rx_idx > total_len) {
|
||||||
|
return HCI_PACKET_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H4_EVT:
|
||||||
|
if (rx_idx >= sizeof(h4_hci_evt_pkt_t)) {
|
||||||
|
const size_t total_len =
|
||||||
|
sizeof(h4_hci_evt_pkt_t) + ((h4_hci_evt_pkt_t *) rx_buffer)->param_len;
|
||||||
|
if (rx_idx == total_len) {
|
||||||
|
packet_is_complete = true;
|
||||||
|
}
|
||||||
|
if (rx_idx > total_len) {
|
||||||
|
return HCI_PACKET_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown or bad packet type. Start over.
|
||||||
|
rx_idx = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end while
|
||||||
|
|
||||||
|
if (packet_is_complete) {
|
||||||
|
// Stop incoming data while processing packet.
|
||||||
|
common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
|
||||||
|
size_t pkt_len = rx_idx;
|
||||||
|
|
||||||
|
// Reset for next packet.
|
||||||
|
rx_idx = 0;
|
||||||
|
packet_is_complete = false;
|
||||||
|
|
||||||
|
switch (rx_buffer[0]) {
|
||||||
|
case H4_ACL:
|
||||||
|
#if HCI_DEBUG
|
||||||
|
dump_acl_pkt(false, pkt_len, rx_buffer);
|
||||||
|
#endif
|
||||||
|
process_acl_data_pkt(pkt_len, rx_buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H4_EVT:
|
||||||
|
#if HCI_DEBUG
|
||||||
|
dump_evt_pkt(false, pkt_len, rx_buffer);
|
||||||
|
#endif
|
||||||
|
process_evt_pkt(pkt_len, rx_buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
#if HCI_DEBUG
|
||||||
|
mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let incoming bytes flow again.
|
||||||
|
common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All done with this batch. Hold off receiving bytes until we're ready again.
|
||||||
|
///common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true);
|
||||||
|
hci_poll_in_progress = false;
|
||||||
|
return HCI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STATIC hci_result_t write_pkt(uint8_t *buffer, size_t len) {
|
||||||
|
// Wait for CTS to go low before writing to HCI adapter.
|
||||||
|
uint64_t start = supervisor_ticks_ms64();
|
||||||
|
|
||||||
|
while (common_hal_digitalio_digitalinout_get_value(common_hal_bleio_adapter_obj.cts_digitalinout)) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
if (supervisor_ticks_ms64() - start > CTS_TIMEOUT_MSECS) {
|
||||||
|
return HCI_WRITE_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int errcode = 0;
|
||||||
|
common_hal_busio_uart_write(common_hal_bleio_adapter_obj.hci_uart, buffer, len, &errcode);
|
||||||
|
if (errcode) {
|
||||||
|
return HCI_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HCI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* params) {
|
||||||
|
uint8_t cmd_pkt_len = sizeof(h4_hci_cmd_pkt_t) + params_len;
|
||||||
|
uint8_t tx_buffer[cmd_pkt_len];
|
||||||
|
|
||||||
|
// cmd header is at the beginning of tx_buffer
|
||||||
|
h4_hci_cmd_pkt_t *cmd_pkt = (h4_hci_cmd_pkt_t *) tx_buffer;
|
||||||
|
cmd_pkt->pkt_type = H4_CMD;
|
||||||
|
cmd_pkt->opcode = opcode;
|
||||||
|
cmd_pkt->param_len = params_len;
|
||||||
|
|
||||||
|
memcpy(cmd_pkt->params, params, params_len);
|
||||||
|
|
||||||
|
#if HCI_DEBUG
|
||||||
|
dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int result = write_pkt(tx_buffer, cmd_pkt_len);
|
||||||
|
if (result != HCI_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_response_received = false;
|
||||||
|
|
||||||
|
// Wait for a response. Note that other packets may be received that are not
|
||||||
|
// command responses.
|
||||||
|
uint64_t start = supervisor_ticks_ms64();
|
||||||
|
while (supervisor_ticks_ms64() - start < RESPONSE_TIMEOUT_MSECS) {
|
||||||
|
// RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
if (cmd_response_received && cmd_response_opcode == opcode) {
|
||||||
|
// If this is definitely a response to the command that was sent,
|
||||||
|
// return the status value, which will will be
|
||||||
|
// BT_HCI_ERR_SUCCESS (0x00) if the command succeeded,
|
||||||
|
// or a BT_HCI_ERR_x value (> 0x00) if there was a problem.
|
||||||
|
return cmd_response_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No I/O error, but no response sent back in time.
|
||||||
|
return HCI_RESPONSE_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint16_t data_len, uint8_t *data) {
|
||||||
|
// Wait for all backlogged packets to finish.
|
||||||
|
while (pending_pkt >= common_hal_bleio_adapter_obj.max_acl_num_buffers) {
|
||||||
|
// RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt();
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// buf_len is size of entire packet including header.
|
||||||
|
const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + sizeof(acl_data_t) + data_len;
|
||||||
|
uint8_t tx_buffer[buf_len];
|
||||||
|
|
||||||
|
h4_hci_acl_pkt_t *acl_pkt = (h4_hci_acl_pkt_t *) tx_buffer;
|
||||||
|
acl_data_t *acl_data = (acl_data_t *) acl_pkt->data;
|
||||||
|
acl_pkt->pkt_type = H4_ACL;
|
||||||
|
acl_pkt->handle = handle;
|
||||||
|
acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH;
|
||||||
|
acl_pkt->bc = 0;
|
||||||
|
acl_pkt->data_len = (uint16_t)(sizeof(acl_data_t) + data_len);
|
||||||
|
acl_data->acl_data_len = data_len;
|
||||||
|
acl_data->cid = cid;
|
||||||
|
|
||||||
|
memcpy(&acl_data->acl_data, data, data_len);
|
||||||
|
|
||||||
|
#if HCI_DEBUG
|
||||||
|
dump_acl_pkt(true, buf_len, tx_buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pending_pkt++;
|
||||||
|
|
||||||
|
int errcode = 0;
|
||||||
|
common_hal_busio_uart_write(common_hal_bleio_adapter_obj.hci_uart, tx_buffer, buf_len, &errcode);
|
||||||
|
if (errcode) {
|
||||||
|
return HCI_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
return HCI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_reset(void) {
|
||||||
|
return send_command(BT_HCI_OP_RESET, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_version, uint16_t *manufacturer, uint16_t *lmp_subversion) {
|
||||||
|
hci_result_t result = send_command(BT_HCI_OP_READ_LOCAL_VERSION_INFO, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_read_local_version_info *response =
|
||||||
|
(struct bt_hci_rp_read_local_version_info *) cmd_response_data;
|
||||||
|
*hci_version = response->hci_version;
|
||||||
|
*hci_revision = response->hci_revision;
|
||||||
|
*lmp_version = response->lmp_version;
|
||||||
|
*manufacturer = response->manufacturer;
|
||||||
|
*lmp_subversion = response->lmp_subversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_read_bd_addr(bt_addr_t *addr) {
|
||||||
|
int result = send_command(BT_HCI_OP_READ_BD_ADDR, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_read_bd_addr *response = (struct bt_hci_rp_read_bd_addr *) cmd_response_data;
|
||||||
|
memcpy(addr->val, response->bdaddr.val, sizeof_field(bt_addr_t, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_read_rssi(uint16_t handle, int *rssi) {
|
||||||
|
int result = send_command(BT_HCI_OP_READ_RSSI, sizeof(handle), &handle);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_read_rssi *response = (struct bt_hci_rp_read_rssi *) cmd_response_data;
|
||||||
|
*rssi = response->rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_set_event_mask(uint64_t event_mask) {
|
||||||
|
return send_command(BT_HCI_OP_SET_EVENT_MASK, sizeof(event_mask), &event_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_read_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num) {
|
||||||
|
int result = send_command(BT_HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_le_read_buffer_size *response =
|
||||||
|
(struct bt_hci_rp_le_read_buffer_size *) cmd_response_data;
|
||||||
|
*le_max_len = response->le_max_len;
|
||||||
|
*le_max_num = response->le_max_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_read_buffer_size(uint16_t *acl_max_len, uint8_t *sco_max_len, uint16_t *acl_max_num, uint16_t *sco_max_num) {
|
||||||
|
int result = send_command(BT_HCI_OP_READ_BUFFER_SIZE, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_read_buffer_size *response =
|
||||||
|
(struct bt_hci_rp_read_buffer_size *) cmd_response_data;
|
||||||
|
*acl_max_len = response->acl_max_len;
|
||||||
|
*sco_max_len = response->sco_max_len;
|
||||||
|
*acl_max_num = response->acl_max_num;
|
||||||
|
*sco_max_num = response->sco_max_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_random_address(uint8_t addr[6]) {
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, 6, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t type, uint8_t own_addr_type, bt_addr_le_t *direct_addr, uint8_t channel_map, uint8_t filter_policy) {
|
||||||
|
struct bt_hci_cp_le_set_adv_param params = {
|
||||||
|
.min_interval = min_interval,
|
||||||
|
.max_interval = max_interval,
|
||||||
|
.type = type,
|
||||||
|
.own_addr_type = own_addr_type,
|
||||||
|
// .direct_addr set below.
|
||||||
|
.channel_map = channel_map,
|
||||||
|
.filter_policy = filter_policy,
|
||||||
|
};
|
||||||
|
params.direct_addr.type = direct_addr->type;
|
||||||
|
memcpy(params.direct_addr.a.val, direct_addr->a.val, sizeof(params.direct_addr.a.val));
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_extended_advertising_parameters(uint8_t handle, uint16_t props, uint32_t prim_min_interval, uint32_t prim_max_interval, uint8_t prim_channel_map, uint8_t own_addr_type, bt_addr_le_t *peer_addr, uint8_t filter_policy, int8_t tx_power, uint8_t prim_adv_phy, uint8_t sec_adv_max_skip, uint8_t sec_adv_phy, uint8_t sid, uint8_t scan_req_notify_enable) {
|
||||||
|
struct bt_hci_cp_le_set_ext_adv_param params = {
|
||||||
|
.handle = handle,
|
||||||
|
.props = props,
|
||||||
|
// .prim_min_interval and .prim_max_interval set below
|
||||||
|
.prim_channel_map = prim_channel_map,
|
||||||
|
.own_addr_type = own_addr_type,
|
||||||
|
// .peer_addr set below.
|
||||||
|
.tx_power = tx_power,
|
||||||
|
.sec_adv_max_skip = sec_adv_max_skip,
|
||||||
|
.sec_adv_phy = sec_adv_phy,
|
||||||
|
.sid = sid,
|
||||||
|
.scan_req_notify_enable = scan_req_notify_enable,
|
||||||
|
};
|
||||||
|
// Assumes little-endian.
|
||||||
|
memcpy(params.prim_min_interval, (void *) &prim_min_interval,
|
||||||
|
sizeof_field(struct bt_hci_cp_le_set_ext_adv_param, prim_min_interval));
|
||||||
|
memcpy(params.prim_max_interval, (void *) &prim_max_interval,
|
||||||
|
sizeof_field(struct bt_hci_cp_le_set_ext_adv_param, prim_max_interval));
|
||||||
|
memcpy(params.peer_addr.a.val, peer_addr->a.val, sizeof_field(bt_addr_le_t, a.val));
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_EXT_ADV_PARAM, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_read_maximum_advertising_data_length(uint16_t *max_adv_data_len) {
|
||||||
|
int result = send_command(BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_le_read_max_adv_data_len *response =
|
||||||
|
(struct bt_hci_rp_le_read_max_adv_data_len *) cmd_response_data;
|
||||||
|
*max_adv_data_len = response->max_adv_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_read_local_supported_features(uint8_t features[8]) {
|
||||||
|
int result = send_command(BT_HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
|
||||||
|
if (result == HCI_OK) {
|
||||||
|
struct bt_hci_rp_le_read_local_features *response =
|
||||||
|
(struct bt_hci_rp_le_read_local_features *) cmd_response_data;
|
||||||
|
memcpy(features, response->features,
|
||||||
|
sizeof_field(struct bt_hci_rp_le_read_local_features, features));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_advertising_data(uint8_t len, uint8_t data[]) {
|
||||||
|
struct bt_hci_cp_le_set_adv_data params = {
|
||||||
|
// Zero out unused data bytes.
|
||||||
|
.data = { 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
params.len = len;
|
||||||
|
memcpy(params.data, data, len);
|
||||||
|
|
||||||
|
// All data bytes are sent even if some are unused.
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_extended_advertising_data(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len, uint8_t data[]) {
|
||||||
|
const uint8_t max_len = sizeof_field(struct bt_hci_cp_le_set_ext_adv_data, data);
|
||||||
|
uint8_t valid_len = MIN(len, max_len);
|
||||||
|
struct bt_hci_cp_le_set_ext_adv_data params = {
|
||||||
|
.handle = handle,
|
||||||
|
.op = op,
|
||||||
|
.frag_pref = frag_pref,
|
||||||
|
.len = valid_len,
|
||||||
|
};
|
||||||
|
memcpy(params.data, data, valid_len);
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(params) - (max_len - valid_len), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_scan_response_data(uint8_t len, uint8_t data[]) {
|
||||||
|
struct bt_hci_cp_le_set_scan_rsp_data params = {
|
||||||
|
// Zero out unused data bytes.
|
||||||
|
.data = { 0 },
|
||||||
|
};
|
||||||
|
params.len = len;
|
||||||
|
memcpy(params.data, data, len);
|
||||||
|
|
||||||
|
// All data bytes are sent even if some are unused.
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_advertising_enable(uint8_t enable) {
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_extended_advertising_enable(uint8_t enable, uint8_t set_num, uint8_t handle[], uint16_t duration[], uint8_t max_ext_adv_evts[]) {
|
||||||
|
uint8_t params[sizeof(struct bt_hci_cp_le_set_ext_adv_enable) +
|
||||||
|
set_num * (sizeof(struct bt_hci_ext_adv_set))];
|
||||||
|
struct bt_hci_cp_le_set_ext_adv_enable *params_p = (struct bt_hci_cp_le_set_ext_adv_enable *) ¶ms;
|
||||||
|
params_p->enable = enable;
|
||||||
|
params_p->set_num = set_num;
|
||||||
|
for (size_t i = 0; i < set_num; i++) {
|
||||||
|
params_p->s[i].handle = handle[i];
|
||||||
|
params_p->s[i].duration = duration[i];
|
||||||
|
params_p->s[i].max_ext_adv_evts = max_ext_adv_evts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_scan_parameters(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t addr_type, uint8_t filter_policy) {
|
||||||
|
struct bt_hci_cp_le_set_scan_param params = {
|
||||||
|
.scan_type = scan_type,
|
||||||
|
.interval = interval,
|
||||||
|
.window = window,
|
||||||
|
.addr_type = addr_type,
|
||||||
|
.filter_policy = filter_policy,
|
||||||
|
};
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup) {
|
||||||
|
struct bt_hci_cp_le_set_scan_enable params = {
|
||||||
|
.enable = enable,
|
||||||
|
.filter_dup = filter_dup,
|
||||||
|
};
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_create_conn(uint16_t scan_interval, uint16_t scan_window, uint8_t filter_policy, bt_addr_le_t *peer_addr, uint8_t own_addr_type, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t min_ce_len, uint16_t max_ce_len) {
|
||||||
|
struct bt_hci_cp_le_create_conn params = {
|
||||||
|
.scan_interval = scan_interval,
|
||||||
|
.scan_window = scan_window,
|
||||||
|
.filter_policy = filter_policy,
|
||||||
|
// .peer_addr is set below
|
||||||
|
.own_addr_type = own_addr_type,
|
||||||
|
.conn_interval_min = conn_interval_min,
|
||||||
|
.conn_interval_max = conn_interval_max,
|
||||||
|
.conn_latency = conn_latency,
|
||||||
|
.supervision_timeout = supervision_timeout,
|
||||||
|
.min_ce_len = min_ce_len,
|
||||||
|
.max_ce_len = max_ce_len,
|
||||||
|
};
|
||||||
|
params.peer_addr.type = peer_addr->type;
|
||||||
|
memcpy(params.peer_addr.a.val, peer_addr->a.val, sizeof(params.peer_addr.a.val));
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_CREATE_CONN, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_cancel_conn(void) {
|
||||||
|
return send_command(BT_HCI_OP_CONNECT_CANCEL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_le_conn_update(uint16_t handle, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
|
||||||
|
struct hci_cp_le_conn_update params = {
|
||||||
|
.handle = handle,
|
||||||
|
.conn_interval_min = conn_interval_min,
|
||||||
|
.conn_interval_max = conn_interval_max,
|
||||||
|
.conn_latency = conn_latency,
|
||||||
|
.supervision_timeout = supervision_timeout,
|
||||||
|
.min_ce_len = 4,
|
||||||
|
.max_ce_len = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_LE_CONN_UPDATE, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_result_t hci_disconnect(uint16_t handle) {
|
||||||
|
struct bt_hci_cp_disconnect params = {
|
||||||
|
.handle = handle,
|
||||||
|
.reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN,
|
||||||
|
};
|
||||||
|
|
||||||
|
return send_command(BT_HCI_OP_DISCONNECT, sizeof(params), ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hci_check_error(hci_result_t result) {
|
||||||
|
switch (result) {
|
||||||
|
case HCI_OK:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_RESPONSE_TIMEOUT:
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Timeout waiting for HCI response"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_WRITE_TIMEOUT:
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Timeout waiting to write HCI request"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_READ_ERROR:
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Error reading from HCI adapter"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_WRITE_ERROR:
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_PACKET_SIZE_ERROR:
|
||||||
|
mp_raise_RuntimeError(translate("HCI packet size mismatch"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case HCI_ATT_ERROR:
|
||||||
|
mp_raise_RuntimeError(translate("Error in ATT protocol code"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Should be an HCI status error, > 0.
|
||||||
|
if (result > 0) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("HCI status error: %02x"), result);
|
||||||
|
} else {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Unknown hci_result_t: %d"), result);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
81
devices/ble_hci/common-hal/_bleio/hci.h
Normal file
81
devices/ble_hci/common-hal/_bleio/hci.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
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 MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
|
||||||
|
#define MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common-hal/_bleio/hci_include/hci.h"
|
||||||
|
#include "common-hal/_bleio/hci_include/hci_err.h"
|
||||||
|
|
||||||
|
// Incomplete forward declaration to get around mutually-dependent include files.
|
||||||
|
typedef struct _bleio_adapter_obj_t bleio_adapter_obj_t;
|
||||||
|
|
||||||
|
// An hci_result_t is one of the HCI_x values below,
|
||||||
|
// or it is > 0 and is an HCI command status value (see hci_include/hci_err.h)
|
||||||
|
typedef int hci_result_t;
|
||||||
|
#define HCI_OK (0)
|
||||||
|
#define HCI_RESPONSE_TIMEOUT (-1)
|
||||||
|
#define HCI_WRITE_TIMEOUT (-2)
|
||||||
|
#define HCI_READ_ERROR (-3)
|
||||||
|
#define HCI_WRITE_ERROR (-4)
|
||||||
|
#define HCI_ATT_ERROR (-5)
|
||||||
|
#define HCI_PACKET_SIZE_ERROR (-6)
|
||||||
|
|
||||||
|
extern void bleio_hci_reset(void);
|
||||||
|
|
||||||
|
void hci_check_error(hci_result_t result);
|
||||||
|
|
||||||
|
hci_result_t hci_disconnect(uint16_t handle);
|
||||||
|
|
||||||
|
hci_result_t hci_le_cancel_conn(void);
|
||||||
|
hci_result_t hci_le_conn_update(uint16_t handle, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout);
|
||||||
|
hci_result_t hci_le_create_conn(uint16_t scan_interval, uint16_t scan_window, uint8_t filter_policy, bt_addr_le_t *peer_addr, uint8_t own_addr_type, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t min_ce_len, uint16_t max_ce_len);
|
||||||
|
|
||||||
|
hci_result_t hci_le_read_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num);
|
||||||
|
hci_result_t hci_le_read_maximum_advertising_data_length(uint16_t *max_adv_data_len);
|
||||||
|
hci_result_t hci_le_read_local_supported_features(uint8_t features[8]);
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_advertising_data(uint8_t length, uint8_t data[]);
|
||||||
|
hci_result_t hci_le_set_advertising_enable(uint8_t enable);
|
||||||
|
hci_result_t hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t type, uint8_t own_addr_type, bt_addr_le_t *direct_addr, uint8_t channel_map, uint8_t filter_policy);
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_extended_advertising_data(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len, uint8_t data[]);
|
||||||
|
hci_result_t hci_le_set_extended_advertising_enable(uint8_t enable, uint8_t set_num, uint8_t handle[], uint16_t duration[], uint8_t max_ext_adv_evts[]);
|
||||||
|
hci_result_t hci_le_set_extended_advertising_parameters(uint8_t handle, uint16_t props, uint32_t prim_min_interval, uint32_t prim_max_interval, uint8_t prim_channel_map, uint8_t own_addr_type, bt_addr_le_t *peer_addr, uint8_t filter_policy, int8_t tx_power, uint8_t prim_adv_phy, uint8_t sec_adv_max_skip, uint8_t sec_adv_phy, uint8_t sid, uint8_t scan_req_notify_enable);
|
||||||
|
|
||||||
|
hci_result_t hci_le_set_random_address(uint8_t addr[6]);
|
||||||
|
hci_result_t hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup);
|
||||||
|
hci_result_t hci_le_set_scan_parameters(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t addr_type, uint8_t filter_policy);
|
||||||
|
hci_result_t hci_le_set_scan_response_data(uint8_t length, uint8_t data[]);
|
||||||
|
|
||||||
|
hci_result_t hci_poll_for_incoming_pkt(void);
|
||||||
|
|
||||||
|
hci_result_t hci_read_bd_addr(bt_addr_t *addr);
|
||||||
|
hci_result_t hci_read_buffer_size(uint16_t *acl_max_len, uint8_t *sco_max_len, uint16_t *acl_max_num, uint16_t *sco_max_num);
|
||||||
|
hci_result_t hci_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_version, uint16_t *manufacturer, uint16_t *lmp_subversion);
|
||||||
|
hci_result_t hci_read_rssi(uint16_t handle, int *rssi);
|
||||||
|
|
||||||
|
hci_result_t hci_reset(void);
|
||||||
|
|
||||||
|
hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint16_t data_len, uint8_t *data);
|
||||||
|
hci_result_t hci_set_event_mask(uint64_t event_mask);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
|
335
devices/ble_hci/common-hal/_bleio/hci_debug.c
Normal file
335
devices/ble_hci/common-hal/_bleio/hci_debug.c
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file is #include'd in hci.c when HCI_DEBUG is non-zero.
|
||||||
|
|
||||||
|
STATIC const char* att_opcode_name(uint16_t opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case BT_ATT_OP_ERROR_RSP: return "ERROR_RSP";
|
||||||
|
case BT_ATT_OP_MTU_REQ: return "MTU_REQ";
|
||||||
|
case BT_ATT_OP_MTU_RSP: return "MTU_RSP";
|
||||||
|
case BT_ATT_OP_FIND_INFO_REQ: return "FIND_INFO_REQ";
|
||||||
|
case BT_ATT_OP_FIND_INFO_RSP: return "FIND_INFO_RSP";
|
||||||
|
case BT_ATT_OP_FIND_TYPE_REQ: return "FIND_TYPE_REQ";
|
||||||
|
case BT_ATT_OP_FIND_TYPE_RSP: return "FIND_TYPE_RSP";
|
||||||
|
case BT_ATT_OP_READ_TYPE_REQ: return "READ_TYPE_REQ";
|
||||||
|
case BT_ATT_OP_READ_TYPE_RSP: return "READ_TYPE_RSP";
|
||||||
|
case BT_ATT_OP_READ_REQ: return "READ_REQ";
|
||||||
|
case BT_ATT_OP_READ_RSP: return "READ_RSP";
|
||||||
|
case BT_ATT_OP_READ_BLOB_REQ: return "READ_BLOB_REQ";
|
||||||
|
case BT_ATT_OP_READ_BLOB_RSP: return "READ_BLOB_RSP";
|
||||||
|
case BT_ATT_OP_READ_MULT_REQ: return "READ_MULT_REQ";
|
||||||
|
case BT_ATT_OP_READ_MULT_RSP: return "READ_MULT_RSP";
|
||||||
|
case BT_ATT_OP_READ_GROUP_REQ: return "READ_GROUP_REQ";
|
||||||
|
case BT_ATT_OP_READ_GROUP_RSP: return "READ_GROUP_RSP";
|
||||||
|
case BT_ATT_OP_WRITE_REQ: return "WRITE_REQ";
|
||||||
|
case BT_ATT_OP_WRITE_RSP: return "WRITE_RSP";
|
||||||
|
case BT_ATT_OP_PREPARE_WRITE_REQ: return "PREPARE_WRITE_REQ";
|
||||||
|
case BT_ATT_OP_PREPARE_WRITE_RSP: return "PREPARE_WRITE_RSP";
|
||||||
|
case BT_ATT_OP_EXEC_WRITE_REQ: return "EXEC_WRITE_REQ";
|
||||||
|
case BT_ATT_OP_EXEC_WRITE_RSP: return "EXEC_WRITE_RSP";
|
||||||
|
case BT_ATT_OP_NOTIFY: return "NOTIFY";
|
||||||
|
case BT_ATT_OP_INDICATE: return "INDICATE";
|
||||||
|
case BT_ATT_OP_CONFIRM: return "CONFIRM";
|
||||||
|
case BT_ATT_OP_READ_MULT_VL_REQ: return "READ_MULT_VL_REQ";
|
||||||
|
case BT_ATT_OP_READ_MULT_VL_RSP: return "READ_MULT_VL_RSP";
|
||||||
|
case BT_ATT_OP_NOTIFY_MULT: return "NOTIFY_MULT";
|
||||||
|
case BT_ATT_OP_WRITE_CMD: return "WRITE_CMD";
|
||||||
|
case BT_ATT_OP_SIGNED_WRITE_CMD: return "SIGNED_WRITE_CMD";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC const char* hci_evt_name(uint8_t evt) {
|
||||||
|
switch (evt) {
|
||||||
|
case BT_HCI_EVT_UNKNOWN: return "UNKNOWN";
|
||||||
|
case BT_HCI_EVT_VENDOR: return "VENDOR";
|
||||||
|
case BT_HCI_EVT_INQUIRY_COMPLETE: return "INQUIRY_COMPLETE";
|
||||||
|
case BT_HCI_EVT_CONN_COMPLETE: return "CONN_COMPLETE";
|
||||||
|
case BT_HCI_EVT_CONN_REQUEST: return "CONN_REQUEST";
|
||||||
|
case BT_HCI_EVT_DISCONN_COMPLETE: return "DISCONN_COMPLETE";
|
||||||
|
case BT_HCI_EVT_AUTH_COMPLETE: return "AUTH_COMPLETE";
|
||||||
|
case BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE: return "REMOTE_NAME_REQ_COMPLETE";
|
||||||
|
case BT_HCI_EVT_ENCRYPT_CHANGE: return "ENCRYPT_CHANGE";
|
||||||
|
case BT_HCI_EVT_REMOTE_FEATURES: return "REMOTE_FEATURES";
|
||||||
|
case BT_HCI_EVT_REMOTE_VERSION_INFO: return "REMOTE_VERSION_INFO";
|
||||||
|
case BT_HCI_EVT_CMD_COMPLETE: return "CMD_COMPLETE";
|
||||||
|
case BT_HCI_EVT_CMD_STATUS: return "CMD_STATUS";
|
||||||
|
case BT_HCI_EVT_ROLE_CHANGE: return "ROLE_CHANGE";
|
||||||
|
case BT_HCI_EVT_NUM_COMPLETED_PACKETS: return "NUM_COMPLETED_PACKETS";
|
||||||
|
case BT_HCI_EVT_PIN_CODE_REQ: return "PIN_CODE_REQ";
|
||||||
|
case BT_HCI_EVT_LINK_KEY_REQ: return "LINK_KEY_REQ";
|
||||||
|
case BT_HCI_EVT_LINK_KEY_NOTIFY: return "LINK_KEY_NOTIFY";
|
||||||
|
case BT_HCI_EVT_DATA_BUF_OVERFLOW: return "DATA_BUF_OVERFLOW";
|
||||||
|
case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: return "INQUIRY_RESULT_WITH_RSSI";
|
||||||
|
case BT_HCI_EVT_REMOTE_EXT_FEATURES: return "REMOTE_EXT_FEATURES";
|
||||||
|
case BT_HCI_EVT_SYNC_CONN_COMPLETE: return "SYNC_CONN_COMPLETE";
|
||||||
|
case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: return "EXTENDED_INQUIRY_RESULT";
|
||||||
|
case BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE: return "ENCRYPT_KEY_REFRESH_COMPLETE";
|
||||||
|
case BT_HCI_EVT_IO_CAPA_REQ: return "IO_CAPA_REQ";
|
||||||
|
case BT_HCI_EVT_IO_CAPA_RESP: return "IO_CAPA_RESP";
|
||||||
|
case BT_HCI_EVT_USER_CONFIRM_REQ: return "USER_CONFIRM_REQ";
|
||||||
|
case BT_HCI_EVT_USER_PASSKEY_REQ: return "USER_PASSKEY_REQ";
|
||||||
|
case BT_HCI_EVT_SSP_COMPLETE: return "SSP_COMPLETE";
|
||||||
|
case BT_HCI_EVT_USER_PASSKEY_NOTIFY: return "USER_PASSKEY_NOTIFY";
|
||||||
|
case BT_HCI_EVT_LE_META_EVENT: return "LE_META_EVENT";
|
||||||
|
case BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP: return "AUTH_PAYLOAD_TIMEOUT_EXP";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC const char* hci_evt_le_name(uint8_t evt_le) {
|
||||||
|
switch (evt_le) {
|
||||||
|
case BT_HCI_EVT_LE_CONN_COMPLETE: return "LE_CONN_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_ADVERTISING_REPORT: return "LE_ADVERTISING_REPORT";
|
||||||
|
case BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE: return "LE_CONN_UPDATE_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_LTK_REQUEST: return "LE_LTK_REQUEST";
|
||||||
|
case BT_HCI_EVT_LE_CONN_PARAM_REQ: return "LE_CONN_PARAM_REQ";
|
||||||
|
case BT_HCI_EVT_LE_DATA_LEN_CHANGE: return "LE_DATA_LEN_CHANGE";
|
||||||
|
case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE: return "LE_P256_PUBLIC_KEY_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE: return "LE_GENERATE_DHKEY_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_ENH_CONN_COMPLETE: return "LE_ENH_CONN_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_DIRECT_ADV_REPORT: return "LE_DIRECT_ADV_REPORT";
|
||||||
|
case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE: return "LE_PHY_UPDATE_COMPLETE";
|
||||||
|
case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: return "LE_EXT_ADVERTISING_REPORT";
|
||||||
|
case BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED: return "LE_PER_ADV_SYNC_ESTABLISHED";
|
||||||
|
case BT_HCI_EVT_LE_PER_ADVERTISING_REPORT: return "LE_PER_ADVERTISING_REPORT";
|
||||||
|
case BT_HCI_EVT_LE_PER_ADV_SYNC_LOST: return "LE_PER_ADV_SYNC_LOST";
|
||||||
|
case BT_HCI_EVT_LE_SCAN_TIMEOUT: return "LE_SCAN_TIMEOUT";
|
||||||
|
case BT_HCI_EVT_LE_ADV_SET_TERMINATED: return "LE_ADV_SET_TERMINATED";
|
||||||
|
case BT_HCI_EVT_LE_SCAN_REQ_RECEIVED: return "LE_SCAN_REQ_RECEIVED";
|
||||||
|
case BT_HCI_EVT_LE_CHAN_SEL_ALGO: return "LE_CHAN_SEL_ALGO";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC const char* hci_opcode_name(uint16_t opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case BT_OP_NOP: return "NOP";
|
||||||
|
case BT_HCI_OP_INQUIRY: return "INQUIRY";
|
||||||
|
case BT_HCI_OP_INQUIRY_CANCEL: return "INQUIRY_CANCEL";
|
||||||
|
case BT_HCI_OP_CONNECT: return "CONNECT";
|
||||||
|
case BT_HCI_OP_DISCONNECT: return "DISCONNECT";
|
||||||
|
case BT_HCI_OP_CONNECT_CANCEL: return "CONNECT_CANCEL";
|
||||||
|
case BT_HCI_OP_ACCEPT_CONN_REQ: return "ACCEPT_CONN_REQ";
|
||||||
|
case BT_HCI_OP_SETUP_SYNC_CONN: return "SETUP_SYNC_CONN";
|
||||||
|
case BT_HCI_OP_ACCEPT_SYNC_CONN_REQ: return "ACCEPT_SYNC_CONN_REQ";
|
||||||
|
case BT_HCI_OP_REJECT_CONN_REQ: return "REJECT_CONN_REQ";
|
||||||
|
case BT_HCI_OP_LINK_KEY_REPLY: return "LINK_KEY_REPLY";
|
||||||
|
case BT_HCI_OP_LINK_KEY_NEG_REPLY: return "LINK_KEY_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_PIN_CODE_REPLY: return "PIN_CODE_REPLY";
|
||||||
|
case BT_HCI_OP_PIN_CODE_NEG_REPLY: return "PIN_CODE_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_AUTH_REQUESTED: return "AUTH_REQUESTED";
|
||||||
|
case BT_HCI_OP_SET_CONN_ENCRYPT: return "SET_CONN_ENCRYPT";
|
||||||
|
case BT_HCI_OP_REMOTE_NAME_REQUEST: return "REMOTE_NAME_REQUEST";
|
||||||
|
case BT_HCI_OP_REMOTE_NAME_CANCEL: return "REMOTE_NAME_CANCEL";
|
||||||
|
case BT_HCI_OP_READ_REMOTE_FEATURES: return "READ_REMOTE_FEATURES";
|
||||||
|
case BT_HCI_OP_READ_REMOTE_EXT_FEATURES: return "READ_REMOTE_EXT_FEATURES";
|
||||||
|
case BT_HCI_OP_READ_REMOTE_VERSION_INFO: return "READ_REMOTE_VERSION_INFO";
|
||||||
|
case BT_HCI_OP_IO_CAPABILITY_REPLY: return "IO_CAPABILITY_REPLY";
|
||||||
|
case BT_HCI_OP_USER_CONFIRM_REPLY: return "USER_CONFIRM_REPLY";
|
||||||
|
case BT_HCI_OP_USER_CONFIRM_NEG_REPLY: return "USER_CONFIRM_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_USER_PASSKEY_REPLY: return "USER_PASSKEY_REPLY";
|
||||||
|
case BT_HCI_OP_USER_PASSKEY_NEG_REPLY: return "USER_PASSKEY_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_IO_CAPABILITY_NEG_REPLY: return "IO_CAPABILITY_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_SET_EVENT_MASK: return "SET_EVENT_MASK";
|
||||||
|
case BT_HCI_OP_RESET: return "RESET";
|
||||||
|
case BT_HCI_OP_WRITE_LOCAL_NAME: return "WRITE_LOCAL_NAME";
|
||||||
|
case BT_HCI_OP_WRITE_PAGE_TIMEOUT: return "WRITE_PAGE_TIMEOUT";
|
||||||
|
case BT_HCI_OP_WRITE_SCAN_ENABLE: return "WRITE_SCAN_ENABLE";
|
||||||
|
case BT_HCI_OP_READ_TX_POWER_LEVEL: return "READ_TX_POWER_LEVEL";
|
||||||
|
case BT_HCI_OP_SET_CTL_TO_HOST_FLOW: return "SET_CTL_TO_HOST_FLOW";
|
||||||
|
case BT_HCI_OP_HOST_BUFFER_SIZE: return "HOST_BUFFER_SIZE";
|
||||||
|
case BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS: return "HOST_NUM_COMPLETED_PACKETS";
|
||||||
|
case BT_HCI_OP_WRITE_INQUIRY_MODE: return "WRITE_INQUIRY_MODE";
|
||||||
|
case BT_HCI_OP_WRITE_SSP_MODE: return "WRITE_SSP_MODE";
|
||||||
|
case BT_HCI_OP_SET_EVENT_MASK_PAGE_2: return "SET_EVENT_MASK_PAGE_2";
|
||||||
|
case BT_HCI_OP_LE_WRITE_LE_HOST_SUPP: return "LE_WRITE_LE_HOST_SUPP";
|
||||||
|
case BT_HCI_OP_WRITE_SC_HOST_SUPP: return "WRITE_SC_HOST_SUPP";
|
||||||
|
case BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT: return "READ_AUTH_PAYLOAD_TIMEOUT";
|
||||||
|
case BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT: return "WRITE_AUTH_PAYLOAD_TIMEOUT";
|
||||||
|
case BT_HCI_OP_READ_LOCAL_VERSION_INFO: return "READ_LOCAL_VERSION_INFO";
|
||||||
|
case BT_HCI_OP_READ_SUPPORTED_COMMANDS: return "READ_SUPPORTED_COMMANDS";
|
||||||
|
case BT_HCI_OP_READ_LOCAL_EXT_FEATURES: return "READ_LOCAL_EXT_FEATURES";
|
||||||
|
case BT_HCI_OP_READ_LOCAL_FEATURES: return "READ_LOCAL_FEATURES";
|
||||||
|
case BT_HCI_OP_READ_BUFFER_SIZE: return "READ_BUFFER_SIZE";
|
||||||
|
case BT_HCI_OP_READ_BD_ADDR: return "READ_BD_ADDR";
|
||||||
|
case BT_HCI_OP_READ_RSSI: return "READ_RSSI";
|
||||||
|
case BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE: return "READ_ENCRYPTION_KEY_SIZE";
|
||||||
|
case BT_HCI_OP_LE_SET_EVENT_MASK: return "LE_SET_EVENT_MASK";
|
||||||
|
case BT_HCI_OP_LE_READ_BUFFER_SIZE: return "LE_READ_BUFFER_SIZE";
|
||||||
|
case BT_HCI_OP_LE_READ_LOCAL_FEATURES: return "LE_READ_LOCAL_FEATURES";
|
||||||
|
case BT_HCI_OP_LE_SET_RANDOM_ADDRESS: return "LE_SET_RANDOM_ADDRESS";
|
||||||
|
case BT_HCI_OP_LE_SET_ADV_PARAM: return "LE_SET_ADV_PARAM";
|
||||||
|
case BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER: return "LE_READ_ADV_CHAN_TX_POWER";
|
||||||
|
case BT_HCI_OP_LE_SET_ADV_DATA: return "LE_SET_ADV_DATA";
|
||||||
|
case BT_HCI_OP_LE_SET_SCAN_RSP_DATA: return "LE_SET_SCAN_RSP_DATA";
|
||||||
|
case BT_HCI_OP_LE_SET_ADV_ENABLE: return "LE_SET_ADV_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_SET_SCAN_PARAM: return "LE_SET_SCAN_PARAM";
|
||||||
|
case BT_HCI_OP_LE_SET_SCAN_ENABLE: return "LE_SET_SCAN_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_CREATE_CONN: return "LE_CREATE_CONN";
|
||||||
|
case BT_HCI_OP_LE_CREATE_CONN_CANCEL: return "LE_CREATE_CONN_CANCEL";
|
||||||
|
case BT_HCI_OP_LE_READ_WL_SIZE: return "LE_READ_WL_SIZE";
|
||||||
|
case BT_HCI_OP_LE_CLEAR_WL: return "LE_CLEAR_WL";
|
||||||
|
case BT_HCI_OP_LE_ADD_DEV_TO_WL: return "LE_ADD_DEV_TO_WL";
|
||||||
|
case BT_HCI_OP_LE_REM_DEV_FROM_WL: return "LE_REM_DEV_FROM_WL";
|
||||||
|
case BT_HCI_OP_LE_CONN_UPDATE: return "LE_CONN_UPDATE";
|
||||||
|
case BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF: return "LE_SET_HOST_CHAN_CLASSIF";
|
||||||
|
case BT_HCI_OP_LE_READ_CHAN_MAP: return "LE_READ_CHAN_MAP";
|
||||||
|
case BT_HCI_OP_LE_READ_REMOTE_FEATURES: return "LE_READ_REMOTE_FEATURES";
|
||||||
|
case BT_HCI_OP_LE_ENCRYPT: return "LE_ENCRYPT";
|
||||||
|
case BT_HCI_OP_LE_RAND: return "LE_RAND";
|
||||||
|
case BT_HCI_OP_LE_START_ENCRYPTION: return "LE_START_ENCRYPTION";
|
||||||
|
case BT_HCI_OP_LE_LTK_REQ_REPLY: return "LE_LTK_REQ_REPLY";
|
||||||
|
case BT_HCI_OP_LE_LTK_REQ_NEG_REPLY: return "LE_LTK_REQ_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_LE_READ_SUPP_STATES: return "LE_READ_SUPP_STATES";
|
||||||
|
case BT_HCI_OP_LE_RX_TEST: return "LE_RX_TEST";
|
||||||
|
case BT_HCI_OP_LE_TX_TEST: return "LE_TX_TEST";
|
||||||
|
case BT_HCI_OP_LE_TEST_END: return "LE_TEST_END";
|
||||||
|
case BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY: return "LE_CONN_PARAM_REQ_REPLY";
|
||||||
|
case BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY: return "LE_CONN_PARAM_REQ_NEG_REPLY";
|
||||||
|
case BT_HCI_OP_LE_SET_DATA_LEN: return "LE_SET_DATA_LEN";
|
||||||
|
case BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN: return "LE_READ_DEFAULT_DATA_LEN";
|
||||||
|
case BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN: return "LE_WRITE_DEFAULT_DATA_LEN";
|
||||||
|
case BT_HCI_OP_LE_P256_PUBLIC_KEY: return "LE_P256_PUBLIC_KEY";
|
||||||
|
case BT_HCI_OP_LE_GENERATE_DHKEY: return "LE_GENERATE_DHKEY";
|
||||||
|
case BT_HCI_OP_LE_ADD_DEV_TO_RL: return "LE_ADD_DEV_TO_RL";
|
||||||
|
case BT_HCI_OP_LE_REM_DEV_FROM_RL: return "LE_REM_DEV_FROM_RL";
|
||||||
|
case BT_HCI_OP_LE_CLEAR_RL: return "LE_CLEAR_RL";
|
||||||
|
case BT_HCI_OP_LE_READ_RL_SIZE: return "LE_READ_RL_SIZE";
|
||||||
|
case BT_HCI_OP_LE_READ_PEER_RPA: return "LE_READ_PEER_RPA";
|
||||||
|
case BT_HCI_OP_LE_READ_LOCAL_RPA: return "LE_READ_LOCAL_RPA";
|
||||||
|
case BT_HCI_OP_LE_SET_ADDR_RES_ENABLE: return "LE_SET_ADDR_RES_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_SET_RPA_TIMEOUT: return "LE_SET_RPA_TIMEOUT";
|
||||||
|
case BT_HCI_OP_LE_READ_MAX_DATA_LEN: return "LE_READ_MAX_DATA_LEN";
|
||||||
|
case BT_HCI_OP_LE_READ_PHY: return "LE_READ_PHY";
|
||||||
|
case BT_HCI_OP_LE_SET_DEFAULT_PHY: return "LE_SET_DEFAULT_PHY";
|
||||||
|
case BT_HCI_OP_LE_SET_PHY: return "LE_SET_PHY";
|
||||||
|
case BT_HCI_OP_LE_ENH_RX_TEST: return "LE_ENH_RX_TEST";
|
||||||
|
case BT_HCI_OP_LE_ENH_TX_TEST: return "LE_ENH_TX_TEST";
|
||||||
|
case BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR: return "LE_SET_ADV_SET_RANDOM_ADDR";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_ADV_PARAM: return "LE_SET_EXT_ADV_PARAM";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_ADV_DATA: return "LE_SET_EXT_ADV_DATA";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA: return "LE_SET_EXT_SCAN_RSP_DATA";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_ADV_ENABLE: return "LE_SET_EXT_ADV_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN: return "LE_READ_MAX_ADV_DATA_LEN";
|
||||||
|
case BT_HCI_OP_LE_READ_NUM_ADV_SETS: return "LE_READ_NUM_ADV_SETS";
|
||||||
|
case BT_HCI_OP_LE_REMOVE_ADV_SET: return "LE_REMOVE_ADV_SET";
|
||||||
|
case BT_HCI_OP_CLEAR_ADV_SETS: return "CLEAR_ADV_SETS";
|
||||||
|
case BT_HCI_OP_LE_SET_PER_ADV_PARAM: return "LE_SET_PER_ADV_PARAM";
|
||||||
|
case BT_HCI_OP_LE_SET_PER_ADV_DATA: return "LE_SET_PER_ADV_DATA";
|
||||||
|
case BT_HCI_OP_LE_SET_PER_ADV_ENABLE: return "LE_SET_PER_ADV_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_SCAN_PARAM: return "LE_SET_EXT_SCAN_PARAM";
|
||||||
|
case BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE: return "LE_SET_EXT_SCAN_ENABLE";
|
||||||
|
case BT_HCI_OP_LE_EXT_CREATE_CONN: return "LE_EXT_CREATE_CONN";
|
||||||
|
case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC: return "LE_PER_ADV_CREATE_SYNC";
|
||||||
|
case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL: return "LE_PER_ADV_CREATE_SYNC_CANCEL";
|
||||||
|
case BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC: return "LE_PER_ADV_TERMINATE_SYNC";
|
||||||
|
case BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST: return "LE_ADD_DEV_TO_PER_ADV_LIST";
|
||||||
|
case BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST: return "LE_REM_DEV_FROM_PER_ADV_LIST";
|
||||||
|
case BT_HCI_OP_LE_CLEAR_PER_ADV_LIST: return "LE_CLEAR_PER_ADV_LIST";
|
||||||
|
case BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE: return "LE_READ_PER_ADV_LIST_SIZE";
|
||||||
|
case BT_HCI_OP_LE_READ_TX_POWER: return "LE_READ_TX_POWER";
|
||||||
|
case BT_HCI_OP_LE_READ_RF_PATH_COMP: return "LE_READ_RF_PATH_COMP";
|
||||||
|
case BT_HCI_OP_LE_WRITE_RF_PATH_COMP: return "LE_WRITE_RF_PATH_COMP";
|
||||||
|
case BT_HCI_OP_LE_SET_PRIVACY_MODE: return "LE_SET_PRIVACY_MODE";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
|
||||||
|
h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data;
|
||||||
|
mp_printf(&mp_plat_print,
|
||||||
|
"%s HCI COMMAND (%x) op: %s (%04x), len: %d, data: ",
|
||||||
|
tx ? "TX->" : "RX<-",
|
||||||
|
pkt->pkt_type,
|
||||||
|
hci_opcode_name(pkt->opcode), pkt->opcode, pkt->param_len);
|
||||||
|
for (size_t i = 0; i < pkt->param_len; i++) {
|
||||||
|
mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
|
||||||
|
}
|
||||||
|
if (pkt_len != sizeof(h4_hci_cmd_pkt_t) + pkt->param_len) {
|
||||||
|
mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
|
||||||
|
}
|
||||||
|
mp_printf(&mp_plat_print, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
|
||||||
|
h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data;
|
||||||
|
acl_data_t *acl = (acl_data_t *) pkt->data;
|
||||||
|
|
||||||
|
mp_printf(&mp_plat_print,
|
||||||
|
"%s HCI ACLDATA (%x) ",
|
||||||
|
tx ? "TX->" : "RX<-", pkt->pkt_type);
|
||||||
|
|
||||||
|
if (pkt->pb != ACL_DATA_PB_MIDDLE && acl->cid == BT_L2CAP_CID_ATT) {
|
||||||
|
// This is the start of a fragmented acl_data packet or is a full packet,
|
||||||
|
// and is an ATT protocol packet.
|
||||||
|
mp_printf(&mp_plat_print, "att: %s (%02x), ", att_opcode_name(acl->acl_data[0]), acl->acl_data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_printf(&mp_plat_print,
|
||||||
|
"handle: %04x, pb: %d, bc: %d, data_len: %d, ",
|
||||||
|
pkt->handle, pkt->pb, pkt->bc, pkt->data_len);
|
||||||
|
|
||||||
|
if (pkt->pb != ACL_DATA_PB_MIDDLE) {
|
||||||
|
// This is the start of a fragmented acl_data packet or is a full packet.
|
||||||
|
mp_printf(&mp_plat_print,
|
||||||
|
"acl data_len: %d, cid: %04x, data: ",
|
||||||
|
acl->acl_data_len, acl->cid);
|
||||||
|
for (size_t i = 0; i < acl->acl_data_len; i++) {
|
||||||
|
mp_printf(&mp_plat_print, "%02x ", acl->acl_data[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < pkt->data_len; i++) {
|
||||||
|
mp_printf(&mp_plat_print, "more data: %02x ", pkt->data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkt_len != sizeof(h4_hci_acl_pkt_t) + pkt->data_len) {
|
||||||
|
mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
|
||||||
|
}
|
||||||
|
mp_printf(&mp_plat_print, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) {
|
||||||
|
h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t *) pkt_data;
|
||||||
|
mp_printf(&mp_plat_print,
|
||||||
|
"%s HCI EVENT (%x) evt: %s (%02x), param_len: %d, data: ",
|
||||||
|
tx ? "TX->" : "RX<-",
|
||||||
|
pkt->pkt_type,
|
||||||
|
pkt->evt == BT_HCI_EVT_LE_META_EVENT
|
||||||
|
? hci_evt_le_name(pkt->params[0])
|
||||||
|
: hci_evt_name(pkt->evt),
|
||||||
|
pkt->evt, pkt->param_len);
|
||||||
|
for (size_t i = 0; i < pkt->param_len; i++) {
|
||||||
|
mp_printf(&mp_plat_print, "%02x ", pkt->params[i]);
|
||||||
|
}
|
||||||
|
if (pkt_len != sizeof(h4_hci_evt_pkt_t) + pkt->param_len) {
|
||||||
|
mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len);
|
||||||
|
}
|
||||||
|
mp_printf(&mp_plat_print, "\n");
|
||||||
|
}
|
2
devices/ble_hci/common-hal/_bleio/hci_include/NOTE.txt
Normal file
2
devices/ble_hci/common-hal/_bleio/hci_include/NOTE.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
The HCI-related include files here were copied from the Zephyr project, from this commit:
|
||||||
|
https://github.com/zephyrproject-rtos/zephyr/tree/0a87f9359edf1ec1c169626df3e19c2b4a4e9646/include/bluetooth
|
101
devices/ble_hci/common-hal/_bleio/hci_include/addr.h
Normal file
101
devices/ble_hci/common-hal/_bleio/hci_include/addr.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// CircuitPython: Adapted from Zephyer include files.
|
||||||
|
/** @file
|
||||||
|
* @brief Bluetooth device address definitions and utilities.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||||
|
* Copyright 2020 Dan Halbert for Adafruit Industries
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_
|
||||||
|
#define ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bluetooth device address definitions and utilities.
|
||||||
|
* @defgroup bt_addr Device Address
|
||||||
|
* @ingroup bluetooth
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BT_ADDR_LE_PUBLIC 0x00
|
||||||
|
#define BT_ADDR_LE_RANDOM 0x01
|
||||||
|
#define BT_ADDR_LE_PUBLIC_ID 0x02
|
||||||
|
#define BT_ADDR_LE_RANDOM_ID 0x03
|
||||||
|
|
||||||
|
/** Bluetooth Device Address */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t val[6];
|
||||||
|
} bt_addr_t;
|
||||||
|
|
||||||
|
/** Bluetooth LE Device Address */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t type;
|
||||||
|
bt_addr_t a;
|
||||||
|
} bt_addr_le_t;
|
||||||
|
|
||||||
|
#define BT_ADDR_ANY ((bt_addr_t[]) { { { 0, 0, 0, 0, 0, 0 } } })
|
||||||
|
#define BT_ADDR_NONE ((bt_addr_t[]) { { \
|
||||||
|
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } })
|
||||||
|
#define BT_ADDR_LE_ANY ((bt_addr_le_t[]) { { 0, { { 0, 0, 0, 0, 0, 0 } } } })
|
||||||
|
#define BT_ADDR_LE_NONE ((bt_addr_le_t[]) { { 0, \
|
||||||
|
{ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } })
|
||||||
|
|
||||||
|
static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b)
|
||||||
|
{
|
||||||
|
return memcmp(a, b, sizeof(*a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b)
|
||||||
|
{
|
||||||
|
return memcmp(a, b, sizeof(*a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src)
|
||||||
|
{
|
||||||
|
memcpy(dst, src, sizeof(*dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src)
|
||||||
|
{
|
||||||
|
memcpy(dst, src, sizeof(*dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BT_ADDR_IS_RPA(a) (((a)->val[5] & 0xc0) == 0x40)
|
||||||
|
#define BT_ADDR_IS_NRPA(a) (((a)->val[5] & 0xc0) == 0x00)
|
||||||
|
#define BT_ADDR_IS_STATIC(a) (((a)->val[5] & 0xc0) == 0xc0)
|
||||||
|
|
||||||
|
#define BT_ADDR_SET_RPA(a) ((a)->val[5] = (((a)->val[5] & 0x3f) | 0x40))
|
||||||
|
#define BT_ADDR_SET_NRPA(a) ((a)->val[5] &= 0x3f)
|
||||||
|
#define BT_ADDR_SET_STATIC(a) ((a)->val[5] |= 0xc0)
|
||||||
|
|
||||||
|
int bt_addr_le_create_nrpa(bt_addr_le_t *addr);
|
||||||
|
int bt_addr_le_create_static(bt_addr_le_t *addr);
|
||||||
|
|
||||||
|
static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr)
|
||||||
|
{
|
||||||
|
if (addr->type != BT_ADDR_LE_RANDOM) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BT_ADDR_IS_RPA(&addr->a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr)
|
||||||
|
{
|
||||||
|
if (addr->type == BT_ADDR_LE_PUBLIC) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BT_ADDR_IS_STATIC(&addr->a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_ */
|
41
devices/ble_hci/common-hal/_bleio/hci_include/att.h
Normal file
41
devices/ble_hci/common-hal/_bleio/hci_include/att.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// CircuitPython: Adapted from Zephyr include file.
|
||||||
|
/** @file
|
||||||
|
* @brief Attribute Protocol handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_
|
||||||
|
#define ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_
|
||||||
|
|
||||||
|
/* Error codes for Error response PDU */
|
||||||
|
#define BT_ATT_ERR_INVALID_HANDLE 0x01
|
||||||
|
#define BT_ATT_ERR_READ_NOT_PERMITTED 0x02
|
||||||
|
#define BT_ATT_ERR_WRITE_NOT_PERMITTED 0x03
|
||||||
|
#define BT_ATT_ERR_INVALID_PDU 0x04
|
||||||
|
#define BT_ATT_ERR_AUTHENTICATION 0x05
|
||||||
|
#define BT_ATT_ERR_NOT_SUPPORTED 0x06
|
||||||
|
#define BT_ATT_ERR_INVALID_OFFSET 0x07
|
||||||
|
#define BT_ATT_ERR_AUTHORIZATION 0x08
|
||||||
|
#define BT_ATT_ERR_PREPARE_QUEUE_FULL 0x09
|
||||||
|
#define BT_ATT_ERR_ATTRIBUTE_NOT_FOUND 0x0a
|
||||||
|
#define BT_ATT_ERR_ATTRIBUTE_NOT_LONG 0x0b
|
||||||
|
#define BT_ATT_ERR_ENCRYPTION_KEY_SIZE 0x0c
|
||||||
|
#define BT_ATT_ERR_INVALID_ATTRIBUTE_LEN 0x0d
|
||||||
|
#define BT_ATT_ERR_UNLIKELY 0x0e
|
||||||
|
#define BT_ATT_ERR_INSUFFICIENT_ENCRYPTION 0x0f
|
||||||
|
#define BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE 0x10
|
||||||
|
#define BT_ATT_ERR_INSUFFICIENT_RESOURCES 0x11
|
||||||
|
#define BT_ATT_ERR_DB_OUT_OF_SYNC 0x12
|
||||||
|
#define BT_ATT_ERR_VALUE_NOT_ALLOWED 0x13
|
||||||
|
|
||||||
|
/* Common Profile Error Codes (from CSS) */
|
||||||
|
#define BT_ATT_ERR_WRITE_REQ_REJECTED 0xfc
|
||||||
|
#define BT_ATT_ERR_CCC_IMPROPER_CONF 0xfd
|
||||||
|
#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe
|
||||||
|
#define BT_ATT_ERR_OUT_OF_RANGE 0xff
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_ */
|
266
devices/ble_hci/common-hal/_bleio/hci_include/att_internal.h
Normal file
266
devices/ble_hci/common-hal/_bleio/hci_include/att_internal.h
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
// CircuitPython: Adapted from Zephyr include file.
|
||||||
|
|
||||||
|
/* att_internal.h - Attribute protocol handling */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
// for __packed
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#define BT_EATT_PSM 0x27
|
||||||
|
#define BT_ATT_DEFAULT_LE_MTU 23
|
||||||
|
#define BT_ATT_TIMEOUT K_SECONDS(30)
|
||||||
|
|
||||||
|
//FIX #if BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU
|
||||||
|
// #define BT_ATT_MTU BT_L2CAP_RX_MTU
|
||||||
|
// #else
|
||||||
|
// #define BT_ATT_MTU CONFIG_BT_L2CAP_TX_MTU
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
struct bt_att_hdr {
|
||||||
|
uint8_t code;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_ATT_OP_ERROR_RSP 0x01
|
||||||
|
struct bt_att_error_rsp {
|
||||||
|
uint8_t request;
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t error;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_ATT_OP_MTU_REQ 0x02
|
||||||
|
struct bt_att_exchange_mtu_req {
|
||||||
|
uint16_t mtu;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_ATT_OP_MTU_RSP 0x03
|
||||||
|
struct bt_att_exchange_mtu_rsp {
|
||||||
|
uint16_t mtu;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Find Information Request */
|
||||||
|
#define BT_ATT_OP_FIND_INFO_REQ 0x04
|
||||||
|
struct bt_att_find_info_req {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Format field values for BT_ATT_OP_FIND_INFO_RSP */
|
||||||
|
#define BT_ATT_INFO_16 0x01
|
||||||
|
#define BT_ATT_INFO_128 0x02
|
||||||
|
|
||||||
|
struct bt_att_info_16 {
|
||||||
|
uint16_t handle;
|
||||||
|
uint16_t uuid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_att_info_128 {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t uuid[16];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Find Information Response */
|
||||||
|
#define BT_ATT_OP_FIND_INFO_RSP 0x05
|
||||||
|
struct bt_att_find_info_rsp {
|
||||||
|
uint8_t format;
|
||||||
|
uint8_t info[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Find By Type Value Request */
|
||||||
|
#define BT_ATT_OP_FIND_TYPE_REQ 0x06
|
||||||
|
struct bt_att_find_type_req {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
uint16_t type;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_att_handle_group {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Find By Type Value Response */
|
||||||
|
#define BT_ATT_OP_FIND_TYPE_RSP 0x07
|
||||||
|
struct bt_att_find_type_rsp {
|
||||||
|
struct bt_att_handle_group list[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read By Type Request */
|
||||||
|
#define BT_ATT_OP_READ_TYPE_REQ 0x08
|
||||||
|
struct bt_att_read_type_req {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
uint8_t uuid[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_att_data {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read By Type Response */
|
||||||
|
#define BT_ATT_OP_READ_TYPE_RSP 0x09
|
||||||
|
struct bt_att_read_type_rsp {
|
||||||
|
uint8_t len;
|
||||||
|
struct bt_att_data data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Request */
|
||||||
|
#define BT_ATT_OP_READ_REQ 0x0a
|
||||||
|
struct bt_att_read_req {
|
||||||
|
uint16_t handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Response */
|
||||||
|
#define BT_ATT_OP_READ_RSP 0x0b
|
||||||
|
struct bt_att_read_rsp {
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Blob Request */
|
||||||
|
#define BT_ATT_OP_READ_BLOB_REQ 0x0c
|
||||||
|
struct bt_att_read_blob_req {
|
||||||
|
uint16_t handle;
|
||||||
|
uint16_t offset;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Blob Response */
|
||||||
|
#define BT_ATT_OP_READ_BLOB_RSP 0x0d
|
||||||
|
struct bt_att_read_blob_rsp {
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Multiple Request */
|
||||||
|
#define BT_ATT_READ_MULT_MIN_LEN_REQ 0x04
|
||||||
|
|
||||||
|
#define BT_ATT_OP_READ_MULT_REQ 0x0e
|
||||||
|
struct bt_att_read_mult_req {
|
||||||
|
uint16_t handles[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Multiple Respose */
|
||||||
|
#define BT_ATT_OP_READ_MULT_RSP 0x0f
|
||||||
|
struct bt_att_read_mult_rsp {
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read by Group Type Request */
|
||||||
|
#define BT_ATT_OP_READ_GROUP_REQ 0x10
|
||||||
|
struct bt_att_read_group_req {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
uint8_t uuid[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_att_group_data {
|
||||||
|
uint16_t start_handle;
|
||||||
|
uint16_t end_handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read by Group Type Response */
|
||||||
|
#define BT_ATT_OP_READ_GROUP_RSP 0x11
|
||||||
|
struct bt_att_read_group_rsp {
|
||||||
|
uint8_t len;
|
||||||
|
struct bt_att_group_data data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Write Request */
|
||||||
|
#define BT_ATT_OP_WRITE_REQ 0x12
|
||||||
|
struct bt_att_write_req {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Write Response */
|
||||||
|
#define BT_ATT_OP_WRITE_RSP 0x13
|
||||||
|
|
||||||
|
/* Prepare Write Request */
|
||||||
|
#define BT_ATT_OP_PREPARE_WRITE_REQ 0x16
|
||||||
|
struct bt_att_prepare_write_req {
|
||||||
|
uint16_t handle;
|
||||||
|
uint16_t offset;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Prepare Write Respond */
|
||||||
|
#define BT_ATT_OP_PREPARE_WRITE_RSP 0x17
|
||||||
|
struct bt_att_prepare_write_rsp {
|
||||||
|
uint16_t handle;
|
||||||
|
uint16_t offset;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Execute Write Request */
|
||||||
|
#define BT_ATT_FLAG_CANCEL 0x00
|
||||||
|
#define BT_ATT_FLAG_EXEC 0x01
|
||||||
|
|
||||||
|
#define BT_ATT_OP_EXEC_WRITE_REQ 0x18
|
||||||
|
struct bt_att_exec_write_req {
|
||||||
|
uint8_t flags;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Execute Write Response */
|
||||||
|
#define BT_ATT_OP_EXEC_WRITE_RSP 0x19
|
||||||
|
|
||||||
|
/* Handle Value Notification */
|
||||||
|
#define BT_ATT_OP_NOTIFY 0x1b
|
||||||
|
struct bt_att_notify {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Handle Value Indication */
|
||||||
|
#define BT_ATT_OP_INDICATE 0x1d
|
||||||
|
struct bt_att_indicate {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Handle Value Confirm */
|
||||||
|
#define BT_ATT_OP_CONFIRM 0x1e
|
||||||
|
|
||||||
|
struct bt_att_signature {
|
||||||
|
uint8_t value[12];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_ATT_OP_READ_MULT_VL_REQ 0x20
|
||||||
|
struct bt_att_read_mult_vl_req {
|
||||||
|
uint16_t handles[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Read Multiple Respose */
|
||||||
|
#define BT_ATT_OP_READ_MULT_VL_RSP 0x21
|
||||||
|
struct bt_att_read_mult_vl_rsp {
|
||||||
|
uint16_t len;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Handle Multiple Value Notification */
|
||||||
|
#define BT_ATT_OP_NOTIFY_MULT 0x23
|
||||||
|
struct bt_att_notify_mult {
|
||||||
|
uint16_t handle;
|
||||||
|
uint16_t len;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Write Command */
|
||||||
|
#define BT_ATT_OP_WRITE_CMD 0x52
|
||||||
|
struct bt_att_write_cmd {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Signed Write Command */
|
||||||
|
#define BT_ATT_OP_SIGNED_WRITE_CMD 0xd2
|
||||||
|
struct bt_att_signed_write_cmd {
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t value[0];
|
||||||
|
} __packed;
|
1772
devices/ble_hci/common-hal/_bleio/hci_include/hci.h
Normal file
1772
devices/ble_hci/common-hal/_bleio/hci_include/hci.h
Normal file
File diff suppressed because it is too large
Load Diff
92
devices/ble_hci/common-hal/_bleio/hci_include/hci_err.h
Normal file
92
devices/ble_hci/common-hal/_bleio/hci_include/hci_err.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/** @file
|
||||||
|
* @brief Bluetooth Host Control Interface status codes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_
|
||||||
|
#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */
|
||||||
|
#define BT_HCI_ERR_SUCCESS 0x00
|
||||||
|
#define BT_HCI_ERR_UNKNOWN_CMD 0x01
|
||||||
|
#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02
|
||||||
|
#define BT_HCI_ERR_HW_FAILURE 0x03
|
||||||
|
#define BT_HCI_ERR_PAGE_TIMEOUT 0x04
|
||||||
|
#define BT_HCI_ERR_AUTH_FAIL 0x05
|
||||||
|
#define BT_HCI_ERR_PIN_OR_KEY_MISSING 0x06
|
||||||
|
#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED 0x07
|
||||||
|
#define BT_HCI_ERR_CONN_TIMEOUT 0x08
|
||||||
|
#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED 0x09
|
||||||
|
#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED 0x0a
|
||||||
|
#define BT_HCI_ERR_CONN_ALREADY_EXISTS 0x0b
|
||||||
|
#define BT_HCI_ERR_CMD_DISALLOWED 0x0c
|
||||||
|
#define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d
|
||||||
|
#define BT_HCI_ERR_INSUFFICIENT_SECURITY 0x0e
|
||||||
|
#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE 0x0f
|
||||||
|
#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT 0x10
|
||||||
|
#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL 0x11
|
||||||
|
#define BT_HCI_ERR_INVALID_PARAM 0x12
|
||||||
|
#define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13
|
||||||
|
#define BT_HCI_ERR_REMOTE_LOW_RESOURCES 0x14
|
||||||
|
#define BT_HCI_ERR_REMOTE_POWER_OFF 0x15
|
||||||
|
#define BT_HCI_ERR_LOCALHOST_TERM_CONN 0x16
|
||||||
|
#define BT_HCI_ERR_REPEATED_ATTEMPTS 0x17
|
||||||
|
#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18
|
||||||
|
#define BT_HCI_ERR_UNKNOWN_LMP_PDU 0x19
|
||||||
|
#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a
|
||||||
|
#define BT_HCI_ERR_SCO_OFFSET_REJECTED 0x1b
|
||||||
|
#define BT_HCI_ERR_SCO_INTERVAL_REJECTED 0x1c
|
||||||
|
#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED 0x1d
|
||||||
|
#define BT_HCI_ERR_INVALID_LL_PARAM 0x1e
|
||||||
|
#define BT_HCI_ERR_UNSPECIFIED 0x1f
|
||||||
|
#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL 0x20
|
||||||
|
#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21
|
||||||
|
#define BT_HCI_ERR_LL_RESP_TIMEOUT 0x22
|
||||||
|
#define BT_HCI_ERR_LL_PROC_COLLISION 0x23
|
||||||
|
#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24
|
||||||
|
#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE 0x25
|
||||||
|
#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED 0x26
|
||||||
|
#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED 0x27
|
||||||
|
#define BT_HCI_ERR_INSTANT_PASSED 0x28
|
||||||
|
#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29
|
||||||
|
#define BT_HCI_ERR_DIFF_TRANS_COLLISION 0x2a
|
||||||
|
#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2c
|
||||||
|
#define BT_HCI_ERR_QOS_REJECTED 0x2d
|
||||||
|
#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED 0x2e
|
||||||
|
#define BT_HCI_ERR_INSUFF_SECURITY 0x2f
|
||||||
|
#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30
|
||||||
|
#define BT_HCI_ERR_ROLE_SWITCH_PENDING 0x32
|
||||||
|
#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION 0x34
|
||||||
|
#define BT_HCI_ERR_ROLE_SWITCH_FAILED 0x35
|
||||||
|
#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE 0x36
|
||||||
|
#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37
|
||||||
|
#define BT_HCI_ERR_HOST_BUSY_PAIRING 0x38
|
||||||
|
#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39
|
||||||
|
#define BT_HCI_ERR_CONTROLLER_BUSY 0x3a
|
||||||
|
#define BT_HCI_ERR_UNACCEPT_CONN_PARAM 0x3b
|
||||||
|
#define BT_HCI_ERR_ADV_TIMEOUT 0x3c
|
||||||
|
#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL 0x3d
|
||||||
|
#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB 0x3e
|
||||||
|
#define BT_HCI_ERR_MAC_CONN_FAILED 0x3f
|
||||||
|
#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED 0x40
|
||||||
|
#define BT_HCI_ERR_SUBMAP_NOT_DEFINED 0x41
|
||||||
|
#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER 0x42
|
||||||
|
#define BT_HCI_ERR_LIMIT_REACHED 0x43
|
||||||
|
#define BT_HCI_ERR_OP_CANCELLED_BY_HOST 0x44
|
||||||
|
#define BT_HCI_ERR_PACKET_TOO_LONG 0x45
|
||||||
|
|
||||||
|
#define BT_HCI_ERR_AUTHENTICATION_FAIL __DEPRECATED_MACRO BT_HCI_ERR_AUTH_FAIL
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ */
|
152
devices/ble_hci/common-hal/_bleio/hci_include/hci_raw.h
Normal file
152
devices/ble_hci/common-hal/_bleio/hci_include/hci_raw.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/** @file
|
||||||
|
* @brief Bluetooth HCI RAW channel handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_
|
||||||
|
#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HCI RAW channel
|
||||||
|
* @defgroup hci_raw HCI RAW channel
|
||||||
|
* @ingroup bluetooth
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE)
|
||||||
|
#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - BT_L2CAP_HDR_SIZE)
|
||||||
|
#else
|
||||||
|
#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */
|
||||||
|
#endif /* CONFIG_BT_CTLR */
|
||||||
|
|
||||||
|
/** Data size needed for ACL buffers */
|
||||||
|
#define BT_BUF_ACL_SIZE BT_L2CAP_BUF_SIZE(BT_L2CAP_MTU)
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_TX_BUFFERS)
|
||||||
|
#define BT_HCI_ACL_COUNT CONFIG_BT_CTLR_TX_BUFFERS
|
||||||
|
#else
|
||||||
|
#define BT_HCI_ACL_COUNT 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BT_BUF_TX_SIZE MAX(BT_BUF_RX_SIZE, BT_BUF_ACL_SIZE)
|
||||||
|
|
||||||
|
/** @brief Send packet to the Bluetooth controller
|
||||||
|
*
|
||||||
|
* Send packet to the Bluetooth controller. Caller needs to
|
||||||
|
* implement netbuf pool.
|
||||||
|
*
|
||||||
|
* @param buf netbuf packet to be send
|
||||||
|
*
|
||||||
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
|
*/
|
||||||
|
int bt_send(struct net_buf *buf);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/** Passthrough mode
|
||||||
|
*
|
||||||
|
* While in this mode the buffers are passed as is between the stack
|
||||||
|
* and the driver.
|
||||||
|
*/
|
||||||
|
BT_HCI_RAW_MODE_PASSTHROUGH = 0x00,
|
||||||
|
|
||||||
|
/** H:4 mode
|
||||||
|
*
|
||||||
|
* While in this mode H:4 headers will added into the buffers
|
||||||
|
* according to the buffer type when coming from the stack and will be
|
||||||
|
* removed and used to set the buffer type.
|
||||||
|
*/
|
||||||
|
BT_HCI_RAW_MODE_H4 = 0x01,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Set Bluetooth RAW channel mode
|
||||||
|
*
|
||||||
|
* Set access mode of Bluetooth RAW channel.
|
||||||
|
*
|
||||||
|
* @param mode Access mode.
|
||||||
|
*
|
||||||
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
|
*/
|
||||||
|
int bt_hci_raw_set_mode(uint8_t mode);
|
||||||
|
|
||||||
|
/** @brief Get Bluetooth RAW channel mode
|
||||||
|
*
|
||||||
|
* Get access mode of Bluetooth RAW channel.
|
||||||
|
*
|
||||||
|
* @return Access mode.
|
||||||
|
*/
|
||||||
|
uint8_t bt_hci_raw_get_mode(void);
|
||||||
|
|
||||||
|
#define BT_HCI_ERR_EXT_HANDLED 0xff
|
||||||
|
|
||||||
|
/** Helper macro to define a command extension
|
||||||
|
*
|
||||||
|
* @param _op Opcode of the command.
|
||||||
|
* @param _min_len Minimal length of the command.
|
||||||
|
* @param _func Handler function to be called.
|
||||||
|
*/
|
||||||
|
#define BT_HCI_RAW_CMD_EXT(_op, _min_len, _func) \
|
||||||
|
{ \
|
||||||
|
.op = _op, \
|
||||||
|
.min_len = _min_len, \
|
||||||
|
.func = _func, \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bt_hci_raw_cmd_ext {
|
||||||
|
/** Opcode of the command */
|
||||||
|
uint16_t op;
|
||||||
|
|
||||||
|
/** Minimal length of the command */
|
||||||
|
size_t min_len;
|
||||||
|
|
||||||
|
/** Handler function.
|
||||||
|
*
|
||||||
|
* Handler function to be called when a command is intercepted.
|
||||||
|
*
|
||||||
|
* @param buf Buffer containing the command.
|
||||||
|
*
|
||||||
|
* @return HCI Status code or BT_HCI_ERR_EXT_HANDLED if command has
|
||||||
|
* been handled already and a response has been sent as oppose to
|
||||||
|
* BT_HCI_ERR_SUCCESS which just indicates that the command can be
|
||||||
|
* sent to the controller to be processed.
|
||||||
|
*/
|
||||||
|
uint8_t (*func)(struct net_buf *buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Register Bluetooth RAW command extension table
|
||||||
|
*
|
||||||
|
* Register Bluetooth RAW channel command extension table, opcodes in this
|
||||||
|
* table are intercepted to sent to the handler function.
|
||||||
|
*
|
||||||
|
* @param cmds Pointer to the command extension table.
|
||||||
|
* @param size Size of the command extension table.
|
||||||
|
*/
|
||||||
|
void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size);
|
||||||
|
|
||||||
|
/** @brief Enable Bluetooth RAW channel:
|
||||||
|
*
|
||||||
|
* Enable Bluetooth RAW HCI channel.
|
||||||
|
*
|
||||||
|
* @param rx_queue netbuf queue where HCI packets received from the Bluetooth
|
||||||
|
* controller are to be queued. The queue is defined in the caller while
|
||||||
|
* the available buffers pools are handled in the stack.
|
||||||
|
*
|
||||||
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
|
*/
|
||||||
|
int bt_enable_raw(struct k_fifo *rx_queue);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_ */
|
379
devices/ble_hci/common-hal/_bleio/hci_include/hci_vs.h
Normal file
379
devices/ble_hci/common-hal/_bleio/hci_include/hci_vs.h
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/* hci_vs.h - Bluetooth Host Control Interface Vendor Specific definitions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 Nordic Semiconductor ASA
|
||||||
|
* Copyright (c) 2015-2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_
|
||||||
|
#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_
|
||||||
|
|
||||||
|
#include <bluetooth/hci.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BT_VS_CMD_BIT_VERSION 0
|
||||||
|
#define BT_VS_CMD_BIT_SUP_CMD 1
|
||||||
|
#define BT_VS_CMD_BIT_SUP_FEAT 2
|
||||||
|
#define BT_VS_CMD_BIT_SET_EVT_MASK 3
|
||||||
|
#define BT_VS_CMD_BIT_RESET 4
|
||||||
|
#define BT_VS_CMD_BIT_WRITE_BDADDR 5
|
||||||
|
#define BT_VS_CMD_BIT_SET_TRACE_ENABLE 6
|
||||||
|
#define BT_VS_CMD_BIT_READ_BUILD_INFO 7
|
||||||
|
#define BT_VS_CMD_BIT_READ_STATIC_ADDRS 8
|
||||||
|
#define BT_VS_CMD_BIT_READ_KEY_ROOTS 9
|
||||||
|
#define BT_VS_CMD_BIT_READ_CHIP_TEMP 10
|
||||||
|
#define BT_VS_CMD_BIT_READ_HOST_STACK_CMD 11
|
||||||
|
#define BT_VS_CMD_BIT_SET_SCAN_REP_ENABLE 12
|
||||||
|
#define BT_VS_CMD_BIT_WRITE_TX_POWER 13
|
||||||
|
#define BT_VS_CMD_BIT_READ_TX_POWER 14
|
||||||
|
|
||||||
|
#define BT_VS_CMD_SUP_FEAT(cmd) BT_LE_FEAT_TEST(cmd, \
|
||||||
|
BT_VS_CMD_BIT_SUP_FEAT)
|
||||||
|
#define BT_VS_CMD_READ_STATIC_ADDRS(cmd) BT_LE_FEAT_TEST(cmd, \
|
||||||
|
BT_VS_CMD_BIT_READ_STATIC_ADDRS)
|
||||||
|
#define BT_VS_CMD_READ_KEY_ROOTS(cmd) BT_LE_FEAT_TEST(cmd, \
|
||||||
|
BT_VS_CMD_BIT_READ_KEY_ROOTS)
|
||||||
|
|
||||||
|
#define BT_HCI_VS_HW_PLAT_INTEL 0x0001
|
||||||
|
#define BT_HCI_VS_HW_PLAT_NORDIC 0x0002
|
||||||
|
#define BT_HCI_VS_HW_PLAT_NXP 0x0003
|
||||||
|
|
||||||
|
#define BT_HCI_VS_HW_VAR_NORDIC_NRF51X 0x0001
|
||||||
|
#define BT_HCI_VS_HW_VAR_NORDIC_NRF52X 0x0002
|
||||||
|
#define BT_HCI_VS_HW_VAR_NORDIC_NRF53X 0x0003
|
||||||
|
|
||||||
|
#define BT_HCI_VS_FW_VAR_STANDARD_CTLR 0x0001
|
||||||
|
#define BT_HCI_VS_FW_VAR_VS_CTLR 0x0002
|
||||||
|
#define BT_HCI_VS_FW_VAR_FW_LOADER 0x0003
|
||||||
|
#define BT_HCI_VS_FW_VAR_RESCUE_IMG 0x0004
|
||||||
|
#define BT_HCI_OP_VS_READ_VERSION_INFO BT_OP(BT_OGF_VS, 0x0001)
|
||||||
|
struct bt_hci_rp_vs_read_version_info {
|
||||||
|
uint8_t status;
|
||||||
|
uint16_t hw_platform;
|
||||||
|
uint16_t hw_variant;
|
||||||
|
uint8_t fw_variant;
|
||||||
|
uint8_t fw_version;
|
||||||
|
uint16_t fw_revision;
|
||||||
|
uint32_t fw_build;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_VS, 0x0002)
|
||||||
|
struct bt_hci_rp_vs_read_supported_commands {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t commands[64];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_SUPPORTED_FEATURES BT_OP(BT_OGF_VS, 0x0003)
|
||||||
|
struct bt_hci_rp_vs_read_supported_features {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t features[8];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_SET_EVENT_MASK BT_OP(BT_OGF_VS, 0x0004)
|
||||||
|
struct bt_hci_cp_vs_set_event_mask {
|
||||||
|
uint8_t event_mask[8];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_RESET_SOFT 0x00
|
||||||
|
#define BT_HCI_VS_RESET_HARD 0x01
|
||||||
|
#define BT_HCI_OP_VS_RESET BT_OP(BT_OGF_VS, 0x0005)
|
||||||
|
struct bt_hci_cp_vs_reset {
|
||||||
|
uint8_t type;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_WRITE_BD_ADDR BT_OP(BT_OGF_VS, 0x0006)
|
||||||
|
struct bt_hci_cp_vs_write_bd_addr {
|
||||||
|
bt_addr_t bdaddr;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_TRACE_DISABLED 0x00
|
||||||
|
#define BT_HCI_VS_TRACE_ENABLED 0x01
|
||||||
|
|
||||||
|
#define BT_HCI_VS_TRACE_HCI_EVTS 0x00
|
||||||
|
#define BT_HCI_VS_TRACE_VDC 0x01
|
||||||
|
#define BT_HCI_OP_VS_SET_TRACE_ENABLE BT_OP(BT_OGF_VS, 0x0007)
|
||||||
|
struct bt_hci_cp_vs_set_trace_enable {
|
||||||
|
uint8_t enable;
|
||||||
|
uint8_t type;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_BUILD_INFO BT_OP(BT_OGF_VS, 0x0008)
|
||||||
|
struct bt_hci_rp_vs_read_build_info {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t info[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_hci_vs_static_addr {
|
||||||
|
bt_addr_t bdaddr;
|
||||||
|
uint8_t ir[16];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_STATIC_ADDRS BT_OP(BT_OGF_VS, 0x0009)
|
||||||
|
struct bt_hci_rp_vs_read_static_addrs {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t num_addrs;
|
||||||
|
struct bt_hci_vs_static_addr a[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS BT_OP(BT_OGF_VS, 0x000a)
|
||||||
|
struct bt_hci_rp_vs_read_key_hierarchy_roots {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t ir[16];
|
||||||
|
uint8_t er[16];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_CHIP_TEMP BT_OP(BT_OGF_VS, 0x000b)
|
||||||
|
struct bt_hci_rp_vs_read_chip_temp {
|
||||||
|
uint8_t status;
|
||||||
|
int8_t temps;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_hci_vs_cmd {
|
||||||
|
uint16_t vendor_id;
|
||||||
|
uint16_t opcode_base;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_VID_ANDROID 0x0001
|
||||||
|
#define BT_HCI_VS_VID_MICROSOFT 0x0002
|
||||||
|
#define BT_HCI_OP_VS_READ_HOST_STACK_CMDS BT_OP(BT_OGF_VS, 0x000c)
|
||||||
|
struct bt_hci_rp_vs_read_host_stack_cmds {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t num_cmds;
|
||||||
|
struct bt_hci_vs_cmd c[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_SCAN_REQ_REPORTS_DISABLED 0x00
|
||||||
|
#define BT_HCI_VS_SCAN_REQ_REPORTS_ENABLED 0x01
|
||||||
|
#define BT_HCI_OP_VS_SET_SCAN_REQ_REPORTS BT_OP(BT_OGF_VS, 0x000d)
|
||||||
|
struct bt_hci_cp_vs_set_scan_req_reports {
|
||||||
|
uint8_t enable;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_LL_HANDLE_TYPE_ADV 0x00
|
||||||
|
#define BT_HCI_VS_LL_HANDLE_TYPE_SCAN 0x01
|
||||||
|
#define BT_HCI_VS_LL_HANDLE_TYPE_CONN 0x02
|
||||||
|
#define BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF 0x7F
|
||||||
|
#define BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000e)
|
||||||
|
struct bt_hci_cp_vs_write_tx_power_level {
|
||||||
|
uint8_t handle_type;
|
||||||
|
uint16_t handle;
|
||||||
|
int8_t tx_power_level;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_hci_rp_vs_write_tx_power_level {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t handle_type;
|
||||||
|
uint16_t handle;
|
||||||
|
int8_t selected_tx_power;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000f)
|
||||||
|
struct bt_hci_cp_vs_read_tx_power_level {
|
||||||
|
uint8_t handle_type;
|
||||||
|
uint16_t handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_hci_rp_vs_read_tx_power_level {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t handle_type;
|
||||||
|
uint16_t handle;
|
||||||
|
int8_t tx_power_level;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_READ_USB_TRANSPORT_MODE BT_OP(BT_OGF_VS, 0x0010)
|
||||||
|
|
||||||
|
struct bt_hci_rp_vs_read_usb_transport_mode {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t num_supported_modes;
|
||||||
|
uint8_t supported_mode[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_USB_H2_MODE 0x00
|
||||||
|
#define BT_HCI_VS_USB_H4_MODE 0x01
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_SET_USB_TRANSPORT_MODE BT_OP(BT_OGF_VS, 0x0011)
|
||||||
|
|
||||||
|
struct bt_hci_cp_vs_set_usb_transport_mode {
|
||||||
|
uint8_t mode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Events */
|
||||||
|
|
||||||
|
struct bt_hci_evt_vs {
|
||||||
|
uint8_t subevent;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_EVT_VS_FATAL_ERROR 0x02
|
||||||
|
struct bt_hci_evt_vs_fatal_error {
|
||||||
|
uint64_t pc;
|
||||||
|
uint8_t err_info[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_VS_TRACE_LMP_TX 0x01
|
||||||
|
#define BT_HCI_VS_TRACE_LMP_RX 0x02
|
||||||
|
#define BT_HCI_VS_TRACE_LLCP_TX 0x03
|
||||||
|
#define BT_HCI_VS_TRACE_LLCP_RX 0x04
|
||||||
|
#define BT_HCI_VS_TRACE_LE_CONN_IND 0x05
|
||||||
|
#define BT_HCI_EVT_VS_TRACE_INFO 0x03
|
||||||
|
struct bt_hci_evt_vs_trace_info {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_EVT_VS_SCAN_REQ_RX 0x04
|
||||||
|
struct bt_hci_evt_vs_scan_req_rx {
|
||||||
|
bt_addr_le_t addr;
|
||||||
|
int8_t rssi;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Event mask bits */
|
||||||
|
|
||||||
|
#define BT_EVT_MASK_VS_FATAL_ERROR BT_EVT_BIT(1)
|
||||||
|
#define BT_EVT_MASK_VS_TRACE_INFO BT_EVT_BIT(2)
|
||||||
|
#define BT_EVT_MASK_VS_SCAN_REQ_RX BT_EVT_BIT(3)
|
||||||
|
|
||||||
|
/* Mesh HCI commands */
|
||||||
|
#define BT_HCI_MESH_REVISION 0x01
|
||||||
|
|
||||||
|
#define BT_HCI_OP_VS_MESH BT_OP(BT_OGF_VS, 0x0042)
|
||||||
|
#define BT_HCI_MESH_EVT_PREFIX 0xF0
|
||||||
|
|
||||||
|
struct bt_hci_cp_mesh {
|
||||||
|
uint8_t opcode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_GET_OPTS 0x00
|
||||||
|
struct bt_hci_rp_mesh_get_opts {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t revision;
|
||||||
|
uint8_t ch_map;
|
||||||
|
int8_t min_tx_power;
|
||||||
|
int8_t max_tx_power;
|
||||||
|
uint8_t max_scan_filter;
|
||||||
|
uint8_t max_filter_pattern;
|
||||||
|
uint8_t max_adv_slot;
|
||||||
|
uint8_t max_tx_window;
|
||||||
|
uint8_t evt_prefix_len;
|
||||||
|
uint8_t evt_prefix;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_MESH_PATTERN_LEN_MAX 0x0f
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_SET_SCAN_FILTER 0x01
|
||||||
|
struct bt_hci_mesh_pattern {
|
||||||
|
uint8_t pattern_len;
|
||||||
|
uint8_t pattern[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_hci_cp_mesh_set_scan_filter {
|
||||||
|
uint8_t scan_filter;
|
||||||
|
uint8_t filter_dup;
|
||||||
|
uint8_t num_patterns;
|
||||||
|
struct bt_hci_mesh_pattern patterns[0];
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_rp_mesh_set_scan_filter {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t scan_filter;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_ADVERTISE 0x02
|
||||||
|
struct bt_hci_cp_mesh_advertise {
|
||||||
|
uint8_t adv_slot;
|
||||||
|
uint8_t own_addr_type;
|
||||||
|
bt_addr_t random_addr;
|
||||||
|
uint8_t ch_map;
|
||||||
|
int8_t tx_power;
|
||||||
|
uint8_t min_tx_delay;
|
||||||
|
uint8_t max_tx_delay;
|
||||||
|
uint8_t retx_count;
|
||||||
|
uint8_t retx_interval;
|
||||||
|
uint8_t scan_delay;
|
||||||
|
uint16_t scan_duration;
|
||||||
|
uint8_t scan_filter;
|
||||||
|
uint8_t data_len;
|
||||||
|
uint8_t data[31];
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_rp_mesh_advertise {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t adv_slot;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_ADVERTISE_TIMED 0x03
|
||||||
|
struct bt_hci_cp_mesh_advertise_timed {
|
||||||
|
uint8_t adv_slot;
|
||||||
|
uint8_t own_addr_type;
|
||||||
|
bt_addr_t random_addr;
|
||||||
|
uint8_t ch_map;
|
||||||
|
int8_t tx_power;
|
||||||
|
uint8_t retx_count;
|
||||||
|
uint8_t retx_interval;
|
||||||
|
uint32_t instant;
|
||||||
|
uint16_t tx_delay;
|
||||||
|
uint16_t tx_window;
|
||||||
|
uint8_t data_len;
|
||||||
|
uint8_t data[31];
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_rp_mesh_advertise_timed {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t adv_slot;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_ADVERTISE_CANCEL 0x04
|
||||||
|
struct bt_hci_cp_mesh_advertise_cancel {
|
||||||
|
uint8_t adv_slot;
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_rp_mesh_advertise_cancel {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t adv_slot;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_OC_MESH_SET_SCANNING 0x05
|
||||||
|
struct bt_hci_cp_mesh_set_scanning {
|
||||||
|
uint8_t enable;
|
||||||
|
uint8_t ch_map;
|
||||||
|
uint8_t scan_filter;
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_rp_mesh_set_scanning {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t opcode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Events */
|
||||||
|
struct bt_hci_evt_mesh {
|
||||||
|
uint8_t prefix;
|
||||||
|
uint8_t subevent;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_EVT_MESH_ADV_COMPLETE 0x00
|
||||||
|
struct bt_hci_evt_mesh_adv_complete {
|
||||||
|
uint8_t adv_slot;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_EVT_MESH_SCANNING_REPORT 0x01
|
||||||
|
struct bt_hci_evt_mesh_scan_report {
|
||||||
|
bt_addr_le_t addr;
|
||||||
|
uint8_t chan;
|
||||||
|
int8_t rssi;
|
||||||
|
uint32_t instant;
|
||||||
|
uint8_t data_len;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
struct bt_hci_evt_mesh_scanning_report {
|
||||||
|
uint8_t num_reports;
|
||||||
|
struct bt_hci_evt_mesh_scan_report reports[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_ */
|
230
devices/ble_hci/common-hal/_bleio/hci_include/l2cap_internal.h
Normal file
230
devices/ble_hci/common-hal/_bleio/hci_include/l2cap_internal.h
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
// CircuitPython: Adapted from Zephyr include file.
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Internal APIs for Bluetooth L2CAP handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
// for __packed
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
enum l2cap_conn_list_action {
|
||||||
|
BT_L2CAP_CHAN_LOOKUP,
|
||||||
|
BT_L2CAP_CHAN_DETACH,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BT_L2CAP_CID_BR_SIG 0x0001
|
||||||
|
#define BT_L2CAP_CID_ATT 0x0004
|
||||||
|
#define BT_L2CAP_CID_LE_SIG 0x0005
|
||||||
|
#define BT_L2CAP_CID_SMP 0x0006
|
||||||
|
#define BT_L2CAP_CID_BR_SMP 0x0007
|
||||||
|
|
||||||
|
#define BT_L2CAP_PSM_RFCOMM 0x0003
|
||||||
|
|
||||||
|
struct bt_l2cap_hdr {
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t cid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_l2cap_sig_hdr {
|
||||||
|
uint8_t code;
|
||||||
|
uint8_t ident;
|
||||||
|
uint16_t len;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_REJ_NOT_UNDERSTOOD 0x0000
|
||||||
|
#define BT_L2CAP_REJ_MTU_EXCEEDED 0x0001
|
||||||
|
#define BT_L2CAP_REJ_INVALID_CID 0x0002
|
||||||
|
|
||||||
|
#define BT_L2CAP_CMD_REJECT 0x01
|
||||||
|
struct bt_l2cap_cmd_reject {
|
||||||
|
uint16_t reason;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct bt_l2cap_cmd_reject_cid_data {
|
||||||
|
uint16_t scid;
|
||||||
|
uint16_t dcid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONN_REQ 0x02
|
||||||
|
struct bt_l2cap_conn_req {
|
||||||
|
uint16_t psm;
|
||||||
|
uint16_t scid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* command statuses in reposnse */
|
||||||
|
#define BT_L2CAP_CS_NO_INFO 0x0000
|
||||||
|
#define BT_L2CAP_CS_AUTHEN_PEND 0x0001
|
||||||
|
|
||||||
|
/* valid results in conn response on BR/EDR */
|
||||||
|
#define BT_L2CAP_BR_SUCCESS 0x0000
|
||||||
|
#define BT_L2CAP_BR_PENDING 0x0001
|
||||||
|
#define BT_L2CAP_BR_ERR_PSM_NOT_SUPP 0x0002
|
||||||
|
#define BT_L2CAP_BR_ERR_SEC_BLOCK 0x0003
|
||||||
|
#define BT_L2CAP_BR_ERR_NO_RESOURCES 0x0004
|
||||||
|
#define BT_L2CAP_BR_ERR_INVALID_SCID 0x0006
|
||||||
|
#define BT_L2CAP_BR_ERR_SCID_IN_USE 0x0007
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONN_RSP 0x03
|
||||||
|
struct bt_l2cap_conn_rsp {
|
||||||
|
uint16_t dcid;
|
||||||
|
uint16_t scid;
|
||||||
|
uint16_t result;
|
||||||
|
uint16_t status;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONF_SUCCESS 0x0000
|
||||||
|
#define BT_L2CAP_CONF_UNACCEPT 0x0001
|
||||||
|
#define BT_L2CAP_CONF_REJECT 0x0002
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONF_REQ 0x04
|
||||||
|
struct bt_l2cap_conf_req {
|
||||||
|
uint16_t dcid;
|
||||||
|
uint16_t flags;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONF_RSP 0x05
|
||||||
|
struct bt_l2cap_conf_rsp {
|
||||||
|
uint16_t scid;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t result;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Option type used by MTU config request data */
|
||||||
|
#define BT_L2CAP_CONF_OPT_MTU 0x01
|
||||||
|
/* Options bits selecting most significant bit (hint) in type field */
|
||||||
|
#define BT_L2CAP_CONF_HINT 0x80
|
||||||
|
#define BT_L2CAP_CONF_MASK 0x7f
|
||||||
|
|
||||||
|
struct bt_l2cap_conf_opt {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_DISCONN_REQ 0x06
|
||||||
|
struct bt_l2cap_disconn_req {
|
||||||
|
uint16_t dcid;
|
||||||
|
uint16_t scid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_DISCONN_RSP 0x07
|
||||||
|
struct bt_l2cap_disconn_rsp {
|
||||||
|
uint16_t dcid;
|
||||||
|
uint16_t scid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_INFO_FEAT_MASK 0x0002
|
||||||
|
#define BT_L2CAP_INFO_FIXED_CHAN 0x0003
|
||||||
|
|
||||||
|
#define BT_L2CAP_INFO_REQ 0x0a
|
||||||
|
struct bt_l2cap_info_req {
|
||||||
|
uint16_t type;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* info result */
|
||||||
|
#define BT_L2CAP_INFO_SUCCESS 0x0000
|
||||||
|
#define BT_L2CAP_INFO_NOTSUPP 0x0001
|
||||||
|
|
||||||
|
#define BT_L2CAP_INFO_RSP 0x0b
|
||||||
|
struct bt_l2cap_info_rsp {
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t result;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONN_PARAM_REQ 0x12
|
||||||
|
struct bt_l2cap_conn_param_req {
|
||||||
|
uint16_t min_interval;
|
||||||
|
uint16_t max_interval;
|
||||||
|
uint16_t latency;
|
||||||
|
uint16_t timeout;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONN_PARAM_ACCEPTED 0x0000
|
||||||
|
#define BT_L2CAP_CONN_PARAM_REJECTED 0x0001
|
||||||
|
|
||||||
|
#define BT_L2CAP_CONN_PARAM_RSP 0x13
|
||||||
|
struct bt_l2cap_conn_param_rsp {
|
||||||
|
uint16_t result;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_LE_CONN_REQ 0x14
|
||||||
|
struct bt_l2cap_le_conn_req {
|
||||||
|
uint16_t psm;
|
||||||
|
uint16_t scid;
|
||||||
|
uint16_t mtu;
|
||||||
|
uint16_t mps;
|
||||||
|
uint16_t credits;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* valid results in conn response on LE */
|
||||||
|
#define BT_L2CAP_LE_SUCCESS 0x0000
|
||||||
|
#define BT_L2CAP_LE_ERR_PSM_NOT_SUPP 0x0002
|
||||||
|
#define BT_L2CAP_LE_ERR_NO_RESOURCES 0x0004
|
||||||
|
#define BT_L2CAP_LE_ERR_AUTHENTICATION 0x0005
|
||||||
|
#define BT_L2CAP_LE_ERR_AUTHORIZATION 0x0006
|
||||||
|
#define BT_L2CAP_LE_ERR_KEY_SIZE 0x0007
|
||||||
|
#define BT_L2CAP_LE_ERR_ENCRYPTION 0x0008
|
||||||
|
#define BT_L2CAP_LE_ERR_INVALID_SCID 0x0009
|
||||||
|
#define BT_L2CAP_LE_ERR_SCID_IN_USE 0x000A
|
||||||
|
#define BT_L2CAP_LE_ERR_UNACCEPT_PARAMS 0x000B
|
||||||
|
#define BT_L2CAP_LE_ERR_INVALID_PARAMS 0x000C
|
||||||
|
|
||||||
|
#define BT_L2CAP_LE_CONN_RSP 0x15
|
||||||
|
struct bt_l2cap_le_conn_rsp {
|
||||||
|
uint16_t dcid;
|
||||||
|
uint16_t mtu;
|
||||||
|
uint16_t mps;
|
||||||
|
uint16_t credits;
|
||||||
|
uint16_t result;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_LE_CREDITS 0x16
|
||||||
|
struct bt_l2cap_le_credits {
|
||||||
|
uint16_t cid;
|
||||||
|
uint16_t credits;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_ECRED_CONN_REQ 0x17
|
||||||
|
struct bt_l2cap_ecred_conn_req {
|
||||||
|
uint16_t psm;
|
||||||
|
uint16_t mtu;
|
||||||
|
uint16_t mps;
|
||||||
|
uint16_t credits;
|
||||||
|
uint16_t scid[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_ECRED_CONN_RSP 0x18
|
||||||
|
struct bt_l2cap_ecred_conn_rsp {
|
||||||
|
uint16_t mtu;
|
||||||
|
uint16_t mps;
|
||||||
|
uint16_t credits;
|
||||||
|
uint16_t result;
|
||||||
|
uint16_t dcid[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_ECRED_RECONF_REQ 0x19
|
||||||
|
struct bt_l2cap_ecred_reconf_req {
|
||||||
|
uint16_t mtu;
|
||||||
|
uint16_t mps;
|
||||||
|
uint16_t scid[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_L2CAP_RECONF_SUCCESS 0x0000
|
||||||
|
#define BT_L2CAP_RECONF_INVALID_MTU 0x0001
|
||||||
|
#define BT_L2CAP_RECONF_INVALID_MPS 0x0002
|
||||||
|
|
||||||
|
#define BT_L2CAP_ECRED_RECONF_RSP 0x1a
|
||||||
|
struct bt_l2cap_ecred_reconf_rsp {
|
||||||
|
uint16_t result;
|
||||||
|
} __packed;
|
29
devices/ble_hci/supervisor/bluetooth.c
Normal file
29
devices/ble_hci/supervisor/bluetooth.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if CIRCUITPY_BLE_FILE_SERVICE
|
||||||
|
#error CIRCUITPY_BLE_FILE_SERVICE not implemented for CIRCUITPY_BLEIO_HCI
|
||||||
|
#endif
|
34
devices/ble_hci/supervisor/bluetooth.h
Normal file
34
devices/ble_hci/supervisor/bluetooth.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H
|
||||||
|
#define MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H
|
||||||
|
|
||||||
|
void supervisor_start_bluetooth(void);
|
||||||
|
bool supervisor_bluetooth_hook(ble_evt_t *ble_evt);
|
||||||
|
void supervisor_bluetooth_background(void);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H
|
@ -5,7 +5,7 @@ The latest documentation can be found at:
|
|||||||
http://circuitpython.readthedocs.io/en/latest/
|
http://circuitpython.readthedocs.io/en/latest/
|
||||||
|
|
||||||
The documentation you see there is generated from the files in the whole tree:
|
The documentation you see there is generated from the files in the whole tree:
|
||||||
https://github.com/adafruit/circuitpython/tree/master
|
https://github.com/adafruit/circuitpython/tree/main
|
||||||
|
|
||||||
Building the documentation locally
|
Building the documentation locally
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
92
docs/autoapi/templates/python/module.rst
Normal file
92
docs/autoapi/templates/python/module.rst
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
{% if not obj.display %}
|
||||||
|
:orphan:
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
:mod:`{{ obj.name }}`
|
||||||
|
======={{ "=" * obj.name|length }}
|
||||||
|
|
||||||
|
.. py:module:: {{ obj.name }}
|
||||||
|
|
||||||
|
{% if obj.docstring %}
|
||||||
|
.. autoapi-nested-parse::
|
||||||
|
|
||||||
|
{{ obj.docstring|prepare_docstring|indent(3) }}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block subpackages %}
|
||||||
|
{% set visible_subpackages = obj.subpackages|selectattr("display")|list %}
|
||||||
|
{% if visible_subpackages %}
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
{% for subpackage in visible_subpackages %}
|
||||||
|
{{ subpackage.short_name }}/index.rst
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block submodules %}
|
||||||
|
{% set visible_submodules = obj.submodules|selectattr("display")|list %}
|
||||||
|
{% if visible_submodules %}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:titlesonly:
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
{% for submodule in visible_submodules %}
|
||||||
|
{{ submodule.short_name }}/index.rst
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% if obj.all is not none %}
|
||||||
|
{% set visible_children = obj.children|selectattr("short_name", "in", obj.all)|list %}
|
||||||
|
{% elif obj.type is equalto("package") %}
|
||||||
|
{% set visible_children = obj.children|selectattr("display")|list %}
|
||||||
|
{% else %}
|
||||||
|
{% set visible_children = obj.children|selectattr("display")|rejectattr("imported")|list %}
|
||||||
|
{% endif %}
|
||||||
|
{% if visible_children %}
|
||||||
|
|
||||||
|
{% set visible_classes = visible_children|selectattr("type", "equalto", "class")|list %}
|
||||||
|
{% set visible_functions = visible_children|selectattr("type", "equalto", "function")|list %}
|
||||||
|
{% if "show-module-summary" in autoapi_options and (visible_classes or visible_functions) %}
|
||||||
|
{% block classes %}
|
||||||
|
{% if visible_classes %}
|
||||||
|
Classes
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
.. autoapisummary::
|
||||||
|
|
||||||
|
{% for klass in visible_classes %}
|
||||||
|
{{ klass.id }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block functions %}
|
||||||
|
{% if visible_functions %}
|
||||||
|
Functions
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoapisummary::
|
||||||
|
|
||||||
|
{% for function in visible_functions %}
|
||||||
|
{{ function.id }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% endif %}
|
||||||
|
{% for obj_item in visible_children %}
|
||||||
|
{{ obj_item.rendered|indent(0) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
@ -1,31 +0,0 @@
|
|||||||
def c2rst(app, docname, source):
|
|
||||||
""" Pre-parse '.c' & '.h' files that contain rST source.
|
|
||||||
"""
|
|
||||||
# Make sure we're outputting HTML
|
|
||||||
if app.builder.format != 'html':
|
|
||||||
return
|
|
||||||
|
|
||||||
fname = app.env.doc2path(docname)
|
|
||||||
if (not fname.endswith(".c") and
|
|
||||||
not fname.endswith(".h")):
|
|
||||||
#print("skipping:", fname)
|
|
||||||
return
|
|
||||||
|
|
||||||
src = source[0]
|
|
||||||
|
|
||||||
stripped = []
|
|
||||||
for line in src.split("\n"):
|
|
||||||
line = line.strip()
|
|
||||||
if line == "//|":
|
|
||||||
stripped.append("")
|
|
||||||
elif line.startswith("//| "):
|
|
||||||
stripped.append(line[len("//| "):])
|
|
||||||
stripped = "\r\n".join(stripped)
|
|
||||||
|
|
||||||
rendered = app.builder.templates.render_string(
|
|
||||||
stripped, app.config.html_context
|
|
||||||
)
|
|
||||||
source[0] = rendered
|
|
||||||
|
|
||||||
def setup(app):
|
|
||||||
app.connect("source-read", c2rst)
|
|
@ -1,9 +1,11 @@
|
|||||||
|
.. role:: strike
|
||||||
|
|
||||||
Design Guide
|
Design Guide
|
||||||
============
|
============
|
||||||
|
|
||||||
This guide covers a variety of development practices for CircuitPython core and library APIs. These
|
This guide covers a variety of development practices for CircuitPython core and library APIs. These
|
||||||
APIs are both `built-into CircuitPython
|
APIs are both `built-into CircuitPython
|
||||||
<https://github.com/adafruit/circuitpython/tree/master/shared-bindings>`_ and those that are
|
<https://github.com/adafruit/circuitpython/tree/main/shared-bindings>`_ and those that are
|
||||||
`distributed on GitHub <https://github.com/search?utf8=%E2%9C%93&q=topic%3Acircuitpython&type=>`_
|
`distributed on GitHub <https://github.com/search?utf8=%E2%9C%93&q=topic%3Acircuitpython&type=>`_
|
||||||
and in the `Adafruit <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_ and `Community
|
and in the `Adafruit <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_ and `Community
|
||||||
<https://github.com/adafruit/CircuitPython_Community_Bundle/>`_ bundles. Consistency with these
|
<https://github.com/adafruit/CircuitPython_Community_Bundle/>`_ bundles. Consistency with these
|
||||||
@ -46,6 +48,41 @@ not have the ``adafruit_`` module or package prefix.
|
|||||||
|
|
||||||
Both should have the CircuitPython repository topic on GitHub.
|
Both should have the CircuitPython repository topic on GitHub.
|
||||||
|
|
||||||
|
Terminology
|
||||||
|
-----------
|
||||||
|
|
||||||
|
As our Code of Conduct states, we strive to use "welcoming and inclusive
|
||||||
|
language." Whether it is in documentation or in code, the words we use matter.
|
||||||
|
This means we disfavor language that due to historical and social context can
|
||||||
|
make community members and potential community members feel unwelcome.
|
||||||
|
|
||||||
|
There are specific terms to avoid except where technical limitations require it.
|
||||||
|
While specific cases may call for other terms, consider using these suggested
|
||||||
|
terms first:
|
||||||
|
|
||||||
|
+--------------------+---------------------+
|
||||||
|
| Preferred | Deprecated |
|
||||||
|
+====================+=====================+
|
||||||
|
| Main (device) | :strike:`Master` |
|
||||||
|
+--------------------+---------------------+
|
||||||
|
| Peripheral | :strike:`Slave` |
|
||||||
|
+--------------------+ +
|
||||||
|
| Sensor | |
|
||||||
|
+--------------------+ +
|
||||||
|
| Secondary (device) | |
|
||||||
|
+--------------------+---------------------+
|
||||||
|
| Denylist | :strike:`Blacklist` |
|
||||||
|
+--------------------+---------------------+
|
||||||
|
| Allowlist | :strike:`Whitelist` |
|
||||||
|
+--------------------+---------------------+
|
||||||
|
|
||||||
|
Note that "technical limitations" refers e.g., to the situation where an
|
||||||
|
upstream library or URL has to contain those substrings in order to work.
|
||||||
|
However, when it comes to documentation and the names of parameters and
|
||||||
|
properties in CircuitPython, we will use alternate terms even if this breaks
|
||||||
|
tradition with past practice.
|
||||||
|
|
||||||
|
|
||||||
.. _lifetime-and-contextmanagers:
|
.. _lifetime-and-contextmanagers:
|
||||||
|
|
||||||
Lifetime and ContextManagers
|
Lifetime and ContextManagers
|
||||||
@ -448,6 +485,19 @@ struct.pack
|
|||||||
|
|
||||||
Use `struct.pack_into` instead of `struct.pack`.
|
Use `struct.pack_into` instead of `struct.pack`.
|
||||||
|
|
||||||
|
Use of MicroPython ``const()``
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
The MicroPython ``const()`` feature, as discussed in `this forum post
|
||||||
|
<https://forum.micropython.org/viewtopic.php?t=450>`_, and in `this issue thread
|
||||||
|
<https://github.com/micropython/micropython/issues/573>`_, provides some
|
||||||
|
optimizations that can be useful on smaller, memory constrained devices. However,
|
||||||
|
when using ``const()``, keep in mind these general guide lines:
|
||||||
|
|
||||||
|
- Always use via an import, ex: ``from micropython import const``
|
||||||
|
- Limit use to global (module level) variables only.
|
||||||
|
- If user will not need access to variable, prefix name with a leading
|
||||||
|
underscore, ex: ``_SOME_CONST``.
|
||||||
|
|
||||||
Sensor properties and units
|
Sensor properties and units
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ CircuitPython/MicroPython-specific libraries
|
|||||||
|
|
||||||
Functionality specific to the CircuitPython/MicroPython implementation is available in
|
Functionality specific to the CircuitPython/MicroPython implementation is available in
|
||||||
the following libraries. These libraries may change signficantly or be removed in future
|
the following libraries. These libraries may change signficantly or be removed in future
|
||||||
versions of CircuitPtyon.
|
versions of CircuitPython.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
We love CircuitPython and would love to see it come to more microcontroller
|
We love CircuitPython and would love to see it come to more microcontroller
|
||||||
platforms. With 3.0 we've reworked CircuitPython to make it easier than ever to
|
platforms. Since 3.0 we've reworked CircuitPython to make it easier than ever to
|
||||||
add support. While there are some major differences between ports, this page
|
add support. While there are some major differences between ports, this page
|
||||||
covers the similarities that make CircuitPython what it is and how that core
|
covers the similarities that make CircuitPython what it is and how that core
|
||||||
fits into a variety of microcontrollers.
|
fits into a variety of microcontrollers.
|
||||||
@ -19,7 +19,7 @@ prepping file systems and automatically running user code on boot. In
|
|||||||
CircuitPython we've dubbed this component the supervisor because it monitors
|
CircuitPython we've dubbed this component the supervisor because it monitors
|
||||||
and facilitates the VMs which run user Python code. Porting involves the
|
and facilitates the VMs which run user Python code. Porting involves the
|
||||||
supervisor because many of the tasks it does while interfacing with the
|
supervisor because many of the tasks it does while interfacing with the
|
||||||
hardware. Once its going though, the REPL works and debugging can migrate to a
|
hardware. Once complete, the REPL works and debugging can migrate to a
|
||||||
Python based approach rather than C.
|
Python based approach rather than C.
|
||||||
|
|
||||||
The third core piece is the plethora of low level APIs that CircuitPython
|
The third core piece is the plethora of low level APIs that CircuitPython
|
||||||
@ -42,6 +42,61 @@ to the port's directory (in the top level until the ``ports`` directory is
|
|||||||
present). This includes the Makefile and any C library resources. Make sure
|
present). This includes the Makefile and any C library resources. Make sure
|
||||||
these resources are compatible with the MIT License of the rest of the code!
|
these resources are compatible with the MIT License of the rest of the code!
|
||||||
|
|
||||||
|
Circuitpython has a number of modules enabled by default in
|
||||||
|
``py/circuitpy_mpconfig.mk``. Most of these modules will need to be disabled in
|
||||||
|
``mpconfigboard.mk`` during the early stages of a port in order for it to
|
||||||
|
compile. As the port progresses in module support, this list can be pruned down
|
||||||
|
as a natural "TODO" list. An example minimal build list is shown below:
|
||||||
|
|
||||||
|
.. code-block:: makefile
|
||||||
|
|
||||||
|
# These modules are implemented in ports/<port>/common-hal:
|
||||||
|
|
||||||
|
# Typically the first module to create
|
||||||
|
CIRCUITPY_MICROCONTROLLER = 0
|
||||||
|
# Typically the second module to create
|
||||||
|
CIRCUITPY_DIGITALIO = 0
|
||||||
|
# Other modules:
|
||||||
|
CIRCUITPY_ANALOGIO = 0
|
||||||
|
CIRCUITPY_BUSIO = 0
|
||||||
|
CIRCUITPY_COUNTIO = 0
|
||||||
|
CIRCUITPY_NEOPIXEL_WRITE = 0
|
||||||
|
CIRCUITPY_PULSEIO = 0
|
||||||
|
CIRCUITPY_OS = 0
|
||||||
|
CIRCUITPY_NVM = 0
|
||||||
|
CIRCUITPY_AUDIOBUSIO = 0
|
||||||
|
CIRCUITPY_AUDIOIO = 0
|
||||||
|
CIRCUITPY_ROTARYIO = 0
|
||||||
|
CIRCUITPY_RTC = 0
|
||||||
|
CIRCUITPY_SDCARDIO = 0
|
||||||
|
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||||
|
CIRCUITPY_FREQUENCYIO = 0
|
||||||
|
CIRCUITPY_I2CPERIPHERAL = 0
|
||||||
|
# Requires SPI, PulseIO (stub ok):
|
||||||
|
CIRCUITPY_DISPLAYIO = 0
|
||||||
|
|
||||||
|
# These modules are implemented in shared-module/ - they can be included in
|
||||||
|
# any port once their prerequisites in common-hal are complete.
|
||||||
|
# Requires DigitalIO:
|
||||||
|
CIRCUITPY_BITBANGIO = 0
|
||||||
|
# Requires DigitalIO
|
||||||
|
CIRCUITPY_GAMEPAD = 0
|
||||||
|
# Requires neopixel_write or SPI (dotstar)
|
||||||
|
CIRCUITPY_PIXELBUF = 0
|
||||||
|
# Requires OS
|
||||||
|
CIRCUITPY_RANDOM = 0
|
||||||
|
# Requires OS, filesystem
|
||||||
|
CIRCUITPY_STORAGE = 0
|
||||||
|
# Requires Microcontroller
|
||||||
|
CIRCUITPY_TOUCHIO = 0
|
||||||
|
# Requires USB
|
||||||
|
CIRCUITPY_USB_HID = 0
|
||||||
|
CIRCUITPY_USB_MIDI = 0
|
||||||
|
# Does nothing without I2C
|
||||||
|
CIRCUITPY_REQUIRE_I2C_PULLUPS = 0
|
||||||
|
# No requirements, but takes extra flash
|
||||||
|
CIRCUITPY_ULAB = 0
|
||||||
|
|
||||||
Step 2: Init
|
Step 2: Init
|
||||||
--------------
|
--------------
|
||||||
Once your build is setup, the next step should be to get your clocks going as
|
Once your build is setup, the next step should be to get your clocks going as
|
||||||
|
161
docs/redirects.txt
Normal file
161
docs/redirects.txt
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
shared-bindings//__init__.rst shared-bindings//
|
||||||
|
shared-bindings/_bleio/Adapter.rst shared-bindings/_bleio/#_bleio.Adapter
|
||||||
|
shared-bindings/_bleio/Address.rst shared-bindings/_bleio/#_bleio.Address
|
||||||
|
shared-bindings/_bleio/Attribute.rst shared-bindings/_bleio/#_bleio.Attribute
|
||||||
|
shared-bindings/_bleio/BluetoothError.rst shared-bindings/_bleio/#_bleio.BluetoothError
|
||||||
|
shared-bindings/_bleio/Characteristic.rst shared-bindings/_bleio/#_bleio.Characteristic
|
||||||
|
shared-bindings/_bleio/CharacteristicBuffer.rst shared-bindings/_bleio/#_bleio.CharacteristicBuffer
|
||||||
|
shared-bindings/_bleio/Connection.rst shared-bindings/_bleio/#_bleio.Connection
|
||||||
|
shared-bindings/_bleio/ConnectionError.rst shared-bindings/_bleio/#_bleio.ConnectionError
|
||||||
|
shared-bindings/_bleio/Descriptor.rst shared-bindings/_bleio/#_bleio.Descriptor
|
||||||
|
shared-bindings/_bleio/PacketBuffer.rst shared-bindings/_bleio/#_bleio.PacketBuffer
|
||||||
|
shared-bindings/_bleio/RoleError.rst shared-bindings/_bleio/#_bleio.RoleError
|
||||||
|
shared-bindings/_bleio/ScanEntry.rst shared-bindings/_bleio/#_bleio.ScanEntry
|
||||||
|
shared-bindings/_bleio/ScanResults.rst shared-bindings/_bleio/#_bleio.ScanResults
|
||||||
|
shared-bindings/_bleio/SecurityError.rst shared-bindings/_bleio/#_bleio.SecurityError
|
||||||
|
shared-bindings/_bleio/Service.rst shared-bindings/_bleio/#_bleio.Service
|
||||||
|
shared-bindings/_bleio/UUID.rst shared-bindings/_bleio/#_bleio.UUID
|
||||||
|
shared-bindings/_bleio/__init__.rst shared-bindings/_bleio/
|
||||||
|
shared-bindings/_eve/__init__.rst shared-bindings/_eve/
|
||||||
|
shared-bindings/_pew/PewPew.rst shared-bindings/_pew/#_pew.PewPew
|
||||||
|
shared-bindings/_pew/__init__.rst shared-bindings/_pew/
|
||||||
|
shared-bindings/_pixelbuf/PixelBuf.rst shared-bindings/_pixelbuf/#_pixelbuf.PixelBuf
|
||||||
|
shared-bindings/_pixelbuf/__init__.rst shared-bindings/_pixelbuf/
|
||||||
|
shared-bindings/_stage/Layer.rst shared-bindings/_stage/#_stage.Layer
|
||||||
|
shared-bindings/_stage/Text.rst shared-bindings/_stage/#_stage.Text
|
||||||
|
shared-bindings/_stage/__init__.rst shared-bindings/_stage/
|
||||||
|
shared-bindings/aesio/AES.rst shared-bindings/aesio/#aesio.AES
|
||||||
|
shared-bindings/aesio/__init__.rst shared-bindings/aesio/
|
||||||
|
shared-bindings/analogio/AnalogIn.rst shared-bindings/analogio/#analogio.AnalogIn
|
||||||
|
shared-bindings/analogio/AnalogOut.rst shared-bindings/analogio/#analogio.AnalogOut
|
||||||
|
shared-bindings/analogio/__init__.rst shared-bindings/analogio/
|
||||||
|
shared-bindings/audiobusio/I2SOut.rst shared-bindings/audiobusio/#audiobusio.I2SOut
|
||||||
|
shared-bindings/audiobusio/PDMIn.rst shared-bindings/audiobusio/#audiobusio.PDMIn
|
||||||
|
shared-bindings/audiobusio/__init__.rst shared-bindings/audiobusio/
|
||||||
|
shared-bindings/audiocore/RawSample.rst shared-bindings/audiocore/#audiocore.RawSample
|
||||||
|
shared-bindings/audiocore/WaveFile.rst shared-bindings/audiocore/#audiocore.WaveFile
|
||||||
|
shared-bindings/audiocore/__init__.rst shared-bindings/audiocore/
|
||||||
|
shared-bindings/audioio/AudioOut.rst shared-bindings/audioio/#audioio.AudioOut
|
||||||
|
shared-bindings/audioio/__init__.rst shared-bindings/audioio/
|
||||||
|
shared-bindings/audiomixer/Mixer.rst shared-bindings/audiomixer/#audiomixer.Mixer
|
||||||
|
shared-bindings/audiomixer/MixerVoice.rst shared-bindings/audiomixer/#audiomixer.MixerVoice
|
||||||
|
shared-bindings/audiomixer/__init__.rst shared-bindings/audiomixer/
|
||||||
|
shared-bindings/audiomp3/MP3.rst shared-bindings/audiomp3/#audiomp3.MP3
|
||||||
|
shared-bindings/audiomp3/__init__.rst shared-bindings/audiomp3/
|
||||||
|
shared-bindings/audiopwmio/PWMAudioOut.rst shared-bindings/audiopwmio/#audiopwmio.PWMAudioOut
|
||||||
|
shared-bindings/audiopwmio/__init__.rst shared-bindings/audiopwmio/
|
||||||
|
shared-bindings/bitbangio/I2C.rst shared-bindings/bitbangio/#bitbangio.I2C
|
||||||
|
shared-bindings/bitbangio/OneWire.rst shared-bindings/bitbangio/#bitbangio.OneWire
|
||||||
|
shared-bindings/bitbangio/SPI.rst shared-bindings/bitbangio/#bitbangio.SPI
|
||||||
|
shared-bindings/bitbangio/__init__.rst shared-bindings/bitbangio/
|
||||||
|
shared-bindings/board/__init__.rst shared-bindings/board/
|
||||||
|
shared-bindings/busio/I2C.rst shared-bindings/busio/#busio.I2C
|
||||||
|
shared-bindings/busio/OneWire.rst shared-bindings/busio/#busio.OneWire
|
||||||
|
shared-bindings/busio/Parity.rst shared-bindings/busio/#busio.Parity
|
||||||
|
shared-bindings/busio/SPI.rst shared-bindings/busio/#busio.SPI
|
||||||
|
shared-bindings/busio/UART.rst shared-bindings/busio/#busio.UART
|
||||||
|
shared-bindings/busio/__init__.rst shared-bindings/busio/
|
||||||
|
shared-bindings/countio/Counter.rst shared-bindings/countio/#countio.Counter
|
||||||
|
shared-bindings/countio/__init__.rst shared-bindings/countio/
|
||||||
|
shared-bindings/digitalio/DigitalInOut.rst shared-bindings/digitalio/#digitalio.DigitalInOut
|
||||||
|
shared-bindings/digitalio/Direction.rst shared-bindings/digitalio/#digitalio.Direction
|
||||||
|
shared-bindings/digitalio/DriveMode.rst shared-bindings/digitalio/#digitalio.DriveMode
|
||||||
|
shared-bindings/digitalio/Pull.rst shared-bindings/digitalio/#digitalio.Pull
|
||||||
|
shared-bindings/digitalio/__init__.rst shared-bindings/digitalio/
|
||||||
|
shared-bindings/displayio/Bitmap.rst shared-bindings/displayio/#displayio.Bitmap
|
||||||
|
shared-bindings/displayio/ColorConverter.rst shared-bindings/displayio/#displayio.ColorConverter
|
||||||
|
shared-bindings/displayio/Display.rst shared-bindings/displayio/#displayio.Display
|
||||||
|
shared-bindings/displayio/EPaperDisplay.rst shared-bindings/displayio/#displayio.EPaperDisplay
|
||||||
|
shared-bindings/displayio/FourWire.rst shared-bindings/displayio/#displayio.FourWire
|
||||||
|
shared-bindings/displayio/Group.rst shared-bindings/displayio/#displayio.Group
|
||||||
|
shared-bindings/displayio/I2CDisplay.rst shared-bindings/displayio/#displayio.I2CDisplay
|
||||||
|
shared-bindings/displayio/OnDiskBitmap.rst shared-bindings/displayio/#displayio.OnDiskBitmap
|
||||||
|
shared-bindings/displayio/Palette.rst shared-bindings/displayio/#displayio.Palette
|
||||||
|
shared-bindings/displayio/ParallelBus.rst shared-bindings/displayio/#displayio.ParallelBus
|
||||||
|
shared-bindings/displayio/Shape.rst shared-bindings/displayio/#displayio.Shape
|
||||||
|
shared-bindings/displayio/TileGrid.rst shared-bindings/displayio/#displayio.TileGrid
|
||||||
|
shared-bindings/displayio/__init__.rst shared-bindings/displayio/
|
||||||
|
shared-bindings/fontio/BuiltinFont.rst shared-bindings/fontio/#fontio.BuiltinFont
|
||||||
|
shared-bindings/fontio/Glyph.rst shared-bindings/fontio/#fontio.Glyph
|
||||||
|
shared-bindings/fontio/__init__.rst shared-bindings/fontio/
|
||||||
|
shared-bindings/framebufferio/FramebufferDisplay.rst shared-bindings/framebufferio/#framebufferio.FramebufferDisplay
|
||||||
|
shared-bindings/framebufferio/__init__.rst shared-bindings/framebufferio/
|
||||||
|
shared-bindings/frequencyio/FrequencyIn.rst shared-bindings/frequencyio/#frequencyio.FrequencyIn
|
||||||
|
shared-bindings/frequencyio/__init__.rst shared-bindings/frequencyio/
|
||||||
|
shared-bindings/gamepad/GamePad.rst shared-bindings/gamepad/#gamepad.GamePad
|
||||||
|
shared-bindings/gamepad/__init__.rst shared-bindings/gamepad/
|
||||||
|
shared-bindings/gamepadshift/GamePadShift.rst shared-bindings/gamepadshift/#gamepadshift.GamePadShift
|
||||||
|
shared-bindings/gamepadshift/__init__.rst shared-bindings/gamepadshift/
|
||||||
|
shared-bindings/gnss/__init__.rst shared-bindings/gnss/
|
||||||
|
shared-bindings/i2cperipheral/__init__.rst shared-bindings/i2cperipheral/
|
||||||
|
shared-bindings/i2csecondary/__init__.rst shared-bindings/i2csecondary/
|
||||||
|
shared-bindings/i2cslave/I2CSlave.rst shared-bindings/i2cperipheral/#i2cperipheral.I2CPeripheral
|
||||||
|
shared-bindings/i2cslave/I2CSlaveRequest.rst shared-bindings/i2cperipheral/#i2cperipheral.I2CPeripheralRequest
|
||||||
|
shared-bindings/math/__init__.rst shared-bindings/math/
|
||||||
|
shared-bindings/microcontroller/Pin.rst shared-bindings/microcontroller/#microcontroller.Pin
|
||||||
|
shared-bindings/microcontroller/Processor.rst shared-bindings/microcontroller/#microcontroller.Processor
|
||||||
|
shared-bindings/microcontroller/RunMode.rst shared-bindings/microcontroller/#microcontroller.RunMode
|
||||||
|
shared-bindings/microcontroller/__init__.rst shared-bindings/microcontroller/
|
||||||
|
shared-bindings/multiterminal/__init__.rst shared-bindings/multiterminal/
|
||||||
|
shared-bindings/neopixel_write/__init__.rst shared-bindings/neopixel_write/
|
||||||
|
shared-bindings/network/__init__.rst shared-bindings/network/
|
||||||
|
shared-bindings/nvm/ByteArray.rst shared-bindings/nvm/#nvm.ByteArray
|
||||||
|
shared-bindings/nvm/__init__.rst shared-bindings/nvm/
|
||||||
|
shared-bindings/os/__init__.rst shared-bindings/os/
|
||||||
|
shared-bindings/protomatter/__init__.rst shared-bindings/protomatter/
|
||||||
|
shared-bindings/ps2io/Ps2.rst shared-bindings/ps2io/#ps2io.Ps2
|
||||||
|
shared-bindings/ps2io/__init__.rst shared-bindings/ps2io/
|
||||||
|
shared-bindings/pulseio/PWMOut.rst shared-bindings/pulseio/#pulseio.PWMOut
|
||||||
|
shared-bindings/pulseio/PulseIn.rst shared-bindings/pulseio/#pulseio.PulseIn
|
||||||
|
shared-bindings/pulseio/PulseOut.rst shared-bindings/pulseio/#pulseio.PulseOut
|
||||||
|
shared-bindings/pulseio/__init__.rst shared-bindings/pulseio/
|
||||||
|
shared-bindings/random/__init__.rst shared-bindings/random/
|
||||||
|
shared-bindings/rgbmatrix/RGBMatrix.rst shared-bindings/rgbmatrix/#rgbmatrix.RGBMatrix
|
||||||
|
shared-bindings/rgbmatrix/__init__.rst shared-bindings/rgbmatrix/
|
||||||
|
shared-bindings/rotaryio/IncrementalEncoder.rst shared-bindings/rotaryio/#rotaryio.IncrementalEncoder
|
||||||
|
shared-bindings/rotaryio/__init__.rst shared-bindings/rotaryio/
|
||||||
|
shared-bindings/rtc/RTC.rst shared-bindings/rtc/#rtc.RTC
|
||||||
|
shared-bindings/rtc/__init__.rst shared-bindings/rtc/
|
||||||
|
shared-bindings/samd/Clock.rst shared-bindings/samd/#samd.Clock
|
||||||
|
shared-bindings/samd/__init__.rst shared-bindings/samd/
|
||||||
|
shared-bindings/socket/__init__.rst shared-bindings/socket/
|
||||||
|
shared-bindings/socket/socket.rst shared-bindings/socket/#socket.socket
|
||||||
|
shared-bindings/storage/VfsFat.rst shared-bindings/storage/#storage.VfsFat
|
||||||
|
shared-bindings/storage/__init__.rst shared-bindings/storage/
|
||||||
|
shared-bindings/struct/__init__.rst shared-bindings/struct/
|
||||||
|
shared-bindings/supervisor/Runtime.rst shared-bindings/supervisor/#supervisor.Runtime
|
||||||
|
shared-bindings/supervisor/__init__.rst shared-bindings/supervisor/
|
||||||
|
shared-bindings/terminalio/Terminal.rst shared-bindings/terminalio/#terminalio.Terminal
|
||||||
|
shared-bindings/terminalio/__init__.rst shared-bindings/terminalio/
|
||||||
|
shared-bindings/time/__init__.rst shared-bindings/time/
|
||||||
|
shared-bindings/time/struct_time.rst shared-bindings/time/#time.struct_time
|
||||||
|
shared-bindings/touchio/TouchIn.rst shared-bindings/touchio/#touchio.TouchIn
|
||||||
|
shared-bindings/touchio/__init__.rst shared-bindings/touchio/
|
||||||
|
shared-bindings/uheap/__init__.rst shared-bindings/uheap/
|
||||||
|
shared-bindings/ulab/__init__.rst shared-bindings/ulab/
|
||||||
|
shared-bindings/ulab/approx/__init__.rst shared-bindings/ulab/approx/
|
||||||
|
shared-bindings/ulab/array.rst shared-bindings/ulab/#ulab.array
|
||||||
|
shared-bindings/ulab/compare/__init__.rst shared-bindings/ulab/compare/
|
||||||
|
shared-bindings/ulab/extras/__init__.rst shared-bindings/ulab/extras/
|
||||||
|
shared-bindings/ulab/fft/__init__.rst shared-bindings/ulab/fft/
|
||||||
|
shared-bindings/ulab/filter/__init__.rst shared-bindings/ulab/filter/
|
||||||
|
shared-bindings/ulab/linalg/__init__.rst shared-bindings/ulab/linalg/
|
||||||
|
shared-bindings/ulab/numerical/__init__.rst shared-bindings/ulab/numerical/
|
||||||
|
shared-bindings/ulab/poly/__init__.rst shared-bindings/ulab/poly/
|
||||||
|
shared-bindings/ulab/vector/__init__.rst shared-bindings/ulab/vector/
|
||||||
|
shared-bindings/usb_hid/Device.rst shared-bindings/usb_hid/#usb_hid.Device
|
||||||
|
shared-bindings/usb_hid/__init__.rst shared-bindings/usb_hid/
|
||||||
|
shared-bindings/usb_midi/PortIn.rst shared-bindings/usb_midi/#usb_midi.PortIn
|
||||||
|
shared-bindings/usb_midi/PortOut.rst shared-bindings/usb_midi/#usb_midi.PortOut
|
||||||
|
shared-bindings/usb_midi/__init__.rst shared-bindings/usb_midi/
|
||||||
|
shared-bindings/ustack/__init__.rst shared-bindings/ustack/
|
||||||
|
shared-bindings/vectorio/Circle.rst shared-bindings/vectorio/#vectorio.Circle
|
||||||
|
shared-bindings/vectorio/Polygon.rst shared-bindings/vectorio/#vectorio.Polygon
|
||||||
|
shared-bindings/vectorio/Rectangle.rst shared-bindings/vectorio/#vectorio.Rectangle
|
||||||
|
shared-bindings/vectorio/VectorShape.rst shared-bindings/vectorio/#vectorio.VectorShape
|
||||||
|
shared-bindings/vectorio/__init__.rst shared-bindings/vectorio/
|
||||||
|
shared-bindings/watchdog/WatchDogMode.rst shared-bindings/watchdog/#watchdog.WatchDogMode
|
||||||
|
shared-bindings/watchdog/WatchDogTimer.rst shared-bindings/watchdog/#watchdog.WatchDogTimer
|
||||||
|
shared-bindings/watchdog/__init__.rst shared-bindings/watchdog/
|
||||||
|
shared-bindings/wiznet/WIZNET5K.rst shared-bindings/wiznet/#wiznet.WIZNET5K
|
||||||
|
shared-bindings/wiznet/__init__.rst shared-bindings/wiznet/
|
@ -1,3 +1,7 @@
|
|||||||
sphinx==1.8.5
|
sphinx<4
|
||||||
recommonmark==0.5.0
|
recommonmark==0.6.0
|
||||||
sphinxcontrib-svg2pdfconverter==0.1.0
|
sphinxcontrib-svg2pdfconverter==0.1.0
|
||||||
|
astroid
|
||||||
|
sphinx-autoapi
|
||||||
|
isort
|
||||||
|
black
|
||||||
|
@ -6,18 +6,28 @@ def rstjinja(app, docname, source):
|
|||||||
Render our pages as a jinja template for fancy templating goodness.
|
Render our pages as a jinja template for fancy templating goodness.
|
||||||
"""
|
"""
|
||||||
# Make sure we're outputting HTML
|
# Make sure we're outputting HTML
|
||||||
if app.builder.format != 'html':
|
if app.builder.format not in ("html", "latex"):
|
||||||
return
|
return
|
||||||
|
|
||||||
# we only want our one jinja template to run through this func
|
# we only want our one jinja template to run through this func
|
||||||
if "shared-bindings/support_matrix" not in docname:
|
if "shared-bindings/support_matrix" not in docname:
|
||||||
return
|
return
|
||||||
|
|
||||||
src = source[0]
|
src = rendered = source[0]
|
||||||
print(docname)
|
print(docname)
|
||||||
rendered = app.builder.templates.render_string(
|
|
||||||
src, app.config.html_context
|
if app.builder.format == "html":
|
||||||
)
|
rendered = app.builder.templates.render_string(
|
||||||
|
src, app.config.html_context
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
from sphinx.util.template import BaseRenderer
|
||||||
|
renderer = BaseRenderer()
|
||||||
|
rendered = renderer.render_string(
|
||||||
|
src,
|
||||||
|
app.config.html_context
|
||||||
|
)
|
||||||
|
|
||||||
source[0] = rendered
|
source[0] = rendered
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2019 Michael Schroeder
|
# SPDX-FileCopyrightText: Copyright (c) 2019 Michael Schroeder
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,62 +23,36 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
SUPPORTED_PORTS = ["atmel-samd", "nrf", "mimxrt10xx"]
|
SUPPORTED_PORTS = ['atmel-samd', 'esp32s2', 'litex', 'mimxrt10xx', 'nrf', 'stm']
|
||||||
|
|
||||||
|
def get_circuitpython_root_dir():
|
||||||
def parse_port_config(contents, chip_keyword=None):
|
""" The path to the root './circuitpython' directory
|
||||||
""" Compile a dictionary of port-wide module configs, which may
|
|
||||||
be categorized by chipset.
|
|
||||||
"""
|
"""
|
||||||
chip_fam = "all"
|
file_path = pathlib.Path(__file__).resolve()
|
||||||
ifeq_found = False
|
root_dir = file_path.parent.parent
|
||||||
port_config_results = {"all": []}
|
|
||||||
|
|
||||||
chip_pattern = ""
|
return root_dir
|
||||||
if chip_keyword:
|
|
||||||
chip_pattern = (
|
|
||||||
re.compile("(?<=ifeq\s\(\$\({}\)\,)(\w+)".format(chip_keyword))
|
|
||||||
)
|
|
||||||
|
|
||||||
for line in contents:
|
|
||||||
if chip_keyword:
|
|
||||||
if not ifeq_found:
|
|
||||||
check_ifeq = chip_pattern.search(line)
|
|
||||||
if check_ifeq:
|
|
||||||
ifeq_found = True
|
|
||||||
chip_fam = check_ifeq.group(1)
|
|
||||||
#print("found chip:", chip_fam)
|
|
||||||
else:
|
|
||||||
ifeq_found = False
|
|
||||||
chip_fam = "all"
|
|
||||||
else:
|
|
||||||
if "endif" in line:
|
|
||||||
ifeq_found = False
|
|
||||||
chip_fam = "all"
|
|
||||||
|
|
||||||
if "CIRCUITPY_" in line:
|
|
||||||
if chip_fam in port_config_results:
|
|
||||||
port_config_results[chip_fam].append(line.rstrip("\n"))
|
|
||||||
else:
|
|
||||||
port_config_results[chip_fam] = [line.rstrip("\n")]
|
|
||||||
|
|
||||||
#print(port_config_results)
|
|
||||||
return port_config_results
|
|
||||||
|
|
||||||
def get_shared_bindings():
|
def get_shared_bindings():
|
||||||
""" Get a list of modules in shared-bindings based on folder names
|
""" Get a list of modules in shared-bindings based on folder names
|
||||||
"""
|
"""
|
||||||
return [item for item in os.listdir("./shared-bindings")]
|
shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings"
|
||||||
|
return [item.name for item in shared_bindings_dir.iterdir()] + ["ulab"]
|
||||||
|
|
||||||
|
|
||||||
def read_mpconfig():
|
def read_mpconfig():
|
||||||
""" Open 'circuitpy_mpconfig.mk' and return the contents.
|
""" Open 'circuitpy_mpconfig.mk' and return the contents.
|
||||||
"""
|
"""
|
||||||
configs = []
|
configs = []
|
||||||
with open("py/circuitpy_mpconfig.mk") as mpconfig:
|
cpy_mpcfg = get_circuitpython_root_dir() / "py" / "circuitpy_mpconfig.mk"
|
||||||
|
with open(cpy_mpcfg) as mpconfig:
|
||||||
configs = mpconfig.read()
|
configs = mpconfig.read()
|
||||||
|
|
||||||
return configs
|
return configs
|
||||||
@ -98,7 +72,7 @@ def build_module_map():
|
|||||||
for module in modules:
|
for module in modules:
|
||||||
full_name = module
|
full_name = module
|
||||||
search_name = module.lstrip("_")
|
search_name = module.lstrip("_")
|
||||||
re_pattern = "CIRCUITPY_{}\s=\s(.+)".format(search_name.upper())
|
re_pattern = "CIRCUITPY_{}\s*\??=\s*(.+)".format(search_name.upper())
|
||||||
find_config = re.findall(re_pattern, configs)
|
find_config = re.findall(re_pattern, configs)
|
||||||
if not find_config:
|
if not find_config:
|
||||||
continue
|
continue
|
||||||
@ -117,171 +91,90 @@ def build_module_map():
|
|||||||
"excluded": {}
|
"excluded": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#print(base)
|
|
||||||
return base
|
return base
|
||||||
|
|
||||||
|
def get_settings_from_makefile(port_dir, board_name):
|
||||||
|
""" Invoke make in a mode which prints the database, then parse it for
|
||||||
|
settings.
|
||||||
|
|
||||||
def get_excluded_boards(base):
|
This means that the effect of all Makefile directives is taken
|
||||||
""" Cycles through each board's `mpconfigboard.mk` file to determine
|
into account, without having to re-encode the logic that sets them
|
||||||
if each module is included or not. Boards are selected by existence
|
in this script, something that has proved error-prone
|
||||||
in a port listed in `SUPPORTED_PORTS` (e.g. `/port/nrf/feather_52840`)
|
|
||||||
|
|
||||||
Boards are further categorized by their respective chipset (SAMD21,
|
|
||||||
SAMD51, nRF52840, etc.)
|
|
||||||
"""
|
"""
|
||||||
modules = list(base.keys())
|
contents = subprocess.run(
|
||||||
|
["make", "-C", port_dir, f"BOARD={board_name}", "-qp", "print-CC"],
|
||||||
|
encoding="utf-8",
|
||||||
|
errors="replace",
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
# Make signals errors with exit status 2; 0 and 1 are "non-error" statuses
|
||||||
|
if contents.returncode not in (0, 1):
|
||||||
|
error_msg = (
|
||||||
|
f"Invoking '{' '.join(contents.args)}' exited with "
|
||||||
|
f"{contents.returncode}: {contents.stderr}"
|
||||||
|
)
|
||||||
|
raise RuntimeError(error_msg)
|
||||||
|
|
||||||
re_board_chip = None
|
settings = {}
|
||||||
chip_keyword = None
|
for line in contents.stdout.split('\n'):
|
||||||
for port in SUPPORTED_PORTS:
|
m = re.match(r'^([A-Z][A-Z0-9_]*) = (.*)$', line)
|
||||||
# each port appears to use its own define for the chipset
|
if m:
|
||||||
if port in ["atmel-samd"]:
|
settings[m.group(1)] = m.group(2)
|
||||||
re_board_chip = re.compile("CHIP_FAMILY\s=\s(\w+)")
|
|
||||||
chip_keyword = "CHIP_FAMILY"
|
|
||||||
elif port in ["nrf"]:
|
|
||||||
re_board_chip = re.compile("MCU_VARIANT\s=\s(\w+)")
|
|
||||||
|
|
||||||
port_dir = "ports/{}".format(port)
|
return settings
|
||||||
|
|
||||||
port_config_contents = ""
|
def lookup_setting(settings, key, default=''):
|
||||||
with open(os.path.join(port_dir, "mpconfigport.mk")) as port_config:
|
while True:
|
||||||
port_config_contents = port_config.readlines()
|
value = settings.get(key, default)
|
||||||
port_config = parse_port_config(port_config_contents, chip_keyword)
|
if not value.startswith('$'):
|
||||||
|
break
|
||||||
|
key = value[2:-1]
|
||||||
|
return value
|
||||||
|
|
||||||
for entry in os.scandir(os.path.join(port_dir, "boards")):
|
def all_ports_all_boards(ports=SUPPORTED_PORTS):
|
||||||
|
for port in ports:
|
||||||
|
|
||||||
|
port_dir = get_circuitpython_root_dir() / "ports" / port
|
||||||
|
for entry in (port_dir / "boards").iterdir():
|
||||||
if not entry.is_dir():
|
if not entry.is_dir():
|
||||||
continue
|
continue
|
||||||
|
yield (port, entry)
|
||||||
|
|
||||||
contents = ""
|
def support_matrix_by_board(use_branded_name=True):
|
||||||
board_dir = os.path.join(entry.path, "mpconfigboard.mk")
|
|
||||||
with open(board_dir) as board:
|
|
||||||
contents = board.read()
|
|
||||||
|
|
||||||
board_chip = re_board_chip.search(contents)
|
|
||||||
#print(entry.name, board_chip.group(1))
|
|
||||||
if not board_chip:
|
|
||||||
board_chip = "Unknown Chip"
|
|
||||||
else:
|
|
||||||
board_chip = board_chip.group(1)
|
|
||||||
|
|
||||||
# add port_config results to contents
|
|
||||||
contents += "\n" + "\n".join(port_config["all"])
|
|
||||||
if board_chip in port_config:
|
|
||||||
contents += "\n" + "\n".join(port_config[board_chip])
|
|
||||||
|
|
||||||
check_dependent_modules = dict()
|
|
||||||
for module in modules:
|
|
||||||
board_is_excluded = False
|
|
||||||
# check if board uses `SMALL_BUILD`. if yes, and current
|
|
||||||
# module is marked as `FULL_BUILD`, board is excluded
|
|
||||||
small_build = re.search("CIRCUITPY_SMALL_BUILD = 1", contents)
|
|
||||||
if small_build and base[module]["full_build"] == "1":
|
|
||||||
board_is_excluded = True
|
|
||||||
|
|
||||||
# check if board uses `MINIMAL_BUILD`. if yes, and current
|
|
||||||
# module is marked as `DEFAULT_BUILD`, board is excluded
|
|
||||||
min_build = re.search("CIRCUITPY_MINIMAL_BUILD = 1", contents)
|
|
||||||
if min_build and base[module]["default_value"] == "CIRCUITPY_DEFAULT_BUILD":
|
|
||||||
board_is_excluded = True
|
|
||||||
|
|
||||||
# check if module is specifically disabled for this board
|
|
||||||
re_pattern = r"CIRCUITPY_{}\s=\s(\w)".format(module.upper())
|
|
||||||
find_module = re.search(re_pattern, contents)
|
|
||||||
if not find_module:
|
|
||||||
if base[module]["default_value"].isdigit():
|
|
||||||
# check if default inclusion is off ('0'). if the board doesn't
|
|
||||||
# have it explicitly enabled, its excluded.
|
|
||||||
if base[module]["default_value"] == "0":
|
|
||||||
board_is_excluded = True
|
|
||||||
else:
|
|
||||||
# this module is dependent on another module. add it
|
|
||||||
# to the list to check after processing all other modules.
|
|
||||||
# only need to check exclusion if it isn't already excluded.
|
|
||||||
if (not board_is_excluded and
|
|
||||||
base[module]["default_value"] not in [
|
|
||||||
"None",
|
|
||||||
"CIRCUITPY_DEFAULT_BUILD"
|
|
||||||
]):
|
|
||||||
check_dependent_modules[module] = base[module]["default_value"]
|
|
||||||
else:
|
|
||||||
board_is_excluded = find_module.group(1) == "0"
|
|
||||||
|
|
||||||
if board_is_excluded:
|
|
||||||
if board_chip in base[module]["excluded"]:
|
|
||||||
base[module]["excluded"][board_chip].append(entry.name)
|
|
||||||
else:
|
|
||||||
base[module]["excluded"][board_chip] = [entry.name]
|
|
||||||
|
|
||||||
for module in check_dependent_modules:
|
|
||||||
depend_results = set()
|
|
||||||
|
|
||||||
parents = check_dependent_modules[module].split("CIRCUITPY_")
|
|
||||||
parents = [item.strip(", ").lower() for item in parents if item]
|
|
||||||
|
|
||||||
for parent in parents:
|
|
||||||
if parent in base:
|
|
||||||
if (board_chip in base[parent]["excluded"] and
|
|
||||||
entry.name in base[parent]["excluded"][board_chip]):
|
|
||||||
depend_results.add(False)
|
|
||||||
else:
|
|
||||||
depend_results.add(True)
|
|
||||||
|
|
||||||
# only exclude the module if there were zero parents enabled
|
|
||||||
# as determined by the 'depend_results' set.
|
|
||||||
if not any(depend_results):
|
|
||||||
if board_chip in base[module]["excluded"]:
|
|
||||||
base[module]["excluded"][board_chip].append(entry.name)
|
|
||||||
else:
|
|
||||||
base[module]["excluded"][board_chip] = [entry.name]
|
|
||||||
|
|
||||||
#print(json.dumps(base, indent=2))
|
|
||||||
return base
|
|
||||||
|
|
||||||
|
|
||||||
def support_matrix_excluded_boards():
|
|
||||||
""" Compiles a list of available modules, and which board definitions
|
|
||||||
do not include them.
|
|
||||||
"""
|
|
||||||
base = build_module_map()
|
|
||||||
|
|
||||||
return get_excluded_boards(base)
|
|
||||||
|
|
||||||
def support_matrix_by_board():
|
|
||||||
""" Compiles a list of the available core modules available for each
|
""" Compiles a list of the available core modules available for each
|
||||||
board.
|
board.
|
||||||
"""
|
"""
|
||||||
base = build_module_map()
|
base = build_module_map()
|
||||||
base_with_exclusions = get_excluded_boards(base)
|
|
||||||
|
|
||||||
boards = dict()
|
def support_matrix(arg):
|
||||||
for port in SUPPORTED_PORTS:
|
port, entry = arg
|
||||||
port_dir = "ports/{}/boards".format(port)
|
port_dir = get_circuitpython_root_dir() / "ports" / port
|
||||||
for entry in os.scandir(port_dir):
|
settings = get_settings_from_makefile(str(port_dir), entry.name)
|
||||||
if not entry.is_dir():
|
|
||||||
continue
|
|
||||||
board_modules = []
|
|
||||||
|
|
||||||
board_name = entry.name
|
if use_branded_name:
|
||||||
board_contents = ""
|
with open(entry / "mpconfigboard.h") as get_name:
|
||||||
with open(os.path.join(entry.path, "mpconfigboard.h")) as get_name:
|
|
||||||
board_contents = get_name.read()
|
board_contents = get_name.read()
|
||||||
board_name_re = re.search("(?<=MICROPY_HW_BOARD_NAME)\s+(.+)",
|
board_name_re = re.search(r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)",
|
||||||
board_contents)
|
board_contents)
|
||||||
if board_name_re:
|
if board_name_re:
|
||||||
board_name = board_name_re.group(1).strip('"')
|
board_name = board_name_re.group(1).strip('"')
|
||||||
|
else:
|
||||||
|
board_name = entry.name
|
||||||
|
|
||||||
for module in base_with_exclusions.keys():
|
board_modules = []
|
||||||
#print(module)
|
for module in base:
|
||||||
board_has_module = True
|
key = f'CIRCUITPY_{module.upper()}'
|
||||||
if base_with_exclusions[module]["excluded"]:
|
if int(lookup_setting(settings, key, '0')):
|
||||||
for port in base_with_exclusions[module]["excluded"].values():
|
board_modules.append(base[module]['name'])
|
||||||
#print(port)
|
|
||||||
if entry.name in port:
|
|
||||||
board_has_module = False
|
|
||||||
|
|
||||||
if board_has_module:
|
return (board_name, sorted(board_modules))
|
||||||
board_modules.append(base_with_exclusions[module]["name"])
|
|
||||||
boards[board_name] = sorted(board_modules)
|
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
|
||||||
|
boards = dict(sorted(executor.map(support_matrix, all_ports_all_boards())))
|
||||||
|
|
||||||
#print(json.dumps(boards, indent=2))
|
#print(json.dumps(boards, indent=2))
|
||||||
return boards
|
return boards
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(json.dumps(support_matrix_by_board(), indent=2))
|
||||||
|
5
docs/static/customstyle.css
vendored
5
docs/static/customstyle.css
vendored
@ -9,7 +9,6 @@
|
|||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* custom CSS to sticky the ' viewing outdated version'
|
/* custom CSS to sticky the ' viewing outdated version'
|
||||||
warning
|
warning
|
||||||
*/
|
*/
|
||||||
@ -37,3 +36,7 @@ body {
|
|||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.strike {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
3
docs/static/favicon.ico.license
vendored
Normal file
3
docs/static/favicon.ico.license
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries
|
||||||
|
|
||||||
|
SPDX-License-Identifier: CC-BY-4.0
|
@ -1,14 +1,20 @@
|
|||||||
Supported Ports
|
Supported Ports
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Adafruit's CircuitPython currently has limited support with a focus on supporting the Atmel SAMD
|
CircuitPython supports a number of microcontroller families. Support quality for each varies
|
||||||
and ESP8266.
|
depending on the active contributors for each port.
|
||||||
|
|
||||||
|
Adafruit sponsored developers are actively contributing to atmel-samd, mimxrt10xx, nrf and stm
|
||||||
|
ports. They also maintain the other ports in order to ensure the boards build. Additional testing
|
||||||
|
is limited.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
../ports/atmel-samd/README
|
../ports/atmel-samd/README
|
||||||
|
../ports/cxd56/README
|
||||||
|
../ports/litex/README
|
||||||
../ports/mimxrt10xx/README
|
../ports/mimxrt10xx/README
|
||||||
../ports/nrf/README
|
../ports/nrf/README
|
||||||
../ports/stm/README
|
../ports/stm/README
|
||||||
../ports/cxd56/README
|
../ports/esp32s2/README
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2018 Damien P. George
|
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2018 Damien P. George
|
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2018 Damien P. George
|
* SPDX-FileCopyrightText: Copyright (c) 2016-2018 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2018 Damien P. George
|
* SPDX-FileCopyrightText: Copyright (c) 2016-2018 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -244,4 +244,3 @@ void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
|||||||
ptr += len;
|
ptr += len;
|
||||||
setSn_RX_RD(sn,ptr);
|
setSn_RX_RD(sn,ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
#ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
||||||
#define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
#define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
||||||
|
|
||||||
|
@ -1,641 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "py/mperrno.h"
|
|
||||||
#include "py/mphal.h"
|
|
||||||
#include "py/runtime.h"
|
|
||||||
#include "extmod/machine_i2c.h"
|
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
|
||||||
|
|
||||||
#if MICROPY_PY_MACHINE_I2C
|
|
||||||
|
|
||||||
typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t;
|
|
||||||
|
|
||||||
STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) {
|
|
||||||
// We need to use an accurate delay to get acceptable I2C
|
|
||||||
// speeds (eg 1us should be not much more than 1us).
|
|
||||||
mp_hal_delay_us_fast(self->us_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
|
|
||||||
mp_hal_pin_od_low(self->scl);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
|
|
||||||
uint32_t count = self->us_timeout;
|
|
||||||
|
|
||||||
mp_hal_pin_od_high(self->scl);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
// For clock stretching, wait for the SCL pin to be released, with timeout.
|
|
||||||
for (; mp_hal_pin_read(self->scl) == 0 && count; --count) {
|
|
||||||
mp_hal_delay_us_fast(1);
|
|
||||||
}
|
|
||||||
if (count == 0) {
|
|
||||||
return -MP_ETIMEDOUT;
|
|
||||||
}
|
|
||||||
return 0; // success
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
|
|
||||||
mp_hal_pin_od_low(self->sda);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
|
|
||||||
mp_hal_pin_od_high(self->sda);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) {
|
|
||||||
return mp_hal_pin_read(self->sda);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int mp_hal_i2c_start(machine_i2c_obj_t *self) {
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
mp_hal_i2c_sda_low(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
return 0; // success
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int mp_hal_i2c_stop(machine_i2c_obj_t *self) {
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
mp_hal_i2c_sda_low(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
|
|
||||||
self->us_delay = 500000 / freq;
|
|
||||||
if (self->us_delay == 0) {
|
|
||||||
self->us_delay = 1;
|
|
||||||
}
|
|
||||||
mp_hal_pin_open_drain(self->scl);
|
|
||||||
mp_hal_pin_open_drain(self->sda);
|
|
||||||
mp_hal_i2c_stop(self); // ignore error
|
|
||||||
}
|
|
||||||
|
|
||||||
// return value:
|
|
||||||
// 0 - byte written and ack received
|
|
||||||
// 1 - byte written and nack received
|
|
||||||
// <0 - error, with errno being the negative of the return value
|
|
||||||
STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
|
|
||||||
for (int i = 7; i >= 0; i--) {
|
|
||||||
if ((val >> i) & 1) {
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
} else {
|
|
||||||
mp_hal_i2c_sda_low(self);
|
|
||||||
}
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ack = mp_hal_i2c_sda_read(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
|
|
||||||
return ack;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return value:
|
|
||||||
// 0 - success
|
|
||||||
// <0 - error, with errno being the negative of the return value
|
|
||||||
STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
|
|
||||||
uint8_t data = 0;
|
|
||||||
for (int i = 7; i >= 0; i--) {
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
data = (data << 1) | mp_hal_i2c_sda_read(self);
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
}
|
|
||||||
*val = data;
|
|
||||||
|
|
||||||
// send ack/nack bit
|
|
||||||
if (!nack) {
|
|
||||||
mp_hal_i2c_sda_low(self);
|
|
||||||
}
|
|
||||||
mp_hal_i2c_delay(self);
|
|
||||||
int ret = mp_hal_i2c_scl_release(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
mp_hal_i2c_scl_low(self);
|
|
||||||
mp_hal_i2c_sda_release(self);
|
|
||||||
|
|
||||||
return 0; // success
|
|
||||||
}
|
|
||||||
|
|
||||||
// return value:
|
|
||||||
// >=0 - number of acks received
|
|
||||||
// <0 - error, with errno being the negative of the return value
|
|
||||||
int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
|
|
||||||
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
|
|
||||||
|
|
||||||
// start the I2C transaction
|
|
||||||
int ret = mp_hal_i2c_start(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the slave address
|
|
||||||
ret = mp_hal_i2c_write_byte(self, addr << 1);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
} else if (ret != 0) {
|
|
||||||
// nack received, release the bus cleanly
|
|
||||||
mp_hal_i2c_stop(self);
|
|
||||||
return -MP_ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the buffer to the I2C memory
|
|
||||||
int num_acks = 0;
|
|
||||||
while (len--) {
|
|
||||||
ret = mp_hal_i2c_write_byte(self, *src++);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
} else if (ret != 0) {
|
|
||||||
// nack received, stop sending
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++num_acks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish the I2C transaction
|
|
||||||
if (stop) {
|
|
||||||
ret = mp_hal_i2c_stop(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_acks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return value:
|
|
||||||
// 0 - success
|
|
||||||
// <0 - error, with errno being the negative of the return value
|
|
||||||
int mp_machine_soft_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
|
|
||||||
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
|
|
||||||
|
|
||||||
// start the I2C transaction
|
|
||||||
int ret = mp_hal_i2c_start(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the slave address
|
|
||||||
ret = mp_hal_i2c_write_byte(self, (addr << 1) | 1);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
} else if (ret != 0) {
|
|
||||||
// nack received, release the bus cleanly
|
|
||||||
mp_hal_i2c_stop(self);
|
|
||||||
return -MP_ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the bytes from the slave
|
|
||||||
while (len--) {
|
|
||||||
ret = mp_hal_i2c_read_byte(self, dest++, len == 0);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish the I2C transaction
|
|
||||||
if (stop) {
|
|
||||||
ret = mp_hal_i2c_stop(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; // success
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
// MicroPython bindings for I2C
|
|
||||||
|
|
||||||
STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
enum { ARG_scl, ARG_sda, ARG_freq, ARG_timeout };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
|
||||||
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
|
||||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
|
|
||||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
|
|
||||||
};
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
||||||
self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
|
|
||||||
self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
|
|
||||||
self->us_timeout = args[ARG_timeout].u_int;
|
|
||||||
mp_hal_i2c_init(self, args[ARG_freq].u_int);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|
||||||
// check the id argument, if given
|
|
||||||
if (n_args > 0) {
|
|
||||||
if (args[0] != MP_OBJ_NEW_SMALL_INT(-1)) {
|
|
||||||
#if defined(MICROPY_PY_MACHINE_I2C_MAKE_NEW)
|
|
||||||
// dispatch to port-specific constructor
|
|
||||||
extern mp_obj_t MICROPY_PY_MACHINE_I2C_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args);
|
|
||||||
return MICROPY_PY_MACHINE_I2C_MAKE_NEW(type, n_args, args, kw_args);
|
|
||||||
#else
|
|
||||||
mp_raise_ValueError(translate("invalid I2C peripheral"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
--n_args;
|
|
||||||
++args;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new soft I2C object
|
|
||||||
machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
|
|
||||||
self->base.type = &machine_i2c_type;
|
|
||||||
machine_i2c_obj_init_helper(self, n_args, args, kw_args);
|
|
||||||
return (mp_obj_t)self;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|
||||||
machine_i2c_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
|
|
||||||
mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
|
||||||
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
|
|
||||||
for (int addr = 0x08; addr < 0x78; ++addr) {
|
|
||||||
int ret = i2c_p->writeto(self, addr, NULL, 0, true);
|
|
||||||
if (ret == 0) {
|
|
||||||
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
if (i2c_p->start == NULL) {
|
|
||||||
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
|
|
||||||
}
|
|
||||||
int ret = i2c_p->start(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
if (i2c_p->stop == NULL) {
|
|
||||||
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
|
|
||||||
}
|
|
||||||
int ret = i2c_p->stop(self);
|
|
||||||
if (ret != 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
if (i2c_p->read == NULL) {
|
|
||||||
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the buffer to read into
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
|
||||||
|
|
||||||
// work out if we want to send a nack at the end
|
|
||||||
bool nack = (n_args == 2) ? true : mp_obj_is_true(args[2]);
|
|
||||||
|
|
||||||
// do the read
|
|
||||||
int ret = i2c_p->read(self, bufinfo.buf, bufinfo.len, nack);
|
|
||||||
if (ret != 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_readinto);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
if (i2c_p->write == NULL) {
|
|
||||||
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the buffer to write from
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
|
||||||
|
|
||||||
// do the write
|
|
||||||
int ret = i2c_p->write(self, bufinfo.buf, bufinfo.len);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return number of acks received
|
|
||||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
|
||||||
vstr_t vstr;
|
|
||||||
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
|
|
||||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
|
||||||
int ret = i2c_p->readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
|
|
||||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
|
||||||
int ret = i2c_p->readfrom(self, addr, bufinfo.buf, bufinfo.len, stop);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
|
||||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
|
||||||
int ret = i2c_p->writeto(self, addr, bufinfo.buf, bufinfo.len, stop);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
// return number of acks received
|
|
||||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
|
|
||||||
|
|
||||||
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
uint8_t memaddr_buf[4];
|
|
||||||
size_t memaddr_len = 0;
|
|
||||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
|
||||||
memaddr_buf[memaddr_len++] = memaddr >> i;
|
|
||||||
}
|
|
||||||
int ret = i2c_p->writeto(self, addr, memaddr_buf, memaddr_len, false);
|
|
||||||
if (ret != memaddr_len) {
|
|
||||||
// must generate STOP
|
|
||||||
i2c_p->writeto(self, addr, NULL, 0, true);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return i2c_p->readfrom(self, addr, buf, len, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_MEMADDR_SIZE (4)
|
|
||||||
#define BUF_STACK_SIZE (12)
|
|
||||||
|
|
||||||
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
|
|
||||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
|
|
||||||
|
|
||||||
// need some memory to create the buffer to send; try to use stack if possible
|
|
||||||
uint8_t buf2_stack[MAX_MEMADDR_SIZE + BUF_STACK_SIZE];
|
|
||||||
uint8_t *buf2;
|
|
||||||
size_t buf2_alloc = 0;
|
|
||||||
if (len <= BUF_STACK_SIZE) {
|
|
||||||
buf2 = buf2_stack;
|
|
||||||
} else {
|
|
||||||
buf2_alloc = MAX_MEMADDR_SIZE + len;
|
|
||||||
buf2 = m_new(uint8_t, buf2_alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the buffer to send
|
|
||||||
size_t memaddr_len = 0;
|
|
||||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
|
||||||
buf2[memaddr_len++] = memaddr >> i;
|
|
||||||
}
|
|
||||||
memcpy(buf2 + memaddr_len, buf, len);
|
|
||||||
|
|
||||||
int ret = i2c_p->writeto(self, addr, buf2, memaddr_len + len, true);
|
|
||||||
if (buf2_alloc != 0) {
|
|
||||||
m_del(uint8_t, buf2, buf2_alloc);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
|
|
||||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
|
||||||
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
|
||||||
{ MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
|
||||||
};
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
|
||||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
|
||||||
|
|
||||||
// create the buffer to store data into
|
|
||||||
vstr_t vstr;
|
|
||||||
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
|
|
||||||
|
|
||||||
// do the transfer
|
|
||||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
|
||||||
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
|
|
||||||
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
|
||||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
|
||||||
|
|
||||||
// get the buffer to store data into
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
|
|
||||||
|
|
||||||
// do the transfer
|
|
||||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
|
||||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
|
||||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
|
||||||
|
|
||||||
// get the buffer to write the data from
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
|
|
||||||
|
|
||||||
// do the transfer
|
|
||||||
int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
|
||||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
|
||||||
if (ret < 0) {
|
|
||||||
mp_raise_OSError(-ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
|
|
||||||
|
|
||||||
// primitive I2C operations
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) },
|
|
||||||
|
|
||||||
// standard bus operations
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
|
|
||||||
|
|
||||||
// memory operations
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
|
|
||||||
};
|
|
||||||
|
|
||||||
MP_DEFINE_CONST_DICT(mp_machine_soft_i2c_locals_dict, machine_i2c_locals_dict_table);
|
|
||||||
|
|
||||||
int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len, bool nack) {
|
|
||||||
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
|
|
||||||
while (len--) {
|
|
||||||
int ret = mp_hal_i2c_read_byte(self, dest++, nack && (len == 0));
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0; // success
|
|
||||||
}
|
|
||||||
|
|
||||||
int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) {
|
|
||||||
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
|
|
||||||
int num_acks = 0;
|
|
||||||
while (len--) {
|
|
||||||
int ret = mp_hal_i2c_write_byte(self, *src++);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
} else if (ret != 0) {
|
|
||||||
// nack received, stop sending
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++num_acks;
|
|
||||||
}
|
|
||||||
return num_acks;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
|
|
||||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_i2c)
|
|
||||||
.start = (int(*)(mp_obj_base_t*))mp_hal_i2c_start,
|
|
||||||
.stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop,
|
|
||||||
.read = mp_machine_soft_i2c_read,
|
|
||||||
.write = mp_machine_soft_i2c_write,
|
|
||||||
.readfrom = mp_machine_soft_i2c_readfrom,
|
|
||||||
.writeto = mp_machine_soft_i2c_writeto,
|
|
||||||
};
|
|
||||||
|
|
||||||
const mp_obj_type_t machine_i2c_type = {
|
|
||||||
{ &mp_type_type },
|
|
||||||
.name = MP_QSTR_I2C,
|
|
||||||
.make_new = machine_i2c_make_new,
|
|
||||||
.protocol = &mp_machine_soft_i2c_p,
|
|
||||||
.locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MICROPY_PY_MACHINE_I2C
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
|
||||||
|
|
||||||
#include "py/obj.h"
|
|
||||||
#include "py/proto.h"
|
|
||||||
|
|
||||||
// I2C protocol
|
|
||||||
// the first 4 methods can be NULL, meaning operation is not supported
|
|
||||||
typedef struct _mp_machine_i2c_p_t {
|
|
||||||
MP_PROTOCOL_HEAD
|
|
||||||
int (*start)(mp_obj_base_t *obj);
|
|
||||||
int (*stop)(mp_obj_base_t *obj);
|
|
||||||
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
|
|
||||||
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
|
|
||||||
int (*readfrom)(mp_obj_base_t *obj, uint16_t addr, uint8_t *dest, size_t len, bool stop);
|
|
||||||
int (*writeto)(mp_obj_base_t *obj, uint16_t addr, const uint8_t *src, size_t len, bool stop);
|
|
||||||
} mp_machine_i2c_p_t;
|
|
||||||
|
|
||||||
typedef struct _mp_machine_soft_i2c_obj_t {
|
|
||||||
mp_obj_base_t base;
|
|
||||||
uint32_t us_delay;
|
|
||||||
uint32_t us_timeout;
|
|
||||||
mp_hal_pin_obj_t scl;
|
|
||||||
mp_hal_pin_obj_t sda;
|
|
||||||
} mp_machine_soft_i2c_obj_t;
|
|
||||||
|
|
||||||
extern const mp_obj_type_t machine_i2c_type;
|
|
||||||
extern const mp_obj_dict_t mp_machine_soft_i2c_locals_dict;
|
|
||||||
|
|
||||||
int mp_machine_soft_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop);
|
|
||||||
int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop);
|
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "extmod/machine_mem.h"
|
#include "extmod/machine_mem.h"
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2015 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||||
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2016 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#if MICROPY_PY_MACHINE
|
#if MICROPY_PY_MACHINE
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// Copyright (c) 2016 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||||
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
||||||
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2017 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#if MICROPY_PY_MACHINE
|
#if MICROPY_PY_MACHINE
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// Copyright (c) 2017 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
||||||
|
|
||||||
|
@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "py/runtime.h"
|
|
||||||
#include "extmod/machine_spi.h"
|
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
|
||||||
|
|
||||||
#if MICROPY_PY_MACHINE_SPI
|
|
||||||
|
|
||||||
// if a port didn't define MSB/LSB constants then provide them
|
|
||||||
#ifndef MICROPY_PY_MACHINE_SPI_MSB
|
|
||||||
#define MICROPY_PY_MACHINE_SPI_MSB (0)
|
|
||||||
#define MICROPY_PY_MACHINE_SPI_LSB (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
// MicroPython bindings for generic machine.SPI
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
|
||||||
|
|
||||||
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|
||||||
// check the id argument, if given
|
|
||||||
if (n_args > 0) {
|
|
||||||
if (args[0] != MP_OBJ_NEW_SMALL_INT(-1)) {
|
|
||||||
#if defined(MICROPY_PY_MACHINE_SPI_MAKE_NEW)
|
|
||||||
// dispatch to port-specific constructor
|
|
||||||
extern mp_obj_t MICROPY_PY_MACHINE_SPI_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
|
||||||
return MICROPY_PY_MACHINE_SPI_MAKE_NEW(type, n_args, args, kw_args);
|
|
||||||
#else
|
|
||||||
mp_raise_ValueError(translate("invalid SPI peripheral"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
--n_args;
|
|
||||||
++args;
|
|
||||||
}
|
|
||||||
|
|
||||||
// software SPI
|
|
||||||
return mp_machine_soft_spi_make_new(type, n_args, args, kw_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|
||||||
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
|
||||||
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
|
|
||||||
spi_p->init(s, n_args - 1, args + 1, kw_args);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
|
|
||||||
|
|
||||||
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
|
|
||||||
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
|
|
||||||
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
|
|
||||||
if (spi_p->deinit != NULL) {
|
|
||||||
spi_p->deinit(s);
|
|
||||||
}
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit);
|
|
||||||
|
|
||||||
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) {
|
|
||||||
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
|
|
||||||
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
|
|
||||||
spi_p->transfer(s, len, src, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
|
|
||||||
vstr_t vstr;
|
|
||||||
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
|
|
||||||
memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
|
|
||||||
mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf);
|
|
||||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) {
|
|
||||||
mp_buffer_info_t bufinfo;
|
|
||||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
|
||||||
memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len);
|
|
||||||
mp_machine_spi_transfer(args[0], bufinfo.len, bufinfo.buf, bufinfo.buf);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto);
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) {
|
|
||||||
mp_buffer_info_t src;
|
|
||||||
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
|
|
||||||
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, NULL);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) {
|
|
||||||
mp_buffer_info_t src;
|
|
||||||
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
|
|
||||||
mp_buffer_info_t dest;
|
|
||||||
mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
|
|
||||||
if (src.len != dest.len) {
|
|
||||||
mp_raise_ValueError(translate("buffers must be the same length"));
|
|
||||||
}
|
|
||||||
mp_machine_spi_transfer(self, src.len, src.buf, dest.buf);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto);
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) },
|
|
||||||
};
|
|
||||||
|
|
||||||
MP_DEFINE_CONST_DICT(mp_machine_spi_locals_dict, machine_spi_locals_dict_table);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
// Implementation of soft SPI
|
|
||||||
|
|
||||||
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
|
|
||||||
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
|
|
||||||
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
|
|
||||||
return MICROPY_HW_SOFTSPI_MAX_BAUDRATE;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return 500000 / delay_half;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
|
|
||||||
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
|
|
||||||
if (baudrate >= MICROPY_HW_SOFTSPI_MAX_BAUDRATE) {
|
|
||||||
return MICROPY_HW_SOFTSPI_MIN_DELAY;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
uint32_t delay_half = 500000 / baudrate;
|
|
||||||
// round delay_half up so that: actual_baudrate <= requested_baudrate
|
|
||||||
if (500000 % baudrate != 0) {
|
|
||||||
delay_half += 1;
|
|
||||||
}
|
|
||||||
return delay_half;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
|
||||||
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
|
||||||
mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u,"
|
|
||||||
" sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")",
|
|
||||||
baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase,
|
|
||||||
mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso));
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) {
|
|
||||||
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
|
|
||||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
|
||||||
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
|
||||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
|
||||||
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} },
|
|
||||||
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
};
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args, all_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
||||||
|
|
||||||
// create new object
|
|
||||||
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
|
|
||||||
self->base.type = &mp_machine_soft_spi_type;
|
|
||||||
|
|
||||||
// set parameters
|
|
||||||
self->spi.delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);
|
|
||||||
self->spi.polarity = args[ARG_polarity].u_int;
|
|
||||||
self->spi.phase = args[ARG_phase].u_int;
|
|
||||||
if (args[ARG_bits].u_int != 8) {
|
|
||||||
mp_raise_ValueError(translate("bits must be 8"));
|
|
||||||
}
|
|
||||||
if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) {
|
|
||||||
mp_raise_ValueError(translate("firstbit must be MSB"));
|
|
||||||
}
|
|
||||||
if (args[ARG_sck].u_obj == MP_OBJ_NULL
|
|
||||||
|| args[ARG_mosi].u_obj == MP_OBJ_NULL
|
|
||||||
|| args[ARG_miso].u_obj == MP_OBJ_NULL) {
|
|
||||||
mp_raise_ValueError(translate("must specify all of sck/mosi/miso"));
|
|
||||||
}
|
|
||||||
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
|
|
||||||
self->spi.mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
|
|
||||||
self->spi.miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
|
|
||||||
|
|
||||||
// configure bus
|
|
||||||
mp_soft_spi_ioctl(&self->spi, MP_SPI_IOCTL_INIT);
|
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
||||||
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
|
|
||||||
|
|
||||||
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
|
|
||||||
static const mp_arg_t allowed_args[] = {
|
|
||||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
|
||||||
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
|
|
||||||
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
|
|
||||||
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
|
||||||
};
|
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
||||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
||||||
|
|
||||||
if (args[ARG_baudrate].u_int != -1) {
|
|
||||||
self->spi.delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);
|
|
||||||
}
|
|
||||||
if (args[ARG_polarity].u_int != -1) {
|
|
||||||
self->spi.polarity = args[ARG_polarity].u_int;
|
|
||||||
}
|
|
||||||
if (args[ARG_phase].u_int != -1) {
|
|
||||||
self->spi.phase = args[ARG_phase].u_int;
|
|
||||||
}
|
|
||||||
if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
|
|
||||||
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
|
|
||||||
}
|
|
||||||
if (args[ARG_mosi].u_obj != MP_OBJ_NULL) {
|
|
||||||
self->spi.mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
|
|
||||||
}
|
|
||||||
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
|
|
||||||
self->spi.miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure bus
|
|
||||||
mp_soft_spi_ioctl(&self->spi, MP_SPI_IOCTL_INIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
|
||||||
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
|
|
||||||
mp_soft_spi_transfer(&self->spi, len, src, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mp_machine_spi_p_t mp_machine_soft_spi_p = {
|
|
||||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_spi)
|
|
||||||
.init = mp_machine_soft_spi_init,
|
|
||||||
.deinit = NULL,
|
|
||||||
.transfer = mp_machine_soft_spi_transfer,
|
|
||||||
};
|
|
||||||
|
|
||||||
const mp_obj_type_t mp_machine_soft_spi_type = {
|
|
||||||
{ &mp_type_type },
|
|
||||||
.name = MP_QSTR_SoftSPI,
|
|
||||||
.print = mp_machine_soft_spi_print,
|
|
||||||
.make_new = mp_machine_spi_make_new, // delegate to master constructor
|
|
||||||
.protocol = &mp_machine_soft_spi_p,
|
|
||||||
.locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MICROPY_PY_MACHINE_SPI
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
|
||||||
|
|
||||||
#include "py/obj.h"
|
|
||||||
#include "py/proto.h"
|
|
||||||
#include "py/mphal.h"
|
|
||||||
#include "drivers/bus/spi.h"
|
|
||||||
|
|
||||||
// SPI protocol
|
|
||||||
typedef struct _mp_machine_spi_p_t {
|
|
||||||
MP_PROTOCOL_HEAD
|
|
||||||
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
|
||||||
void (*deinit)(mp_obj_base_t *obj); // can be NULL
|
|
||||||
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
|
||||||
} mp_machine_spi_p_t;
|
|
||||||
|
|
||||||
typedef struct _mp_machine_soft_spi_obj_t {
|
|
||||||
mp_obj_base_t base;
|
|
||||||
mp_soft_spi_obj_t spi;
|
|
||||||
} mp_machine_soft_spi_obj_t;
|
|
||||||
|
|
||||||
extern const mp_machine_spi_p_t mp_machine_soft_spi_p;
|
|
||||||
extern const mp_obj_type_t mp_machine_soft_spi_type;
|
|
||||||
extern const mp_obj_dict_t mp_machine_spi_locals_dict;
|
|
||||||
|
|
||||||
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
|
||||||
|
|
||||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
|
|
||||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
|
|
||||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
|
|
||||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
|
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
|
@ -1,29 +1,9 @@
|
|||||||
/*
|
// Copyright (c) 2016 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
// SPDX-FileCopyrightText: Copyright (c) 2014-2016 Damien P. George
|
||||||
* The MIT License (MIT)
|
//
|
||||||
*
|
// SPDX-License-Identifier: MIT
|
||||||
* Copyright (c) 2014-2016 Damien P. George
|
|
||||||
* Copyright (c) 2016 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MISC_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MISC_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MISC_H
|
#define MICROPY_INCLUDED_EXTMOD_MISC_H
|
||||||
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2016 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -1,30 +1,9 @@
|
|||||||
/*
|
// Copyright (c) 2015 Galen Hazelwood
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// Copyright (c) 2015-2017 Paul Sokolovsky
|
||||||
*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* The MIT License (MIT)
|
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||||
*
|
//
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
// SPDX-License-Identifier: MIT
|
||||||
* Copyright (c) 2015 Galen Hazelwood
|
|
||||||
* Copyright (c) 2015-2017 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2015-2017 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2014 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
/*
|
// Copyright (c) 2014 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
|
#ifndef MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
|
||||||
#define MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
|
#define MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
|
||||||
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2014 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -541,7 +520,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
|
|||||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||||
if (index >= arr_sz) {
|
if (index >= arr_sz) {
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, translate("struct: index out of range")));
|
mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->len == 2) {
|
if (t->len == 2) {
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// Copyright (c) 2014 Paul Sokolovsky
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Paul Sokolovsky
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "py/objlist.h"
|
#include "py/objlist.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
@ -1,31 +1,12 @@
|
|||||||
/*
|
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
// SPDX-FileCopyrightText: Copyright (c) 2014-2016 Damien P. George
|
||||||
*
|
//
|
||||||
* The MIT License (MIT)
|
// SPDX-License-Identifier: MIT
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2016 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "py/binary.h"
|
||||||
|
#include "py/objarray.h"
|
||||||
#include "py/objlist.h"
|
#include "py/objlist.h"
|
||||||
#include "py/objstringio.h"
|
#include "py/objstringio.h"
|
||||||
#include "py/parsenum.h"
|
#include "py/parsenum.h"
|
||||||
@ -53,6 +34,10 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
|
|||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
|
||||||
|
|
||||||
|
#define JSON_DEBUG(...) (void)0
|
||||||
|
// #define JSON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
// The function below implements a simple non-recursive JSON parser.
|
// The function below implements a simple non-recursive JSON parser.
|
||||||
//
|
//
|
||||||
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
|
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
|
||||||
@ -70,6 +55,8 @@ typedef struct _ujson_stream_t {
|
|||||||
mp_obj_t stream_obj;
|
mp_obj_t stream_obj;
|
||||||
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
|
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
|
||||||
int errcode;
|
int errcode;
|
||||||
|
mp_obj_t python_readinto[2 + 1];
|
||||||
|
mp_obj_array_t bytearray_obj;
|
||||||
byte cur;
|
byte cur;
|
||||||
} ujson_stream_t;
|
} ujson_stream_t;
|
||||||
|
|
||||||
@ -80,6 +67,7 @@ typedef struct _ujson_stream_t {
|
|||||||
|
|
||||||
STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
||||||
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
|
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
|
||||||
|
JSON_DEBUG(" usjon_stream_next err:%2d cur: %c \n", s->errcode, s->cur);
|
||||||
if (s->errcode != 0) {
|
if (s->errcode != 0) {
|
||||||
mp_raise_OSError(s->errcode);
|
mp_raise_OSError(s->errcode);
|
||||||
}
|
}
|
||||||
@ -89,9 +77,40 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
|||||||
return s->cur;
|
return s->cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
STATIC mp_uint_t ujson_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) {
|
||||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
|
ujson_stream_t* s = obj;
|
||||||
ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
|
s->bytearray_obj.items = buf;
|
||||||
|
s->bytearray_obj.len = size;
|
||||||
|
*errcode = 0;
|
||||||
|
mp_obj_t ret = mp_call_method_n_kw(1, 0, s->python_readinto);
|
||||||
|
if (ret == mp_const_none) {
|
||||||
|
*errcode = MP_EAGAIN;
|
||||||
|
return MP_STREAM_ERROR;
|
||||||
|
}
|
||||||
|
return mp_obj_get_int(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
|
||||||
|
const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, stream_obj);
|
||||||
|
ujson_stream_t s;
|
||||||
|
if (stream_p == NULL) {
|
||||||
|
mp_load_method(stream_obj, MP_QSTR_readinto, s.python_readinto);
|
||||||
|
s.bytearray_obj.base.type = &mp_type_bytearray;
|
||||||
|
s.bytearray_obj.typecode = BYTEARRAY_TYPECODE;
|
||||||
|
s.bytearray_obj.free = 0;
|
||||||
|
// len and items are set at read time
|
||||||
|
s.python_readinto[2] = MP_OBJ_FROM_PTR(&s.bytearray_obj);
|
||||||
|
s.stream_obj = &s;
|
||||||
|
s.read = ujson_python_readinto;
|
||||||
|
} else {
|
||||||
|
stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
|
||||||
|
s.stream_obj = stream_obj;
|
||||||
|
s.read = stream_p->read;
|
||||||
|
s.errcode = 0;
|
||||||
|
s.cur = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_DEBUG("got JSON stream\n");
|
||||||
vstr_t vstr;
|
vstr_t vstr;
|
||||||
vstr_init(&vstr, 8);
|
vstr_init(&vstr, 8);
|
||||||
mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
|
mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
|
||||||
@ -262,13 +281,18 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
success:
|
success:
|
||||||
// eat trailing whitespace
|
// It is legal for a stream to have contents after JSON.
|
||||||
while (unichar_isspace(S_CUR(s))) {
|
// E.g., A UART is not closed after receiving an object; in load() we will
|
||||||
S_NEXT(s);
|
// return the first complete JSON object, while in loads() we will retain
|
||||||
}
|
// strict adherence to the buffer's complete semantic.
|
||||||
if (!S_END(s)) {
|
if (!return_first_json) {
|
||||||
// unexpected chars
|
while (unichar_isspace(S_CUR(s))) {
|
||||||
goto fail;
|
S_NEXT(s);
|
||||||
|
}
|
||||||
|
if (!S_END(s)) {
|
||||||
|
// unexpected chars
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
|
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
|
||||||
// not exactly 1 object
|
// not exactly 1 object
|
||||||
@ -280,6 +304,10 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
|||||||
fail:
|
fail:
|
||||||
mp_raise_ValueError(translate("syntax error in JSON"));
|
mp_raise_ValueError(translate("syntax error in JSON"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
||||||
|
return _mod_ujson_load(stream_obj, true);
|
||||||
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
|
||||||
|
|
||||||
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
||||||
@ -287,7 +315,7 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
|||||||
const char *buf = mp_obj_str_get_data(obj, &len);
|
const char *buf = mp_obj_str_get_data(obj, &len);
|
||||||
vstr_t vstr = {len, len, (char*)buf, true};
|
vstr_t vstr = {len, len, (char*)buf, true};
|
||||||
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
|
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
|
||||||
return mod_ujson_load(MP_OBJ_FROM_PTR(&sio));
|
return _mod_ujson_load(MP_OBJ_FROM_PTR(&sio), false);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user