mirror of
https://github.com/google/bumble.git
synced 2026-04-16 00:25:31 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1af61e8af3 | ||
|
|
e11119c565 | ||
|
|
b1a31564ef | ||
|
|
01492d510c | ||
|
|
302c495178 | ||
|
|
fc7923f83b | ||
|
|
a9bd77e6ee | ||
|
|
ce0cf5fd27 | ||
|
|
86ded3fece | ||
|
|
d6b426eeec | ||
|
|
884315ae00 | ||
|
|
7e8b201999 | ||
|
|
e99d291cb7 | ||
|
|
27c0551279 | ||
|
|
db2c833276 | ||
|
|
3dc2b9b2a8 | ||
|
|
210a509385 | ||
|
|
7b7c0ffa42 | ||
|
|
ba0e123d96 |
72
.github/workflows/codeql-analysis.yml
vendored
Normal file
72
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '39 21 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
34
.github/workflows/python-build-test.yml
vendored
Normal file
34
.github/workflows/python-build-test.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# Build and test the python package
|
||||
name: Python build and test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install ".[test,development,documentation]"
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest
|
||||
- name: Build
|
||||
run: |
|
||||
inv build
|
||||
inv mkdocs
|
||||
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
.eggs/
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
*~
|
||||
bumble/__pycache__
|
||||
docs/mkdocs/site
|
||||
tests/__pycache__
|
||||
test-results.xml
|
||||
bumble/transport/__pycache__
|
||||
@@ -11,9 +11,12 @@ Bluetooth Stack for Apps, Emulation, Test and Experimentation
|
||||
|
||||
<img src="docs/mkdocs/src/images/logo_framed.png" alt="drawing" width="200" height="200"/>
|
||||
|
||||
Bumble is a full-featured Bluetooth stack written entirely in Python. It supports most of the common Bluetooth Low Energy (BLE) and Bluetooth Classic (BR/EDR) protocols and profiles, including GAP, L2CAP, ATT, GATT, SMP, SDP, RFCOMM, HFP, HID and A2DP. The stack can be used with physical radios via HCI over USB, UART, or the Linux VHCI, as well as virtual radios, including the virtual Bluetooth support of the Android emulator.
|
||||
|
||||
## Documentation
|
||||
|
||||
See the documentation under `docs/mkdocs/src`, or build the static HTML site from the markdown text with:
|
||||
Browse the pre-built [Online Documentation](https://google.github.io/bumble/),
|
||||
or see the documentation source under `docs/mkdocs/src`, or build the static HTML site from the markdown text with:
|
||||
```
|
||||
mkdocs build -f docs/mkdocs/mkdocs.yml
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ import click
|
||||
from colors import color
|
||||
|
||||
from bumble import hci
|
||||
from bumble.transport import PacketReader
|
||||
from bumble.transport.common import PacketReader
|
||||
from bumble.helpers import PacketTracer
|
||||
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ class L2CAP_Control_Frame:
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@L2CAP_Control_Frame.subclass([
|
||||
('reason', {'size': 2, 'mapper': lambda x: L2CAP_Command_Reject.map_reason(x)}),
|
||||
('reason', {'size': 2, 'mapper': lambda x: L2CAP_Command_Reject.reason_name(x)}),
|
||||
('data', '*')
|
||||
])
|
||||
class L2CAP_Command_Reject(L2CAP_Control_Frame):
|
||||
@@ -262,7 +262,7 @@ class L2CAP_Command_Reject(L2CAP_Control_Frame):
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def map_reason(reason):
|
||||
def reason_name(reason):
|
||||
return name_or_number(L2CAP_Command_Reject.REASON_NAMES, reason)
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ class L2CAP_Configure_Request(L2CAP_Control_Frame):
|
||||
@L2CAP_Control_Frame.subclass([
|
||||
('source_cid', 2),
|
||||
('flags', 2),
|
||||
('result', {'size': 2, 'mapper': lambda x: L2CAP_Configure_Response.map_result(x)}),
|
||||
('result', {'size': 2, 'mapper': lambda x: L2CAP_Configure_Response.result_name(x)}),
|
||||
('options', '*')
|
||||
])
|
||||
class L2CAP_Configure_Response(L2CAP_Control_Frame):
|
||||
@@ -355,7 +355,7 @@ class L2CAP_Configure_Response(L2CAP_Control_Frame):
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def map_result(result):
|
||||
def result_name(result):
|
||||
return name_or_number(L2CAP_Configure_Response.RESULT_NAMES, result)
|
||||
|
||||
|
||||
@@ -403,31 +403,49 @@ class L2CAP_Echo_Response(L2CAP_Control_Frame):
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@L2CAP_Control_Frame.subclass([
|
||||
('info_type', 2)
|
||||
('info_type', {'size': 2, 'mapper': lambda x: L2CAP_Information_Request.info_type_name(x)})
|
||||
])
|
||||
class L2CAP_Information_Request(L2CAP_Control_Frame):
|
||||
'''
|
||||
See Bluetooth spec @ Vol 3, Part A - 4.10 INFORMATION REQUEST
|
||||
'''
|
||||
|
||||
SUCCESS = 0x00
|
||||
NOT_SUPPORTED = 0x01
|
||||
|
||||
CONNECTIONLESS_MTU = 0x0001
|
||||
EXTENDED_FEATURES_SUPPORTED = 0x0002
|
||||
FIXED_CHANNELS_SUPPORTED = 0x0003
|
||||
|
||||
INFO_TYPE_NAMES = {
|
||||
CONNECTIONLESS_MTU: 'CONNECTIONLESS_MTU',
|
||||
EXTENDED_FEATURES_SUPPORTED: 'EXTENDED_FEATURES_SUPPORTED',
|
||||
FIXED_CHANNELS_SUPPORTED: 'FIXED_CHANNELS_SUPPORTED'
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def info_type_name(info_type):
|
||||
return name_or_number(L2CAP_Information_Request.INFO_TYPE_NAMES, info_type)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@L2CAP_Control_Frame.subclass([
|
||||
('info_type', 2),
|
||||
('result', 2),
|
||||
('info_type', {'size': 2, 'mapper': L2CAP_Information_Request.info_type_name}),
|
||||
('result', {'size': 2, 'mapper': lambda x: L2CAP_Information_Response.result_name(x)}),
|
||||
('data', '*')
|
||||
])
|
||||
class L2CAP_Information_Response(L2CAP_Control_Frame):
|
||||
'''
|
||||
See Bluetooth spec @ Vol 3, Part A - 4.11 INFORMATION RESPONSE
|
||||
'''
|
||||
SUCCESS = 0x00
|
||||
NOT_SUPPORTED = 0x01
|
||||
|
||||
RESULT_NAMES = {
|
||||
SUCCESS: 'SUCCESS',
|
||||
NOT_SUPPORTED: 'NOT_SUPPORTED'
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def result_name(result):
|
||||
return name_or_number(L2CAP_Information_Response.RESULT_NAMES, result)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -473,7 +491,7 @@ class L2CAP_LE_Credit_Based_Connection_Request(L2CAP_Control_Frame):
|
||||
('mtu', 2),
|
||||
('mps', 2),
|
||||
('initial_credits', 2),
|
||||
('result', {'size': 2, 'mapper': lambda x: L2CAP_LE_Credit_Based_Connection_Response.map_result(x)})
|
||||
('result', {'size': 2, 'mapper': lambda x: L2CAP_LE_Credit_Based_Connection_Response.result_name(x)})
|
||||
])
|
||||
class L2CAP_LE_Credit_Based_Connection_Response(L2CAP_Control_Frame):
|
||||
'''
|
||||
@@ -505,7 +523,7 @@ class L2CAP_LE_Credit_Based_Connection_Response(L2CAP_Control_Frame):
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def map_result(result):
|
||||
def result_name(result):
|
||||
return name_or_number(L2CAP_LE_Credit_Based_Connection_Response.CONNECTION_RESULT_NAMES, result)
|
||||
|
||||
|
||||
@@ -980,13 +998,13 @@ class ChannelManager:
|
||||
|
||||
def on_l2cap_information_request(self, connection, cid, request):
|
||||
if request.info_type == L2CAP_Information_Request.CONNECTIONLESS_MTU:
|
||||
result = L2CAP_Information_Request.SUCCESS
|
||||
result = L2CAP_Information_Response.SUCCESS
|
||||
data = struct.pack('<H', 1024) # TODO: don't use a fixed value
|
||||
elif request.info_type == L2CAP_Information_Request.EXTENDED_FEATURES_SUPPORTED:
|
||||
result = L2CAP_Information_Request.SUCCESS
|
||||
result = L2CAP_Information_Response.SUCCESS
|
||||
data = bytes.fromhex('00000000') # TODO: don't use a fixed value
|
||||
elif request.info_type == L2CAP_Information_Request.FIXED_CHANNELS_SUPPORTED:
|
||||
result = L2CAP_Information_Request.SUCCESS
|
||||
result = L2CAP_Information_Response.SUCCESS
|
||||
data = bytes.fromhex('FFFFFFFFFFFFFFFF') # TODO: don't use a fixed value
|
||||
else:
|
||||
result = L2CAP_Information_Request.NO_SUPPORTED
|
||||
|
||||
@@ -37,14 +37,17 @@ async def open_usb_transport(spec):
|
||||
'''
|
||||
Open a USB transport.
|
||||
The parameter string has this syntax:
|
||||
either <index> or <vendor>:<product>
|
||||
either <index> or <vendor>:<product>[/<serial-number>]
|
||||
With <index> as the 0-based index to select amongst all the devices that appear
|
||||
to be supporting Bluetooth HCI (0 being the first one), or
|
||||
Where <vendor> and <product> are the vendor ID and product ID in hexadecimal.
|
||||
Where <vendor> and <product> are the vendor ID and product ID in hexadecimal. The
|
||||
/<serial-number> suffix max be specified when more than one device with the same
|
||||
vendor and product identifiers are present.
|
||||
|
||||
Examples:
|
||||
0 --> the first BT USB dongle
|
||||
04b4:f901 --> the BT USB dongle with vendor=04b4 and product=f901
|
||||
04b4:f901/00E04C239987 --> the BT USB dongle with vendor=04b4 and product=f901 and serial number 00E04C239987
|
||||
'''
|
||||
|
||||
USB_RECIPIENT_DEVICE = 0x00
|
||||
@@ -268,22 +271,32 @@ async def open_usb_transport(spec):
|
||||
found = None
|
||||
if ':' in spec:
|
||||
vendor_id, product_id = spec.split(':')
|
||||
found = context.getByVendorIDAndProductID(int(vendor_id, 16), int(product_id, 16), skip_on_error=True)
|
||||
if '/' in product_id:
|
||||
product_id, serial_number = product_id.split('/')
|
||||
for device in context.getDeviceIterator(skip_on_error=True):
|
||||
if (
|
||||
device.getVendorID() == int(vendor_id, 16) and
|
||||
device.getProductID() == int(product_id, 16) and
|
||||
device.getSerialNumber() == serial_number
|
||||
):
|
||||
found = device
|
||||
break
|
||||
device.close()
|
||||
else:
|
||||
found = context.getByVendorIDAndProductID(int(vendor_id, 16), int(product_id, 16), skip_on_error=True)
|
||||
else:
|
||||
device_index = int(spec)
|
||||
device_iterator = context.getDeviceIterator(skip_on_error=True)
|
||||
try:
|
||||
for device in device_iterator:
|
||||
if device.getDeviceClass() == USB_DEVICE_CLASS_WIRELESS_CONTROLLER and \
|
||||
device.getDeviceSubClass() == USB_DEVICE_SUBCLASS_RF_CONTROLLER and \
|
||||
device.getDeviceProtocol() == USB_DEVICE_PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER:
|
||||
if device_index == 0:
|
||||
found = device
|
||||
break
|
||||
device_index -= 1
|
||||
device.close()
|
||||
finally:
|
||||
device_iterator.close()
|
||||
for device in context.getDeviceIterator(skip_on_error=True):
|
||||
if (
|
||||
device.getDeviceClass() == USB_DEVICE_CLASS_WIRELESS_CONTROLLER and
|
||||
device.getDeviceSubClass() == USB_DEVICE_SUBCLASS_RF_CONTROLLER and
|
||||
device.getDeviceProtocol() == USB_DEVICE_PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER
|
||||
):
|
||||
if device_index == 0:
|
||||
found = device
|
||||
break
|
||||
device_index -= 1
|
||||
device.close()
|
||||
|
||||
if found is None:
|
||||
context.close()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
site_name: Bumble
|
||||
|
||||
use_directory_urls: true
|
||||
use_directory_urls: false
|
||||
|
||||
nav:
|
||||
- Introduction: index.md
|
||||
- Getting Started: getting_started.md
|
||||
- Development:
|
||||
- Python Environments: development/python_environments.md
|
||||
- Use Cases:
|
||||
- Overview: use_cases/index.md
|
||||
- Use Case 1: use_cases/use_case_1.md
|
||||
@@ -63,15 +65,18 @@ theme:
|
||||
custom_dir: 'theme'
|
||||
|
||||
plugins:
|
||||
- mkdocstrings
|
||||
- mkdocstrings:
|
||||
handlers:
|
||||
python:
|
||||
paths: [../..]
|
||||
|
||||
docs_dir: 'src'
|
||||
|
||||
edit_uri: ''
|
||||
|
||||
# Repo info
|
||||
#repo_name: TBD
|
||||
#repo_url: https://github.com/TBD
|
||||
repo_name: 'GitHub'
|
||||
repo_url: https://github.com/google/bumble
|
||||
|
||||
# Extensions
|
||||
markdown_extensions:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# This requirements file is for python3
|
||||
mkdocs == 1.2
|
||||
mkdocs == 1.2.3
|
||||
mkdocs-material == 7.1.7
|
||||
mkdocs-material-extensions == 1.0.1
|
||||
pymdown-extensions == 8.2
|
||||
|
||||
@@ -7,6 +7,6 @@ These include:
|
||||
* [Console](console.md) - an interactive text-based console
|
||||
* [HCI Bridge](hci_bridge.md) - a HCI transport bridge to connect two HCI transports and filter/snoop the HCI packets
|
||||
* [Golden Gate Bridge](gg_bridge.md) - a bridge between GATT and UDP to use with the Golden Gate "stack tool"
|
||||
* [`Show`](show.md) - Parse a file with HCI packets and print the details of each packet in a human readable form
|
||||
* [`Link Relay`](link_relay.md) - WebSocket relay for virtual RemoteLink instances to communicate with each other.
|
||||
* [Show](show.md) - Parse a file with HCI packets and print the details of each packet in a human readable form
|
||||
* [Link Relay](link_relay.md) - WebSocket relay for virtual RemoteLink instances to communicate with each other.
|
||||
|
||||
|
||||
45
docs/mkdocs/src/development/python_environments.md
Normal file
45
docs/mkdocs/src/development/python_environments.md
Normal file
@@ -0,0 +1,45 @@
|
||||
PYTHON ENVIRONMENTS
|
||||
===================
|
||||
|
||||
When you don't want to install Bumble in your main/default python environment,
|
||||
using a virtual environment, where the package and its dependencies can be
|
||||
installed, isolated from the rest, may be useful.
|
||||
|
||||
There are many flavors of python environments and dependency managers.
|
||||
This page describes a few of the most common ones.
|
||||
|
||||
|
||||
## venv
|
||||
|
||||
`venv` is a standard module that is included with python.
|
||||
Visit the [`venv` documentation](https://docs.python.org/3/library/venv.html) page for details.
|
||||
|
||||
## Pyenv
|
||||
|
||||
`pyenv` lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.
|
||||
Visit the [`pyenv` site](https://github.com/pyenv/pyenv) for instructions on how to install
|
||||
and use `pyenv`
|
||||
|
||||
## Conda
|
||||
|
||||
Conda is a convenient package manager and virtual environment.
|
||||
The file `environment.yml` is a Conda environment file that you can use to create
|
||||
a new Conda environment. Once created, you can simply activate this environment when
|
||||
working with Bumble.
|
||||
Visit the [Conda site](https://docs.conda.io/en/latest/) for instructions on how to install
|
||||
and use Conda.
|
||||
A few useful commands:
|
||||
|
||||
### Create a new `bumble` Conda environment
|
||||
```
|
||||
$ conda env create -f environment.yml
|
||||
```
|
||||
This will create a new environment, named `bumble`, which you can then activate with:
|
||||
```
|
||||
$ conda activate bumble
|
||||
```
|
||||
|
||||
### Update an existing `bumble` environment
|
||||
```
|
||||
$ conda env update -f environment.yml
|
||||
```
|
||||
@@ -20,7 +20,7 @@ You may be simply using Bumble as a module for your own application or as a depe
|
||||
module, or you may be working on modifying or contributing to the Bumble module or example code
|
||||
itself.
|
||||
|
||||
# Working With Bumble As A Module
|
||||
# Using Bumble As A Python Module
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -29,52 +29,40 @@ manager, or from source.
|
||||
|
||||
!!! tip "Python Virtual Environments"
|
||||
When you install Bumble, you have the option to install it as part of your default
|
||||
python environment, or in a virtual environment, such as a `venv`, `pyenv` or `conda` environment
|
||||
|
||||
### venv
|
||||
|
||||
`venv` is a standard module that is included with python.
|
||||
Visit the [`venv` documentation](https://docs.python.org/3/library/venv.html) page for details.
|
||||
|
||||
### Pyenv
|
||||
|
||||
`pyenv` lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.
|
||||
Visit the [`pyenv` site](https://github.com/pyenv/pyenv) for instructions on how to install
|
||||
and use `pyenv`
|
||||
|
||||
### Conda
|
||||
|
||||
Conda is a convenient package manager and virtual environment.
|
||||
The file `environment.yml` is a Conda environment file that you can use to create
|
||||
a new Conda environment. Once created, you can simply activate this environment when
|
||||
working with Bumble.
|
||||
Visit the [Conda side](https://docs.conda.io/en/latest/) for instructions on how to install
|
||||
and use Conda.
|
||||
A few useful commands:
|
||||
|
||||
#### Create a new `bumble` Conda environment
|
||||
```
|
||||
$ conda env create -f environment.yml
|
||||
```
|
||||
This will create a new environment, named `bumble`, which you can then activate with:
|
||||
```
|
||||
$ conda activate bumble
|
||||
```
|
||||
|
||||
#### Update an existing `bumble` environment
|
||||
```
|
||||
$ conda env update -f environment.yml
|
||||
```
|
||||
python environment, or in a virtual environment, such as a `venv`, `pyenv` or `conda` environment.
|
||||
See the [Python Environments page](development/python_environments.md) page for details.
|
||||
|
||||
### Install From Source
|
||||
|
||||
The instructions for working with virtual Python environments above also apply in this case.
|
||||
|
||||
Install with `pip`
|
||||
Install with `pip`. Run in a command shell in the directory where you downloaded the source
|
||||
distribution
|
||||
```
|
||||
$ python -m pip install -e .
|
||||
```
|
||||
|
||||
### Install from GitHub
|
||||
|
||||
You can install directly from GitHub without first downloading the repo.
|
||||
|
||||
Install the latest commit from the main branch with `pip`:
|
||||
```
|
||||
$ python -m pip install git+https://github.com/google/bumble.git
|
||||
```
|
||||
|
||||
You can specify a specific tag.
|
||||
|
||||
Install tag `v0.0.1` with `pip`:
|
||||
```
|
||||
$ python -m pip install git+https://github.com/google/bumble.git@v0.0.1
|
||||
```
|
||||
|
||||
You can also specify a specific commit.
|
||||
|
||||
Install commit `27c0551` with `pip`:
|
||||
```
|
||||
$ python -m pip install git+https://github.com/google/bumble.git@27c0551
|
||||
```
|
||||
|
||||
# Working On The Bumble Code
|
||||
When you work on the Bumble code itself, and run some of the tests or example apps, or import the
|
||||
module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase.
|
||||
@@ -106,3 +94,13 @@ Setting `PYTHONPATH` locally with each command would look something like:
|
||||
```
|
||||
$ PYTHONPATH=. python examples/run_advertiser.py examples/device1.json serial:/dev/tty.usbmodem0006839912171
|
||||
```
|
||||
|
||||
# Where To Go Next
|
||||
Once you've installed or downloaded Bumble, you can either start using some of the
|
||||
[Bundled apps and tools](apps_and_tools/index.md), or look at the [examples](examples/index.md)
|
||||
to get a feel for how to use the APIs, and start writing your own applications.
|
||||
|
||||
Depending on the use case you're interested in exploring, you may need to use a physical Bluetooth
|
||||
controller, like a USB dongle or a board with a Bluetooth radio. Visit the [Hardware page](hardware/index.md)
|
||||
for more information on using a physical radio, and/or the [Transports page](transports/index.md) for more
|
||||
details on interfacing with either hardware modules or virtual controllers over various transports.
|
||||
|
||||
@@ -46,7 +46,7 @@ through it with Android applications as well as system-managed profiles.
|
||||
To connect a Bumble host stack to a Root Canal virtual controller instance, use
|
||||
the bumble `android-emulator` transport in `host` mode (the default).
|
||||
|
||||
!!! example "Running the example GATT server connected to the emulator"
|
||||
!!! example "Run the example GATT server connected to the emulator"
|
||||
``` shell
|
||||
$ python run_gatt_server.py device1.json android-emulator
|
||||
```
|
||||
@@ -57,7 +57,7 @@ This is an advanced use case, which may not be officially supported, but should
|
||||
versions of the emulator.
|
||||
You will likely need to start the emulator from the command line, in order to specify the `-forward-vhci` option (unless the emulator offers a way to control that feature from a user/ui menu).
|
||||
|
||||
!!! example "Launching the emulator with VHCI forwarding"
|
||||
!!! example "Launch the emulator with VHCI forwarding"
|
||||
In this example, we launch an emulator AVD named "Tiramisu"
|
||||
```shell
|
||||
$ emulator -forward-vhci -avd Tiramisu
|
||||
@@ -70,10 +70,20 @@ You will likely need to start the emulator from the command line, in order to sp
|
||||
|
||||
To connect a virtual controller to the Android Bluetooth stack, use the bumble `android-emulator` transport in `controller` mode. For example, using the default gRPC port, the transport name would be: `android-emulator:mode=controller`.
|
||||
|
||||
!!! example "connecting the Android emulator to the first USB Bluetooth dongle, using the `hci_bridge` application"
|
||||
!!! example "Connect the Android emulator to the first USB Bluetooth dongle, using the `hci_bridge` application"
|
||||
```shell
|
||||
$ bumble-hci-bridge android-emulator:mode=controller usb:0
|
||||
```
|
||||
|
||||
## Other Tools
|
||||
|
||||
The `show` application that's included with Bumble can be used to parse and pretty-print the HCI packets
|
||||
from an Android HCI "snoop log" (see [this page](https://source.android.com/devices/bluetooth/verifying_debugging)
|
||||
for details on how to obtain HCI snoop logs from an Android device).
|
||||
Use the `--format snoop` option to specify that the file is in that specific format.
|
||||
|
||||
!!! example "Analyze an Android HCI snoop log file"
|
||||
```shell
|
||||
$ bumble-show --format snoop btsnoop_hci.log
|
||||
```
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ packages = bumble, bumble.transport, bumble.apps, bumble.apps.link_relay
|
||||
package_dir =
|
||||
bumble = bumble
|
||||
bumble.apps = apps
|
||||
bumble.apps.link_relay = apps/link_relay
|
||||
install_requires =
|
||||
aioconsole >= 0.4.1
|
||||
ansicolors >= 1.1
|
||||
@@ -37,6 +36,7 @@ install_requires =
|
||||
grpcio >= 1.46; platform_system!='Emscripten'
|
||||
libusb1 >= 2.0.1; platform_system!='Emscripten'
|
||||
prompt_toolkit >= 3.0.16; platform_system!='Emscripten'
|
||||
protobuf >= 3.12.4
|
||||
pyee >= 8.2.2
|
||||
pyserial-asyncio >= 0.5; platform_system!='Emscripten'
|
||||
pyserial >= 3.5; platform_system!='Emscripten'
|
||||
@@ -65,4 +65,4 @@ development =
|
||||
documentation =
|
||||
mkdocs >= 1.2.3
|
||||
mkdocs-material >= 8.1.9
|
||||
mkdocstrings >= 0.17.0
|
||||
mkdocstrings[python] >= 0.19.0
|
||||
|
||||
Reference in New Issue
Block a user