Skip to content

Commit f8c1ec1

Browse files
Add BluetoothHIDMaster documentation (earlephilhower#2216)
Also link in FatFSUSB docs, d'oh!
1 parent 1fd66bf commit f8c1ec1

File tree

4 files changed

+218
-6
lines changed

4 files changed

+218
-6
lines changed

docs/bluetooth.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ Bluetooth on PicoW Support
22
==========================
33

44
As of the Pico-SDK version 1.5.0, the PicoW has **BETA** Bluetooth support.
5-
So, since this core builds off the SDK the best that can be suggested it
6-
that we have **ALPHA** Bluetooth support. As such, bug reports are welcome,
7-
but Pull Requests fixing problems you find are seriously appreciated.
85

96
Enabling Bluetooth
107
------------------
@@ -24,6 +21,11 @@ Bluetooth Low Energy (BLE) HID device using the same API as their USB versions.
2421
The ``SerialBT`` library implements a very simple SPP (Serial Port Profile)
2522
Serial-compatible port.
2623

24+
Connect and use Bluetooth peripherals with the PicoW using the
25+
``BluetoothHIDMaster`` library.
26+
27+
``BluetoothAudio`` (A2DP) is also supported, both sink and source.
28+
2729
Writing Custom Bluetooth Applications
2830
-------------------------------------
2931
You may also write full applications using the ``BTStack`` standard callback

docs/fs.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ Close the file. No other operations should be performed on *File* object
598598
after ``close`` function was called.
599599

600600
openNextFile (compatibility method, not recommended for new code)
601-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
601+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
602602

603603
.. code:: cpp
604604
@@ -610,7 +610,7 @@ Opens the next file in the directory pointed to by the File. Only valid
610610
when ``File.isDirectory() == true``.
611611

612612
rewindDirectory (compatibility method, not recommended for new code)
613-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
613+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614614

615615
.. code:: cpp
616616

docs/hidmaster.rst

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
Bluetooth HID Master
2+
====================
3+
4+
The PicoW can connect to a Bluetooth Classic or Bluetooth BLE keyboard,
5+
mouse, or joystick and receive input events from it. As opposed to
6+
the ``Keyboard``, ``Mouse``, and ``Joystick`` libraries, which make
7+
the PicoW into a peripheral others can use, this lets the PicoW use the
8+
same kinds of peripherals in a master rols.
9+
10+
BTDeviceInfo Class
11+
------------------
12+
13+
The ``BluetoothHCI`` class implements a scanning function for classic
14+
and BLE devices and can return a ``std::list`` of discovered devices to an application.
15+
Iterate over the list using any of the STL iteration methods (i.e. ``for (auto e : list)``).
16+
The elements of this list are ``BTDeviceInfo`` objects which have the following
17+
member functions:
18+
19+
``BTDeviceInfo::deviceClass()`` returns the Bluetooth BLE UUID or the Blustooth device
20+
class for the device. This specifies the general class of the device (keyboard, mouse,
21+
etc.).
22+
23+
``BTDeviceInfo::address()`` and ``BTDeviceInfo::addressString()`` return the
24+
Bluetooth address as a binary array or a string that can be used to ``print``.
25+
26+
``BTDeviceInfo::addressType()`` returns whether the BLE address is random or not, and
27+
is not generally needed by a user application.
28+
29+
``BTDeviceInfo::rssi()`` returns an approximate dB level for the device. Less
30+
negative is stronger signal.
31+
32+
``BTDeviceInfo::name()`` returns the advertised name of the device, if present. Some
33+
devices or scans do not return names for valid devices.
34+
35+
36+
BluetoothHCI Class
37+
------------------
38+
39+
The ``BluetoothHCI`` class is responsible for scanning for devices and the lower-level
40+
housekeeping for a master-mode Bluetooth application. Most applications will not need
41+
to access it directly, but it can be used to discover nearby BT devices. As
42+
part of the application Bluetooth setup, call ``BluetoothHCI::install()`` and then
43+
``BluetoothHCI::begin()`` to start BT processing. Your application is still responsible
44+
for all the non-default HCI initialization and customization. See the ``BluetoothScanner.ino``
45+
example for more info.
46+
47+
48+
BluetoothHIDMaster Operation
49+
----------------------------
50+
51+
Most applications will use the ``BluetoothHIDMaster`` class and, after connecting, receive
52+
callbacks from the Bluetooth stack when input events (key presses, mouse moves, button
53+
mashes) occur.
54+
55+
Application flow will generally be:
56+
1. Install the appropriate callbacks using the ``BluetoothHIDMaster::onXXX`` methods
57+
2. Start the Bluetooth processing with ``BluetoothHIDMaster::begin()`` or ``BluetoothHIDMaster::beginBLE()``
58+
3. Connect to the first device found with ``BluetoothHIDMaster::connectXXX()`` and start receiving callbacks.
59+
4. Callbacks will come at interrupt time and set global state variables, which the main ``loop()`` will process
60+
61+
Callback Event Handlers
62+
-----------------------
63+
The main application is informed of new inputs via a standard callback mechanism. These callbacks run at
64+
interrupt time and should not do significant work, ``delay()``, or allocate or free memory. The most common
65+
way of handling this is setting global ``volatile`` flags and variables that the main ``loop()`` will poll
66+
and process.
67+
68+
Mouse Callbacks
69+
~~~~~~~~~~~~~~~
70+
The ``BluetoothHIDMaster::onMouseMove`` callback gets the delta X, Y, and wheel reported by the device.
71+
The ``BluetoothHIDMaster::onMouseButton`` gets a button number and state (up or down) and will be called
72+
each time an individual button is reported changed by the mouse.
73+
74+
.. code :: cpp
75+
76+
void mouseMoveCB(void *cbdata, int dx, int dy, int dw) {
77+
// Process the deltas, adjust global mouse state
78+
}
79+
80+
void mouseButtonCB(void *cbdata, int butt, bool down) {
81+
// Set the global button array with this new info
82+
}
83+
84+
85+
Meyboard Callbacks
86+
~~~~~~~~~~~~~~~~~~
87+
The `BluetoothHIDMaster::onKeyDown`` callback receives the raw HID key (**NOT ASCII**) sent by the device on a key press
88+
while `BluetoothHIDMaster::onKeyUp`` gets the same when a key is released. Note that up to 6 keys can be pressed at any
89+
one time. For media keys ("consumer keys" in the USB HID documentation) the ``BluetoothHIDMaster::onConsumerKeyDown`` and
90+
``BluetoothHIDMaster::onConsumerKeyUp`` perform the same function (and receive the consumer key IDs defined by the
91+
USB HID spec and not ASCII).
92+
93+
To convert the key press and release (including SHIFT handling), use a ``HIDKeyStream`` object. Simply write the raw
94+
HID key and the up/down state to the stream and read back the ASCII for use in an application.
95+
96+
.. code :: cpp
97+
98+
HIDKeyStream keystream;
99+
100+
void keyDownCB(void *cbdata, int key) {
101+
keystream.write((uint8_t )key);
102+
keystream.write((uint8_t) true); // Keystream now has 1 ASCII character to read out and use
103+
char ascii = keystream.read();
104+
// ....
105+
}
106+
107+
void keyUpCB(void *cbdata, int key) {
108+
// Normally don't do anything on this, the character was read in the keyDownCB
109+
}
110+
111+
void consumerKeyDownCB(void *cbdata, int key) {
112+
// switch(key) and use cases from the USB Consumer Key page
113+
}
114+
115+
void consumerKeyUpCB(void *cbdata, int key) {
116+
// switch(key) and use cases from the USB Consumer Key page
117+
}
118+
119+
120+
Joystick Callbacks
121+
~~~~~~~~~~~~~~~~~~
122+
A single ``BluetoothHIDMaster::onJoypad`` callback gets activated every time a report from a joystick is processed.
123+
It receives (potentially, if supported by the device) 4 analog axes, one 8-way digital hat switch position, and up
124+
to 32 button states at a time.
125+
126+
.. code :: cpp
127+
128+
void joypadCB(void *cbdata, int x, int y, int z, int rz, uint8_t hat, uint32_t buttons) {
129+
// HAT 0 = UP and continues clockwise. If no hat direction it is set to 0x0f.
130+
// Use "buttons & (1 << buttonNumber)" to look at the individual button states
131+
// ...
132+
}
133+
134+
PianoKeyboard Example
135+
~~~~~~~~~~~~~~~~~~~~~
136+
See the ``PianoKeyboard.ino`` and ``PianoKeyboardBLE.ino`` examples for more information on callback operation.
137+
138+
139+
BluetoothHIDMaster::onXXX Callback Installers
140+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141+
142+
.. code :: cpp
143+
144+
void BluetoothHIDMaster::onMouseMove(void (*)(void *, int, int, int), void *cbData = nullptr);
145+
void BluetoothHIDMaster::onMouseButton(void (*)(void *, int, bool), void *cbData = nullptr);
146+
void BluetoothHIDMaster::onKeyDown(void (*)(void *, int), void *cbData = nullptr);
147+
void BluetoothHIDMaster::onKeyUp(void (*)(void *, int), void *cbData = nullptr);
148+
void BluetoothHIDMaster::onConsumerKeyDown(void (*)(void *, int), void *cbData = nullptr);
149+
void BluetoothHIDMaster::onConsumerKeyUp(void (*)(void *, int), void *cbData = nullptr);
150+
void BluetoothHIDMaster::onJoypad(void (*)(void *, int, int, int, int, uint8_t, uint32_t), void *cbData = nullptr);
151+
152+
BluetoothHIDMaster Class
153+
------------------------
154+
155+
bool BluetoothHIDMaster::begin()
156+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157+
Installs and configures the Bluetooth Classic stack and starts processing events. No connections are made at this point.
158+
When running in Classic mode, no BLE devices can be detected or used.
159+
160+
161+
bool BluetoothHIDMaster::begin(const char *BLEName)
162+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163+
Installs and configures the Bluetooth BLE stack and starts processing events. No connections are made at this point.
164+
When running in BLE mode, no Classic devices can be detected or used.
165+
166+
bool BluetoothHIDMaster::connected()
167+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168+
Returns if the Bluetooth stack is up and running and a connection to a device is currently active.
169+
170+
void BluetoothHIDMaster::end()
171+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172+
Disables the Bluetooth stack. Note that with the current Bluetooth implementation restarting the stack (i.e. calling ``begin()`` after ``end()``) is not stable and will not work. Consider storing state and rebooting completely if this is necessary.
173+
174+
bool BluetoothHIDMaster::running()
175+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176+
Returns if the Bluetooth stack is running at all. Does not indicate if there is an active connection or not.
177+
178+
bool BluetoothHIDMaster::hciRunning()
179+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180+
Returns if the Bluetooth stack has passed the initial HCI start up phase. Until this returns ``true`` no Bluetooth operations can be performed.
181+
182+
std::list<BTDeviceInfo> BluetoothHIDMaster::scan(uint32_t mask, int scanTimeSec, bool async)
183+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184+
Passes through the ``BluetoothHCI::scan()`` function to manually scan for a list of nearby devices. If you want to connect to the first found device, this is not needed.
185+
186+
bool BluetoothHIDMaster::connect(const uint8_t *addr)
187+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188+
Start the connection process to the Bluetooth Classic device with the given MAC. Note that this returns immediately, but it may take several seconds until ``connected()`` reports that the connection has been established.
189+
190+
bool BluetoothHIDMaster::connectKeyboard(), connectMouse(), connectJoypad(), connectAny()
191+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192+
Connect to the first found specified Bluetooth Classic device type (or any HID device) in pairing mode. No need to call ``scan()`` or have an address.
193+
194+
bool BluetoothHIDMaster::connectBLE(const uint8_t *addr, int addrType)
195+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196+
Start the connection process to the Bluetooth BLE device with the given MAC. Note that this returns immediately, but it may take several seconds until ``connected()`` reports that the connection has been established.
197+
198+
bool BluetoothHIDMaster::connectBLE()
199+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200+
Connect to the first found BLE device that has a HID service UUID (keyboard, mouse, or joystick)
201+
202+
bool BluetoothHIDMaster::disconnect()
203+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204+
Shuts down the connection to the currently connected device.
205+
206+
void BluetoothHIDMaster::clearPairing()
207+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
208+
Erases all Bluetooth keys from memory. This effectively "forgets" all pairing between devices and can help avoid issues with the beta Bluetooth stack in the SDK.

docs/index.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
4444
USB (Arduino and Adafruit_TinyUSB) <usb>
4545
Multicore Processing <multicore>
4646

47-
Bluetooth (Alpha/Beta) <bluetooth>
47+
Bluetooth <bluetooth>
48+
Bluetooth HID Master <hidmaster>
4849

4950
Single File USB Drive <singlefile>
51+
FatFSUSB - full FS access over USB <fatfsusb>
5052

5153
FreeRTOS SMP (multicore) <freertos>
5254

0 commit comments

Comments
 (0)