Compare commits

..

396 Commits
v0.1 ... master

Author SHA1 Message Date
Olivier Martin f99558d9b8 gattlib-py: Make pylint pass (and fix issue) 2024-04-24 14:37:28 +02:00
Olivier Martin b3c5d2d1ed common/gattlib_common: Add support to compare short UUID with long one 2024-04-24 14:37:28 +02:00
Olivier Martin 9fb48aacb6 gattlib-py/examples/advertisement_data: Fix example 2024-04-24 14:37:28 +02:00
Olivier Martin dbe599dbfb examples/notification: Port example to new gattlib API 2024-04-24 14:37:28 +02:00
Olivier Martin f79e90ce02 gattlib-py: Added support for manufacturer data from GATT advertising 2024-04-11 22:01:28 +02:00
Olivier Martin 35566d198a gattlib-py: Fix setup.py when building source package 2024-04-11 22:01:28 +02:00
Olivier Martin f4ed88eb31 mainloop/gattlib_glib_mainloop: Fix non initialized variable 2024-04-11 22:01:28 +02:00
Olivier Martin aaab2dc74e gattlib_adapter_close: Do not block mutex while waiting for scan_loop_thread to complete 2024-04-11 00:28:24 +02:00
Olivier Martin 880f1d2cd0 Add support to retrieve all manufacturer data from GATT advertisement packets 2024-04-10 10:53:45 +02:00
Olivier Martin 8a108495a1 Change 'gattlib_devices_dump_state()' to 'gattlib_adapter_dump_state()' 2024-04-10 10:53:30 +02:00
Olivier Martin 880ff269e5 gattlib_char: Ensure there is no buffer overflow when we initialize list of GATT characteristic 2024-04-10 10:51:58 +02:00
Olivier Martin 76353f8659 Do not build Python support by default and build examples by default 2024-04-10 10:50:48 +02:00
Olivier Martin db04a0eb5c Introduce gattlib_connection_is_valid() to not access 'connection->device' 2024-04-08 23:10:47 +02:00
Olivier Martin 2d771d9390 Fix gattlib_connection_is_connected 2024-04-08 23:09:09 +02:00
Olivier Martin 5406a97e57 More logging 2024-04-08 23:07:57 +02:00
Olivier Martin 4acf4aa0ab connection: Ensure device_object_path is not freed multiple time 2024-04-08 23:07:57 +02:00
Olivier Martin f609f7d507 adapter: Added support to open multiple time the same adapter 2024-04-08 23:07:57 +02:00
Olivier Martin dc009029fa Log when the adapter or device has been released 2024-04-08 12:01:53 +02:00
Olivier Martin cdd62f6d35 Return specific error code when the adapter or device has been removed 2024-04-08 10:08:57 +02:00
Olivier Martin 0e34df58e5 Single lock for all gattlib library 2024-04-08 00:15:16 +02:00
Olivier Martin 014c2802ee Refactor code to better separate gattlib_adapter_t, gattlib_device_t, gattlib_connection_t and their backends 2024-04-05 13:20:40 +02:00
Olivier Martin 22dca4511c Require a lower version of cmake (same version as Ubuntu 22.04 LTS) 2024-04-05 10:25:54 +02:00
Olivier Martin 5049443704 Ensure the connection structure is not freed when used by the connection thread 2024-04-04 23:48:43 +02:00
Olivier Martin a587aa9dfa gattlib_connect: Set the device has DISCONNECTED on error 2024-04-04 21:54:28 +02:00
Olivier Martin 67ff1de69b gattlib-py/adapter: Catch error on opening/closing BLE adapter 2024-04-04 12:03:29 +02:00
Olivier Martin 53e6c2c7ae tests: Added new test that try to connect/disconnect a same device 2024-04-04 12:03:29 +02:00
Olivier Martin fcedfb9e85 gattlib_adapter: Improve BLE scan code with comments and renaming 2024-04-04 12:03:29 +02:00
Olivier Martin b57d9546df gattlib_glib_mainloop: Ensure mainloop is initialized before using it 2024-04-04 12:03:29 +02:00
Olivier Martin 2e99c4f1b6 dbus: Handle when the device is removed from DBUS 2024-04-04 12:03:29 +02:00
Olivier Martin 709b76019e Manage device state during its life cycle 2024-04-04 12:03:29 +02:00
Olivier Martin 0c1334c5b4 Consolidate device list between discovered and connected devices 2024-04-04 12:03:29 +02:00
Olivier Martin aa6a7b79bb Consolidate device state to prevent concurrent accesses 2024-04-04 12:03:29 +02:00
Olivier Martin fab0e8fa67 Consolidate device mutex 2024-04-03 21:13:33 +02:00
Olivier Martin ce52533f39 Rename structure 'gattlib_connection_t' to '_gattlib_device' 2024-04-03 21:13:33 +02:00
Olivier Martin 2861549a80 ci/generate-python-package.sh: Fix script when no MANIFEST.in 2024-04-03 21:13:33 +02:00
Olivier Martin 7758bae7d4 ci: Automatically create a release on tag 2024-04-03 20:06:46 +02:00
Olivier Martin 42c97d4767 Added new Gattlib error types 2024-04-03 20:06:46 +02:00
Olivier Martin aac4e069c9 CMakeLists.txt: Add DEBUG flag when building DEBUG build 2024-04-03 20:06:46 +02:00
Olivier Martin 8f17232216 Update ".gitignore" 2024-04-03 15:03:48 +02:00
Olivier Martin 86f9a742f3 Ensure connection timeout is freed when the connection is free 2024-03-29 09:18:53 +01:00
Olivier Martin 50dca02e97 Update README 2024-03-29 00:20:41 +01:00
Olivier Martin 6cdbe58e7b FixMe: Disable freeing the handler - there is a pointer ref counter not valid when doing so 2024-03-29 00:20:41 +01:00
Olivier Martin db629448fd Use calloc() instead of malloc() when allocating 'struct' or array in memory 2024-03-29 00:20:30 +01:00
Olivier Martin 5f43addb8f gattlib_disconnection: Added support to wait for the disconnection to be effective 2024-03-29 00:20:30 +01:00
Olivier Martin a85dd83015 Consolidate handlers 2024-03-29 00:19:56 +01:00
Olivier Martin 5ca46ad208 examples: Port more examples to new API 2024-03-27 22:07:16 +01:00
Olivier Martin f3f6bb37bb Generate packages 2024-03-26 18:55:58 +01:00
Olivier Martin 5d9a36f1d1 logging_backend/python: Do not call 'GATTLIB_LOG(GATTLIB_ERROR, ...)' on error to avoid recursion 2024-03-26 16:49:19 +01:00
Olivier Martin 6e6436ceb3 gattlib_adapter: Check if 'is_scanning' before stopping BLE scan 2024-03-26 13:46:31 +01:00
Olivier Martin 5ba3eda6f5 dbus/gattlib_adapter: Use mutex to get device manager 2024-03-26 13:46:31 +01:00
Olivier Martin 8e351e746c python: Introduce __version__ 2024-03-26 13:43:42 +01:00
Olivier Martin 6cea2d37db Ensure gattlib can be built without Python support 2024-03-25 12:43:17 +01:00
Olivier Martin 2a46780e96 Fix gattlib and examples 2024-03-18 00:19:44 +01:00
Olivier Martin b2c4094cb6 gattlib-py: Fix some memory leaks 2024-03-13 13:52:57 +01:00
Olivier Martin d2fb01d85e Fix gattlib connection release on disconnection 2024-03-13 13:52:57 +01:00
Olivier Martin 98833bf7ce gattlib-py/gattlib/mainloop: Ensure we are not overwriting the mainloop 2024-03-13 13:52:57 +01:00
Olivier Martin 6823c02892 dbus: Improve logging 2024-03-13 13:52:57 +01:00
Olivier Martin 7925aa6a38 Fix compilation warnings about enum type 2024-03-12 20:38:31 +01:00
Olivier Martin 2edc8f2620 Add support to enable Address Sanitizer 2024-03-12 20:37:53 +01:00
Olivier Martin 36e0cb4934 Add more debug logs 2024-03-07 23:58:35 +01:00
Olivier Martin 24ab0ea95f Reduce compilation warnings 2024-03-07 23:57:58 +01:00
Olivier Martin e26e9f0b7a Fix some compiler warnings 2024-03-07 08:53:42 +01:00
Olivier Martin 6e718253b0 adapter: Add support to avoid double free of BLE adapter 2024-03-06 15:03:56 +01:00
Olivier Martin ea1fe15857 gattlib: Catch connectio timeout 2024-03-05 22:46:38 +01:00
Olivier Martin 00cbc1ab87 common: Set pointer to NULL after freeing them 2024-02-27 11:28:49 +01:00
Olivier Martin d2702050ec gattlib-py: Add support for loading 'libgattlib.so' from different location 2024-02-26 23:19:10 +01:00
Olivier Martin f4cc321a90 dbus/gattlib_adapter: Stop BLE scan before waiting for the loop to stop 2024-02-26 23:16:35 +01:00
Olivier Martin 6321d28d25 gattlib-py/setup.py: Add gattlib-py dependency 2024-02-23 10:20:21 +01:00
Olivier Martin f0426ae3e3 gattlib-py/gattlib: Fix loading native library 2024-02-22 22:26:43 +01:00
Olivier Martin ebd163f1dc ci: Push tagged gattlib to Pypi repo 2024-02-22 21:33:19 +01:00
Olivier Martin 01ea87aa16 Disable C examples as they are not ported yet to new gattlib_connect() 2024-02-22 19:54:43 +01:00
Olivier Martin f38f73a9a4 gattlib: Change gattlib_connect to better use event loop 2024-02-22 19:54:43 +01:00
Olivier Martin e554dec3dc gattlib_adapter: Improve/Fix BLE scan 2024-02-22 19:54:43 +01:00
Olivier Martin 100c5d5f69 gattlib_adapter: Introduce wait_scan_loop_stop_scanning 2024-02-22 19:54:43 +01:00
Olivier Martin 860f7f5b61 ci: Fix tagged release 2024-02-22 19:30:58 +01:00
Olivier Martin 13bd692bb4 ci: Generate Python package with cibuildwheel 2024-02-22 13:28:22 +01:00
Olivier Martin 18e1658d6f ci: Fix build 2024-02-22 09:30:22 +01:00
Olivier Martin d3d9600114 cmake: Specify cmake version + Fix finding Python development module 2024-02-22 09:30:22 +01:00
Olivier Martin 5f5cb5bd12 common/logging_backend: Introduce Python backend 2024-02-22 09:30:22 +01:00
Olivier Martin 6751a17cee .github/workflows/github-actions.yml: Fix Pypi publishing 2024-02-21 18:01:19 +01:00
Olivier Martin 57c99c6038 .github/workflows/github-actions.yml: Update actions/checkout 2024-02-21 17:53:59 +01:00
Olivier Martin b8268c4cb5 ci: Generate Python package 2024-02-21 17:45:09 +01:00
Olivier Martin fbd65421d0 Ensure adapter is present 2024-02-21 00:28:08 +01:00
Olivier Martin 61043afd98 gattlib-py: Use logger (instead of logging) 2024-02-21 00:28:08 +01:00
Olivier Martin aacc53c511 Fix warnings from release build 2024-02-21 00:28:08 +01:00
Olivier Martin 7d5748cb0d ci: Script to generate Python package 2024-02-21 00:28:08 +01:00
Olivier Martin 33a634a535 gattlib-py/setup.py: Build C files along Python module 2024-02-21 00:28:08 +01:00
Olivier Martin 2f83e85eee dbus: Remove event_thread 2024-02-19 18:00:52 +01:00
Olivier Martin 1530184776 gattlib_adapter: Add support to reconnect disconnected device 2024-02-19 18:00:52 +01:00
Olivier Martin b28a0422f0 dbus: Add support to remove device property signal 2024-02-19 18:00:52 +01:00
Olivier Martin b193543fb0 gattlib/mainloop: Move mainloop to Python to ease support 2024-02-19 18:00:52 +01:00
Olivier Martin 7a8d53d817 gattlib-py/gattlib/exception: Print 'le-connection-abort-by-local' on related exception 2024-02-19 18:00:52 +01:00
Olivier Martin 7922810016 gattlib-py/gattlib/device: Fix logging 2024-02-19 18:00:52 +01:00
Olivier Martin 8e5412a1a9 gattlib-py: Ensure BLE adapter is opened 2024-02-19 18:00:52 +01:00
Olivier Martin c4e4b8fa5a dbus/gattlib_notification: Use lookup instead of looping through variant keys 2024-02-19 18:00:52 +01:00
Olivier Martin 76fb44643f gattlib-py/setup.py: Remove Travis CI support 2024-02-19 18:00:52 +01:00
Olivier Martin 0a868a506b Added a public function to ease the use of GLib mainloop 2024-02-19 18:00:52 +01:00
Olivier Martin 4c5f35f15f error: Introduce error module to catch DBUS error details 2024-02-15 22:00:06 +01:00
Olivier Martin ad7aa1899e on_handle_device_property_change: Logging changes 2024-02-15 22:00:06 +01:00
Olivier Martin f894c8e23a gattlib_disconnect: Add mutex to avoid double free 2024-02-15 22:00:06 +01:00
Olivier Martin 7f6979c82b gatt_notification: Use thread pool of one thread to ensure serial processing of notification 2024-02-15 22:00:06 +01:00
Olivier Martin db8aee543b dbus/on_handle_characteristic_indication: Fix logging 2024-02-15 22:00:06 +01:00
Olivier Martin 8065d12dac python: Various fixes 2024-02-15 22:00:06 +01:00
Olivier Martin 011f4e4c4a gattlib_disconnect: Call on_disconnect callback 2024-02-15 22:00:06 +01:00
Olivier Martin 0fde4ff82d gattlib_adapter_close: Ensure BLE scan is disabled 2024-02-15 22:00:06 +01:00
Olivier Martin 9a9e49edcd dbus/on_interface_proxy_properties_changed: Check device_manager is not NULL (could happen on disconnection) 2024-02-15 22:00:06 +01:00
Olivier Martin 959ee55b61 gattlib: Change gattlib_register_(on_disconnect|notification|indication) 2024-02-15 22:00:06 +01:00
Olivier Martin 118dc961d6 gattlib_on_disconnected_device: Make callback synchronous 2024-02-15 22:00:06 +01:00
Olivier Martin 2518348023 gattlib: Introduce 'gattlib_adapter_get_name()' 2024-02-12 22:35:46 +01:00
Olivier Martin 884904a3c0 dbus/gattlib_adapter: Fix 'gattlib_adapter_close()' 2024-02-12 22:35:46 +01:00
Olivier Martin 1d80061bf2 python: Fix callback back to native gattlib 2024-02-12 22:04:57 +01:00
Olivier Martin ec9e5cd38a dbus: Fix build 2024-02-12 09:52:07 +01:00
Olivier Martin d5aa8d6468 Fix logging for on_interface_proxy_properties_changed() 2024-02-12 00:13:07 +01:00
Olivier Martin 306acf8483 Fix 'discovered_devices' list (set NULL after free + mutex) 2024-02-12 00:13:07 +01:00
Olivier Martin 3c9b0eaa1c Introduce 'GATTLIB_ERROR_TIMEOUT' error 2024-02-12 00:13:07 +01:00
Olivier Martin 028dfef5fc python: Update deprecated calls 2024-02-12 00:13:07 +01:00
Olivier Martin a41061c1d4 Various fixes/logging/features 2024-02-12 00:11:45 +01:00
Olivier Martin 642556f8b9 gattlib-py/gattlib/adapter: Update comment 2024-02-12 00:11:45 +01:00
Olivier Martin 96407ad763 gattlib-py/examples/ble_scan: Fix example 2024-02-12 00:11:45 +01:00
Olivier Martin 6d271f98b6 gattlib-py: Document how to develop 'gattlib-py' 2024-02-12 00:11:45 +01:00
Olivier Martin 33a8a27592 gattlib-py: Fix/Handle returned error code 2022-05-16 21:44:31 +02:00
Olivier Martin 0369342fd4 Introduce 'gattlib_characteristic_free_value()' to release memory allocated after reading GATT characteristic 2022-05-16 21:44:31 +02:00
Olivier Martin 3ac5707c95 dbus: Fix battery value reading 2022-05-16 21:44:31 +02:00
Olivier Martin c1a3c02154 dbus: Add battery characteristics to the list of GATT characteristic 2022-05-16 21:44:31 +02:00
Olivier Martin 20f2d5facf gattlib-py/device: Add support to unregister GATT notification 2022-05-16 21:44:31 +02:00
Olivier Martin 59820e2cad gattlib-py/device: Re-enable RSSI 2022-05-16 21:44:31 +02:00
Olivier Martin ac1f3d44d5 gattlib-py/exception: Handle -EINVAL 2022-05-16 21:44:31 +02:00
Olivier Martin bae7df3ee0 gattlib-py/adapter: Add support to pass UUID for the Advertisement filter 2022-05-16 21:44:31 +02:00
Olivier Martin b5a785e4b6 dbus: Refactore gattlib_adapter_scan_enable_with_filter() to also introduce the non-blocking version 2022-05-16 21:44:31 +02:00
Olivier Martin 75fda5df84 gattlib-py: Rename 'id' attribute into 'mac_address' 2022-05-11 20:29:07 +02:00
Olivier Martin 2570850046 common/gattlib_common: Release Python PyObject 2022-05-11 20:29:07 +02:00
Olivier Martin d9c18b93a3 dbus/gattlib_discover_primary: Ensure a valid connection pointer is given 2022-05-11 20:29:07 +02:00
Olivier Martin 0719dcc31d gattlib-py/examples/ble_scan: Explicit action (logging) 2022-05-11 20:29:07 +02:00
Olivier Martin 5c87eda925 build: Disable doc generation by default 2022-05-11 20:29:07 +02:00
wurong bdc273fe0a fix mem leak. 2022-05-11 15:53:48 +02:00
tswaehn b82be455b4 fix: sigsev when service is null 2022-03-10 22:00:34 +01:00
tswaehn 5badee94b9 fix: sigsev when service property returns null 2022-03-10 22:00:34 +01:00
VL-80 2448da5410 bluez5: Fix potential null pointer dereference
d->attrId was called before d was checked for being a valid pointer.
2022-01-30 21:43:05 +01:00
VL-80 85acbd8c88 bluez4: Fix potential null pointer dereference
d->attrId was called before d was checked for being a valid pointer.
2022-01-30 21:43:05 +01:00
VL-80 5b8893c647 bluez/gattlib_adapter.c: Fix bug
The checking of the result of the hci_open_dev() function needs to be done on the derefenced value, not the pointer (which can not be negative).
2022-01-30 21:43:05 +01:00
tswaehn c2c6b2f17b fix: device_manager not found => SIGSEV 2022-01-30 21:41:17 +01:00
tswaehn deee3766e1 fix: gattlib_adapter not found => SIGSEV 2022-01-30 21:41:17 +01:00
Flaviu Tamas bb90b55dde Flush uart after getting message
The internal stdout buffering causes problems when we're trying to get
data, but the data doesn't have any newlines or anything like that.
We're forced to wait for forever until the buffer gets filled up and
output to the console.

This solves that by flushing immediately after each message.
2021-12-03 09:39:07 +01:00
Olivier Martin 1afaa8b460 Introduce Gattlib logging backend 2021-10-18 16:46:45 +02:00
Olivier Martin 809a10a289 dbus/gattlib_notification: Fix warning 2021-10-17 22:28:22 +02:00
Olivier Martin e93504b91f cmake: Update 'cmake_minimum_required' as 2.6 is getting deprecated 2021-10-17 22:22:05 +02:00
Olivier Martin e2b189d226 handle_dbus_gattcharacteristic_from_path: Ensure 'characteristic' is unref 2021-10-17 22:15:27 +02:00
Peter Rosin f90a95bcff avoid calling g_object_unref on the pointers that have just been free()d
"Steal" the notified_characteristics pointer while at it so that it
does not remain and point to a stale list.
2021-10-17 22:07:06 +02:00
Olivier Martin fa54ae42cc handle_dbus_gattcharacteristic_from_path: Ensure 'characteristic_uuid_str' is not NULL 2021-09-15 22:44:28 +02:00
Olivier Martin c3abb7eb6c dbus/gattlib.c: Fix copyright 2021-09-01 10:42:26 +02:00
Olivier Martin f4ecc64d29 Clarify and update license 2021-09-01 00:04:00 +02:00
Кирилл Зимников 2c38df5f30 Fix memory problems 2021-08-31 23:19:37 +02:00
Olivier Martin db44d7a99d ci: Add support for github actions 2021-06-09 17:53:08 +02:00
vlefebvre d66e268865 fix glib CRITICAL warning
In the case when we deal with the timeout/error result, the resource
has lready been unref

Signed-off-by: vlefebvre <valentin.lefebvre@iot.bzh>
2021-05-28 22:29:40 +02:00
vlefebvre f3b5b295bc fix hard path during installation of gattlib
Using CMAKE macro to install correctly the library gattlib. In
aarch64 it will install into /usr/lib64 dir insteed of /usr/lib.

Signed-off-by: vlefebvre <valentin.lefebvre@iot.bzh>
2021-05-28 22:29:08 +02:00
0xloem edb5862f96 make notification example a little more general 2021-05-23 13:46:21 +02:00
Kevin Dewald 15210d1c35 Fixed recently introduced double-free error. 2021-04-15 22:39:10 +02:00
chenbin 3f85abd606 fix memory leak. 2021-04-13 22:49:25 +02:00
Kevin Dewald b137160afc Fixed handling of null MAC addresses during scanning. 2021-04-05 21:45:27 +02:00
Kevin Dewald 9451e19426 Add verification for null mac address. 2021-03-19 12:46:32 +01:00
Kevin Dewald 321c37dc57 Removed extra print statement. 2021-03-04 00:48:06 +01:00
Kevin Dewald 49790a92bf Fixed bug where notifications will be enabled but no events will be received. 2021-03-03 13:04:50 +01:00
Kevin Dewald fee6603fa3 Fixed uninitialized memory error. 2021-03-03 13:01:30 +01:00
Kevin Dewald 3c917fe683 Fixed missing characteristic detection when discovering services. 2021-03-02 22:23:45 +01:00
Olivier Martin d63b7ccb27 examples/nordic_uart: Use 'gattlib_notification_start()' 2021-02-01 16:48:02 +01:00
Olivier Martin b8f60de4e5 dbus/gattlib_notification: Print which UUID cannot be found 2021-02-01 16:46:25 +01:00
0xloem acf3df7da6 Force python to link with the right kind of libraries 2020-12-13 11:30:51 +00:00
Avinash Jois 6dcf6b904e Fix timeout removal 2020-12-07 23:17:08 +00:00
Avinash Jois bef872c588 Remove extra line 2020-12-07 23:17:08 +00:00
Avinash Jois 989483acdb Properly disable scan after scan_loop termination 2020-12-07 23:17:08 +00:00
Ankur Verma c6c29ad9fe Allow gattlib to be added as a subdirectory 2020-11-27 16:00:42 +00:00
Vanshil Shah 054f64e115 Set adapter name properly if non-default adapter is passed in 2020-07-20 20:19:09 +01:00
saad-s f5c2fcc906 cmake option to enable/disable python interface 2020-07-02 13:29:18 +01:00
saad-s d4bd91ad1e fix missing ARCHIVE DESTINATION for static building 2020-07-02 13:29:18 +01:00
Olivier Martin b63dc0f23e dbus: Fix 'Write-Without-Reponse' GATT operation 2020-05-25 23:54:48 +02:00
Ankur Verma 0bbe347daf Add support to build gattlib dbus mode as a static library 2020-05-22 10:50:51 +02:00
Olivier Martin 7056103e6a dbus/gattlib_advertisement: Fix advertisement_data access in get_advertisement_data_from_device() 2020-04-09 21:36:32 +02:00
Olivier Martin b61c03ae25
gattlib-py/examples/advertisement_data: Fix typo 2020-04-09 11:49:19 +02:00
Olivier Martin 3dfaa875b6 gattlib-py/examples: Introduce 'advertisement_data' 2020-04-09 11:47:34 +02:00
Olivier Martin a34a2d2a21 gattlib-py/gattlib/device.py: Add support to retrieve advertisement data when device not connected 2020-04-09 11:47:34 +02:00
Olivier Martin f18dd02530 gattlib-py/gattlib/adapter.py: Add support for GATTLIB_DISCOVER_FILTER_NOTIFY_CHANGE 2020-04-09 11:47:34 +02:00
Olivier Martin 8cb7f01104 gattlib-py: Fix 'gattlib_adapter_scan_*()' prototype after 'timeout' type change 2020-04-09 11:47:34 +02:00
Olivier Martin 9315ecfa54 dbus: Check connection parameter passed to gattlib_get_advertisement_data() 2020-04-09 11:47:34 +02:00
Olivier Martin eb70896c98 examples: Introduce 'advertisement_data' to demonstrate how to retrieve advertisement data from devices around 2020-04-09 10:33:27 +02:00
Olivier Martin 825fc4d07c gattlib: Introduce indefinite scan timeout 2020-04-09 10:33:27 +02:00
Olivier Martin c0215ee4ce gattlib: Introduce GATTLIB_DISCOVER_FILTER_NOTIFY_CHANGE 2020-04-09 10:33:27 +02:00
Olivier Martin 4ebc640ddd dbus: Only start BLE scan when all signals are connected 2020-04-09 10:33:27 +02:00
Luca Weiss d40ac8e743 gattlib-py: add get_advertisement_data method 2020-04-08 22:57:52 +02:00
Olivier Martin a8a06114e2 bluez: Fix warning 2020-04-08 22:30:54 +02:00
Olivier Martin ddc790358f dbus: Ensure GATT Notification/Indication are correctly disconnected 2020-04-08 22:30:54 +02:00
Olivier Martin 504ee7d1a7 dbus: Factorise code between GATT Notification and GATT Indication 2020-04-08 22:30:54 +02:00
Olivier Martin 46da1ee50c dbus: Prevent compiler warning 2020-04-08 22:30:54 +02:00
Olivier Martin 6f3ad714a2 dbus: Attach the BLE adapter to connection 2020-04-08 22:30:54 +02:00
Olivier Martin 71c4e71952 gattlib: Pass 'adapter' rather than MAC address to gattlib_connect() 2020-04-08 22:30:54 +02:00
Olivier Martin 7107d9f5b4 dbus: Check the disconnection of the handler has really succeeded 2020-04-08 22:30:54 +02:00
Olivier Martin 52f195f5c2 dbus: Do not free 'rssi_variant' before using 'arg_properties_builder' 2020-04-08 12:58:39 +02:00
Olivier Martin 6df99eadbe dbus: Remove scan timeout 2020-04-08 00:29:36 +02:00
Chris Thornton d26065d6ad Only pass pointer value as long type on 64 bit systems.
When testing this on a RPI this causes issues, so we need to switch
based on the architecture.
2020-04-07 22:28:11 +02:00
Olivier Martin 0ef32af289 gattlib: Add the ability to stop scanning before timeout expired 2020-04-07 12:29:19 +02:00
Olivier Martin 51bbc0242b example: Add example to find Eddystone in C 2020-04-07 12:29:19 +02:00
Olivier Martin 392d9d5eb3 gattlib.h: Add Eddystone constants 2020-04-07 12:29:19 +02:00
Chris Thornton 1779c75062 Pass the pointer value as a long int to python
The pointer could be truncated which results in an invalid memory
address when trying to get at the array.
2020-04-07 11:48:54 +02:00
Chris Thornton efc656ca52 Use c_ubyte for byte array casts
This prevents having to do the explicit & 0xff, and avoids generating an
error when calling .read() (which didn't have the bitmask)
2020-04-07 11:48:54 +02:00
Chris Thornton 80d26d702d Add types to gattlib_(dis)connect in gattlib-py
The return type defaults to int for connect, causing the pointer to get
corrupted. Similarly, the disconnect call needs to avoid truncating the
handle.
2020-04-06 23:16:42 +02:00
Olivier Martin cfc47a0c0d Fix Python3.8 support
Fix: #146
2020-04-04 10:31:32 +02:00
Olivier Martin 9663984e9d CMakeLists.txt: Fix build 2020-04-04 00:41:09 +02:00
Olivier Martin 26d288613d doc: Check if Doxygen is installed before generating the doc 2020-04-04 00:06:43 +02:00
Olivier Martin 6a4d00b43c doc: Only build Python documention when Sphinx is installed 2020-04-03 23:59:27 +02:00
Vanshil Shah 08ce1b3303 Make indications work properly 2020-03-29 12:12:48 +02:00
Khem Raj 3d656b1e19 cmake: Use GNUInstallDirs
Helps install cmakefiles in right libdir

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2020-03-17 20:39:39 +01:00
Jon 5c7ee43bd7 fixed 'apt-install' to 'apt install'
i want my first commit
2019-11-19 08:17:53 +01:00
Daniels Umanovskis c6a3325222 dbus: Add support for reading manufacturer data from advertisement packets 2019-11-05 23:31:59 +01:00
Daniels Umanovskis d300b66ebd Make building docs optional - defaults to on 2019-10-29 15:44:25 +01:00
Johannes Bauer 1f6c89f0bf Fixed error message in notification example app
Fixed a small typo in which the newline was printed one character early
in an error message.
2019-09-28 15:00:47 +02:00
Olivier Martin 55d875438b CMakeLists.txt: Fixed build 2019-08-07 13:41:02 +02:00
Olivier Martin a5a45a9fad CMakeLists.txt: Fix implicitly converting 'BOOLEAN' to 'STRING' type. 2019-08-07 13:26:36 +02:00
Olivier Martin 42c9f2667d CMakeLists.txt: Fix version number 2019-08-05 14:42:07 +02:00
Olivier Martin 6a770e4349 gattlib-py: Introduce 'setup.py' 2019-08-05 13:33:11 +02:00
Olivier Martin 6ace06d3c5 dbus: Do not free value that has been freed by gdbus API 2019-08-05 09:16:41 +02:00
Olivier Martin 3b495609ed dbus: Remove non-necessary g_variant_builder_unref() as g_variant_builder_end() free it 2019-08-05 09:16:41 +02:00
Olivier Martin 53bb794a7d examples/read_write_memory: Added read/write for demonstrating memory management 2019-07-21 20:35:57 +02:00
Olivier Martin 967b46bb99 dbus: Remove more memory leak 2019-07-21 20:35:57 +02:00
Olivier Martin 51c6cbeee2 dbus: Reduce memory leak 2019-07-18 20:58:26 +02:00
Olivier Martin 3d433e3551 Initial generated documentation support 2019-07-15 23:33:13 +02:00
Olivier Martin e342e292fd gattlib.h: Make sure everything is converted 2019-07-15 23:33:13 +02:00
Olivier Martin 3dd0ab40b4 include/gattlib.h: Added documentation for Stream API 2019-07-15 18:04:11 +02:00
Olivier Martin 193c86590e gattlib: Introduce helper function to select Eddystone devices 2019-07-15 18:04:11 +02:00
Olivier Martin 50129fe753 bluez: Returns GATTLIB_ errors 2019-07-15 18:04:11 +02:00
Olivier Martin 69fb243fe7 gattlib: Implement `gattlib_get_advertisement_data()` 2019-07-15 18:04:11 +02:00
Olivier Martin bcf0596abe README.md: Fixed BLUEZ_VERSION 2019-07-14 22:53:24 +02:00
Olivier Martin c956a5b151 .gitignore: Added '__pycache__' to ignore list 2019-07-14 22:47:06 +02:00
Olivier Martin fef6659af0 gattlib-py: Exposed 'Write-without-response' 2019-07-14 22:47:06 +02:00
Olivier Martin 3f829b806c gattlib-py: Check type of data for write() operation 2019-07-14 22:47:06 +02:00
Olivier Martin 2e6cc4c381 dbus/gattlib.c: Return NOT_FOUND when trying to stop notification not started 2019-07-14 22:47:06 +02:00
Olivier Martin e9b98f6dd7 gattlib-py: Disable gattlib_get_rssi() (see #75) 2019-07-14 22:47:06 +02:00
Olivier Martin 4e9b1094d4 gattlib-py/examples/nordic_thingy: Add example for sound support 2019-07-14 22:47:06 +02:00
Olivier Martin e5daed3484 CMakeLists.txt: Add support to specifying Bluez version at build time 2019-07-14 22:47:06 +02:00
Olivier Martin 4f8625cedf gattlib: Add stream API 2019-07-14 22:47:06 +02:00
Olivier Martin 2831cdf765 dbus: Added Bluez v5.48 DBUS API 2019-07-14 22:47:06 +02:00
Olivier Martin ca92375558 dbus: Move GATT characteristic code into 'gattlib_char.c' 2019-07-14 22:47:06 +02:00
Michael Rolland 4b9252bad1 gattlib: Fix disconnection handler type check 2019-07-11 17:54:56 +02:00
Olivier Martin 0142c33dd8 gattlib: Disable gattlib_get_rssi() for now
This API has been disabled until this issue is clarified: https://github.com/labapart/gattlib/issues/75
RSSI can be accessed through `gattlib_get_rssi_from_mac()` before the
connection is established.
2019-07-09 20:04:35 +02:00
Olivier Martin ebf3cc80fb gattlib-py/examples/nordic_thingy: Explicitely call 'discover()' 2019-07-09 20:04:35 +02:00
Olivier Martin d7a323ccd7 gattlib-py/gattlib/device.py: Fixed returned RSSI value 2019-07-09 20:04:35 +02:00
Olivier Martin a42f76aa7d gattlib: Added 'adapter' and 'user_data' parameter to 'gattlib_discovered_device_t' callback 2019-07-09 20:04:35 +02:00
Olivier Martin a52f66834a gattlib: Introduce 'gattlib_get_rssi_from_mac()' 2019-07-09 20:04:35 +02:00
Olivier Martin a9cd2d3c1a dbus: Refactor Adapter code 2019-07-09 20:04:35 +02:00
Olivier Martin d55898276d gattlib-py/examples: Added new Python sample 'find_eddystone' 2019-07-09 20:04:35 +02:00
Olivier Martin bca923366e gattlib-py: Added BLE Scan sample 2019-07-09 20:04:35 +02:00
Olivier Martin 40eec80170 include/gattlib.h: Added some function documentation 2019-07-09 20:04:35 +02:00
Olivier Martin 2ae549f9d6 gattlib: Introduce gattlib_adapter_scan_enable_with_filter() 2019-07-09 20:04:35 +02:00
Olivier Martin eca8415fd6 gattlib: Introduced gattlib_get_rssi()
Fix: #75
2019-07-09 12:34:32 +02:00
Olivier Martin 531477b941 gattlib-py: Fix disconnect API 2019-07-09 11:22:20 +02:00
Olivier Martin 43b5d9a113 .travis.yml: Fixed cross-compile builds 2019-07-09 11:03:02 +02:00
Olivier Martin 2b9d932792 CMakeLists.txt: Increase CMake version to prevent some CMake error with cross-compiler
See: https://cmake.org/cmake/help/v3.4/policy/CMP0065.html
2019-07-09 11:03:02 +02:00
Olivier Martin e74543fa56 Initial Python support 2019-07-07 22:17:49 +02:00
Olivier Martin a1ad48f20c dbus: Fixed warnings 2019-07-07 22:17:49 +02:00
Olivier Martin 046f077085 gattlib: Move 'struct _gatt_connection_t' out of 'gattlib.h' 2019-07-07 22:17:49 +02:00
Olivier Martin 8438cd5c0d dbus: Check if the Services are really resolved 2019-07-07 22:17:49 +02:00
Olivier Martin 1db0ab51a6 README.md: Added note about support 2019-07-07 22:17:49 +02:00
Olivier Martin 8020503ab6 gattlib: Added support for write-without-response 2019-07-05 22:50:23 +02:00
Olivier Martin 1e0e57070f dbus: Wait for 'ServicesResolved' before telling we are connected 2019-06-27 22:27:39 +02:00
Olivier Martin 2accddb3c7 dbus: Catch error when there is no device present 2019-06-27 22:27:39 +02:00
Olivier Martin 9a665239a1 examples/read_write: Clarify error message 2019-06-27 22:27:39 +02:00
Olivier Martin 50401ad1c5 include/gattlib.h: Allow to call gattlib_discover_primary() with NULL arguments 2019-06-27 22:27:39 +02:00
Olivier Martin 028004a8a1 examples: Use GATTLIB_ error code 2019-06-27 22:27:39 +02:00
Olivier Martin 120f6e0886 bluez: Minor coding style change 2019-06-27 22:27:39 +02:00
Olivier Martin 2d81b253da dbus: Add support for handle 2019-06-12 17:15:50 +02:00
Olivier Martin ceaa8a17e4 gattlib: Change gattlib_read_char_by_uuid() to return an allocated buffer that fits GATT value size 2019-05-27 22:25:46 +02:00
Olivier Martin 683efaaca4 dbus: Fix new device discovery
We check for existing device activity to let the caller they are still present.
2019-05-27 22:25:46 +02:00
Olivier Martin e3ff819872 Reduce memory leaks 2019-05-21 21:40:55 +02:00
Olivier Martin 54f06b64f5 Check allocations are successfull 2019-05-21 21:40:55 +02:00
Olivier Martin c479cec21f include/gattlib.h: Unify error code 2019-05-21 21:40:55 +02:00
Olivier Martin 9bed1e17c8 dbus/gattlib.c: Ensure we register for 'property-changed' signals before making any method calls 2019-05-20 21:44:20 +02:00
Olivier Martin d4e0c22792 CMakeLists.txt: Build firmware as Debug by default 2019-05-20 20:15:34 +02:00
Olivier Martin c2a07a9139 Remove legacy options from `gattlib_connect()`
Legacy options can still be set from 'options' parameter.
2019-05-20 20:15:23 +02:00
Olivier Martin e822d3268a dbus: Ensure the timeout is removed when connected 2019-05-20 20:15:10 +02:00
Olivier Martin d8fb10906b dbus/gattlib.c: Do not list 'old' devices when scanning for BLE device 2019-05-20 20:14:54 +02:00
Olivier Martin 3a1e92ae5d Update 'dev' tag on success 2019-05-19 11:44:47 +02:00
Olivier Martin ca9725f806 dbus: Implement gattlib_connect_async() 2019-05-19 00:27:54 +02:00
Olivier Martin 510d650b85 gattlib_adapter_open: Ensure adapter pointer is not NULL 2019-05-19 00:27:54 +02:00
Olivier Martin 58d5dac125 requirements.dep: Add missing dependency 2019-05-19 00:16:13 +02:00
Olivier Martin 9db483bdcc dbus/CMakeLists.txt: Fix Bluez pre-v5.40 2019-05-19 00:16:13 +02:00
Olivier Martin 60f3bc1c5a .travis.yml: Use cross-sysroot to retrieve Linux Distribution packages for cross-compilation 2019-05-19 00:16:13 +02:00
Olivier Martin 98ac9e5d2b gattlib: Introduce 'gattlib_register_on_disconnect()' 2019-05-03 09:47:58 +02:00
Olivier Martin bcac05a811 examples/notification: Catch CTRL-C to exit properly 2019-05-03 09:47:18 +02:00
Olivier Martin 71f33207c7 dbus: Print error when failing 2019-05-03 09:47:02 +02:00
Olivier Martin f9b92018f1 examples/read_write: Print an error message rather than an assert when the GATT characteristic is not found 2019-03-05 17:15:29 +01:00
Olivier Martin c2e48c3fd6 dbus: Add an error message when trying to access CCC through DBUS interface 2019-03-05 17:14:10 +01:00
Olivier Martin 10af2f1971 dbus/gattlib.c: Add support to read battery level from gattlib_read_char_by_uuid() 2019-03-05 16:58:13 +01:00
Olivier Martin cbeca9d6c0 examples/notification: Exit cleanly notification example 2019-03-05 16:39:46 +01:00
Olivier Martin 62022bdab9 dbus/gattlib.c: Add support to disconnection from notification 2019-03-05 16:33:43 +01:00
Olivier Martin ff07ac89f1 dbus: Add support for Bluez Battery Profile 2019-03-05 16:18:54 +01:00
Olivier Martin 532c405323 dbus/gattlib.c: Print error message on stderr 2019-03-05 16:15:14 +01:00
Olivier Martin 846261120c examples/read_write: Fix hexadecimal value
Found by @kwikius in #74
2019-03-05 13:29:40 +01:00
Olivier Martin 7ad64704cb bluez: Fix buffer length in gattlib_write_char_by_uuid()
Issue found by @kwikius in #74 and @mweal-ed in #35.
2019-03-05 13:22:15 +01:00
Olivier Martin 3ce4632d1c bluez/gattlib_connect.c: Make intentation consistent 2019-03-05 13:15:22 +01:00
Olivier Martin 60b813a770 Fix stack-based bufferoverflow
Fix: #81
Fix: #82
2019-03-05 13:11:50 +01:00
Olivier Martin 5a31a00871 CMakeLists.txt: Add error message when bluez package is not available 2019-03-05 13:04:10 +01:00
Milan Pandurov 1402183edd bugfix: Passing user provided pointer to notification handler
Instead of connection object pointer, user should receive
pointer to context it registered in gattlib_register_notification
2019-03-04 09:16:35 +01:00
Philipp Finke f0b1f7c5ef Added support for multiple connections to devices
with same GATT. This fixes issue #29.
2019-01-30 16:30:54 +01:00
Daniel Vlasenko 7a2fdbd062 andded user data pointer gatt_connect_async signature. these data will be passed to gatt_connect_cb callback to get information about object requested connection 2018-10-18 09:10:55 +02:00
Olivier Martin 0f8c02c6a6 travis-ci: Add libcre-dev to armhf and arm64 2018-01-03 15:10:48 +01:00
Marcus Georgi 096acbe837 explicitly link gattlib library in examples 2018-01-03 14:15:29 +01:00
Marcus Georgi 647f3d3c10 explicitly link to pthread and libpcre in examples
- omitting this causes linker errors when cross-compiling
2018-01-03 14:15:17 +01:00
Thomas Li Fredriksen a370ea5f02 Fixed sub-project include-path interface 2018-01-03 13:45:28 +01:00
Thomas Li Fredriksen d6a87e47a9 Fixed examples linker issue (missing pthread link). Added two cmake-options GATTLIB_BUILD_EXAMPLES and GATTLIB_SHARED_LIB 2018-01-03 13:45:28 +01:00
Olivier Martin 5b08f051d8 travis-ci: Allow to overwrite artifacts as the 'dev' ones need to be overwritten 2018-01-03 13:21:31 +01:00
Olivier Martin f4e09c0fd6 README.md: Update development package links 2018-01-03 13:08:39 +01:00
Olivier Martin 72a13512a0 travis-ci: Skip TRAVIS_TAG from package name as we change the version number when using the tag 'dev' 2018-01-03 12:57:30 +01:00
Olivier Martin 2a8fee224d CMakeLists.txt: Ensure '0.2-dev' tag is used when building 'dev' tag
Debian based distributions do not like package version without number.
2018-01-03 12:11:41 +01:00
Olivier Martin 91f9e93522 travis-ci: Update Debian dependancies 2018-01-03 12:05:08 +01:00
Olivier Martin 3d7802af21 CMakeLists.txt: Print version that is building to ease debugging on travis CI system 2018-01-03 11:57:41 +01:00
Olivier Martin 6ab868245e Fixed travis by updating libc-dev version 2017-10-08 22:16:05 +02:00
csl 56a8b24153 Correct order of arguments to org_bluez_gatt_characteristic1_call_write_value_sync 2017-10-07 23:46:13 +02:00
csl 01d5c51a0c Fix problem with gvariant formatting causing GLib format errors 2017-09-08 17:18:53 +02:00
Olivier Martin 4af454d026 travis: Update ARM Libc for cross-compilation 2017-09-08 17:08:10 +02:00
Olivier Martin 82684b107e Merge pull request #39 from kinemic/debian_architecture_crosscompile
do not use dpkg to change deb arch when crosscompiling
2017-07-27 12:18:04 +02:00
Olivier Martin ce6e6a687d Merge pull request #38 from kinemic/non_travis_versioning
prepend the non-travis version with a number
2017-07-27 12:17:20 +02:00
Marcus Georgi cd6701dc08 do not use dpkg to change deb arch when crosscompiling 2017-07-25 13:47:50 +02:00
Marcus Georgi 3751fd3587 prepend the non-travis version with a number
- otherwise the built deb can't be installed
2017-07-19 14:57:22 +02:00
Olivier Martin 8e159b683d Merge pull request #32 from mweal-ed/get_uuid_from_handle
get_uuid_from_handle returns wrong uuid #30 fix
2017-07-12 17:39:58 +02:00
mikew-ed 6332cb807c get_uuid_from_handle returns wrong uuid #30 fix 2017-07-10 07:35:50 -07:00
Olivier Martin d3ca083826 README.md: Added latest binaries 2017-07-02 17:22:42 +02:00
Olivier Martin a8ff524171 travis-ci: Fixed deployment script 2017-07-02 16:23:53 +02:00
Olivier Martin 6361b818e5 Debian: Force Bluez version in package dependency 2017-07-02 15:44:19 +02:00
Olivier Martin c890f64dd9 dbus: Added support for Bluez DBus API v5.40 2017-07-02 15:36:09 +02:00
Olivier Martin 2e88aec8e1 Initial travis-ci support 2017-07-02 15:01:31 +02:00
Olivier Martin f7a5ced9d5 Merge pull request #23 from kinemic/usrlib
include /usr/lib in link directories when cross compiling
2017-06-02 13:29:48 +02:00
Marcus Georgi a5df534400 include /usr/lib in link directories when cross compiling
- was necessary on one of our machines, otherwise libglib-2.0 and others were
  not found during linking
2017-06-02 11:57:17 +02:00
Olivier Martin 7c40bad040 Merge pull request #21 from kinemic/master
Merge "use relative paths referencing bluez lib"
2017-06-02 11:12:29 +02:00
Marcus Georgi 6d90fa4d48 don't mix C and CXX Flags in CMake
- otherwise clang will report error:
   invalid argument '-std=c++11' not allowed with 'C/ObjC'
2017-06-01 10:16:20 +02:00
Marcus Georgi ecc627cb8a use relative paths referencing bluez lib
- otherwise includes won't work when used as a subdir in other projects
2017-06-01 10:07:45 +02:00
Olivier Martin 0ee021f531 Fixed build for Bluez v4.101 2017-03-17 11:35:13 +01:00
Olivier Martin a40b8f9724 Select gattlib backend (bluez code or DBus API) following Bluez version 2017-03-17 11:20:08 +01:00
Olivier Martin c702d74b23 examples/ble_scan: Ensure we disconnect on error 2017-03-17 11:20:08 +01:00
Olivier Martin cfe5613d0d gattlib.h: Added 'const' to buffer for 'gattlib_write_char_by_(uuid|handle)' 2017-03-17 11:20:08 +01:00
Olivier Martin beed53a6ba gattlib.h: Changed prototype of 'gattlib_read_char_by_uuid' 2017-03-17 11:20:08 +01:00
Olivier Martin 80f9884ae0 gattlib.h: Introduced CREATE_UUID16() 2017-03-17 11:20:08 +01:00
Olivier Martin d0b18d5409 examples: Demonstrate gattlib notification API 2017-03-17 11:20:08 +01:00
Olivier Martin 4dde0c3698 gattlib.h: Introduced gattlib_notification_(start|stop) 2017-03-17 11:20:08 +01:00
Olivier Martin 5391388201 gattlib.h: Pass 'uuid' instead of 'handle' to 'gattlib_event_handler_t' 2017-03-17 11:20:08 +01:00
Olivier Martin 1655e8c329 gattlib.h: Hide implementation specific attributes in gatt_connection_t.context 2017-03-17 11:20:08 +01:00
Olivier Martin ee2fabaf3f Introduced 'gattlib_write_char_by_uuid' 2017-03-17 11:18:59 +01:00
Olivier Martin 74972ae011 Move UUID API to gattlib_common.c 2017-03-17 11:18:59 +01:00
Olivier Martin e880df8e01 gattlib: Added support for adapter to enable/disable scanning 2017-03-17 11:18:58 +01:00
Olivier Martin d998e0072a dbus: Make gattlib based on D-Bus 2017-03-17 11:18:55 +01:00
Olivier Martin 076067a2d7 include/gattlib.h: Remove dependency on glib.h 2017-03-14 12:51:33 +01:00
Olivier Martin ebe4e57591 Move bluez specific files to 'bluez/' directory 2017-03-14 12:51:33 +01:00
Olivier Martin 6a083a8496 examples: Use 'gattlib' pkg-config to build the examples 2017-03-14 12:17:02 +01:00
Robert-B 5b76fada47 older compiler - do not use for loops with variable decalaration 2017-03-14 12:02:19 +01:00
Olivier Martin 15ab7a84d2 Merge pull request #14 from kinemic/master
gattlib: added extern "C" {} around header
2017-03-01 12:41:08 +01:00
Jonas Böer 1434b741ec gattlib: added extern "C" {} around header 2017-03-01 12:28:36 +01:00
Olivier Martin 7417102e12 examples: Adding a new example that demonstrates BLE Nordic UART Service (NUS) 2017-02-26 16:14:17 +01:00
Olivier Martin 180f7dff54 src: Fixed data length for Notify and Indicator handler 2017-02-26 16:08:51 +01:00
Olivier Martin e11618bdeb example/read_write: Implement 'write' using characteristic's UUID 2017-02-22 12:17:53 +01:00
Olivier Martin 4ab4cddfba src/gattlib: Fixed 'gattlib_read_char_by_uuid_async()' returned error 2017-02-22 12:04:54 +01:00
Olivier Martin dfba6f53ec src/gattlib: Fixed 'gattlib_uuid_to_string()' to return the entire UUID 2017-02-22 12:04:23 +01:00
Olivier Martin ecad887c2e gattlib: Introduced 'gattlib_uuid_cmp()' 2017-02-22 12:02:47 +01:00
Olivier Martin 698561a25a README.md: Clean example code for notification printf() 2017-02-22 12:02:01 +01:00
Olivier Martin 07a4e011da bluez(4|5): Fixed ambiguity with variable names 2017-02-18 17:38:36 +01:00
Olivier Martin ed3ff0627f src/gattlib_connect: Prevent Glib warning
Fix warning as explained in this thread: http://www.spinics.net/lists/linux-bluetooth/msg67617.html
2017-02-18 17:13:35 +01:00
Olivier Martin a5d4655922 Merge pull request #9 from oliviermartin/master
bluez5: Fixed for undefined 'bswap_128'
2017-02-08 23:07:11 +01:00
Olivier Martin 671267e266 bluez5: Fixed for undefined 'bswap_128'
'bswap_128' has only be introduced in Bluez 5.29.
We use 'lib/bluetooth.h' instead of '/usr/include/bluetooth/bluetooth.h'
2017-02-08 22:47:23 +01:00
Olivier Martin 45e7a8066c Increase the level of warnings and fix few of them 2017-02-08 19:16:51 +01:00
Olivier Martin bd5d8daa92 examples/gattool: Make the code compliant with C90 2017-02-08 19:16:51 +01:00
Olivier Martin 4a0b3903fb Merge pull request #8 from oliviermartin/master
gattlib.h: Removed dependency on internal Bluez headers
2017-02-08 18:40:22 +01:00
Olivier Martin ece340a193 gattlib.h: Removed dependency on internal Bluez headers 2017-02-08 18:36:51 +01:00
Olivier Martin 21541e755c README.md: Added Bluez5 support 2017-01-31 22:42:57 +01:00
Olivier Martin 751ea82bda bluez5: Replaced 'g_io_add_watch_full' by 'gattlib_watch_connection_full' 2017-01-31 22:38:55 +01:00
Olivier Martin f1aa5b0ede examples/gatttool: Added support for Bluez5 2017-01-31 22:38:55 +01:00
Olivier Martin 98eca71225 examples/ble_scan: Add support for Bluez5 2017-01-31 22:38:55 +01:00
Olivier Martin f152b8d04e bluez5/btio: Added option BT_IO_OPT_TIMEOUT 2017-01-31 22:38:55 +01:00
Olivier Martin e802d4ab50 bluez5: Ported to Gattlib 2017-01-31 22:38:55 +01:00
Olivier Martin 9c43746ec6 gattlib: Added support for Bluez 4 and 5 2017-01-31 22:38:54 +01:00
Olivier Martin 48f3ab4e5f CMakeLists.txt: Check if we are building for Bluez 4 or 5 2017-01-31 22:38:54 +01:00
Olivier Martin 58c547fe9e Added Bluez5 support 2017-01-31 22:38:54 +01:00
Olivier Martin 1e68512f3b Renamed 'bluez' into 'bluez4' 2017-01-30 22:33:22 +01:00
Olivier Martin 9c7382b215 Reduces compilation warnings 2017-01-30 11:52:54 +01:00
Olivier Martin 7f32f5c346 README.md: Add the list of dependencies 2017-01-30 11:52:12 +01:00
Olivier Martin 3bce76b270 Merge pull request #5 from eidheim/master
Fixes #1: corrected bluetooth/uuid.h includes. Also added missing .gi…
2017-01-28 15:15:26 +01:00
eidheim 427bad8904 Fixes #1: corrected bluetooth/uuid.h includes. Also added missing .gitignore file. 2017-01-27 14:47:39 +01:00
Olivier Martin 411dc8633f Prepare new v0.2 release 2016-05-02 19:20:41 +01:00
Olivier Martin d9e67b829b bluez/log.c: Replace 'VERSION' by 'BLUEZ_VERSION_MAJOR.BLUEZ_VERSION_MINOR' 2016-05-02 19:17:06 +01:00
Olivier Martin 4db0060a3b src/gattlib_connect.c: Set the timeout to avoid waiting 20 seconds if the connection is not setup 2016-05-02 19:16:29 +01:00
Olivier Martin f9adbe5b09 Added 'ble_scan' example 2016-05-02 19:16:29 +01:00
Olivier Martin ee58e4cb64 bluez/btio: Added option BT_IO_OPT_TIMEOUT 2016-05-02 19:16:28 +01:00
Olivier Martin 36ff478c3e CMake: Added cross-compilation support 2016-05-02 19:16:28 +01:00
Olivier Martin 69da222e3a Fix Gattlib with Bluez v4.99 2016-05-02 09:41:02 +01:00
Olivier Martin 36a267bfa7 Added Bluez pkg-config and expose its version to the build system 2016-05-02 09:41:02 +01:00
Olivier Martin db5ffbf47d README.md: Added 'Known limitations' 2016-04-29 10:30:09 +01:00
Olivier Martin 15defc8f7d example/gatttool: Updated notification_handler registration 2016-04-28 23:44:49 +01:00
Olivier Martin 183bf5015a gattlib: Added connection specific 'user_data' parameter to notification/indication handlers
The notification/indication handlers are also now connection specific.
2016-04-28 23:44:40 +01:00
Olivier Martin c5622cc385 gattlib_connect: Zero gatt_connection_t at its initialization 2016-04-28 23:44:33 +01:00
Olivier Martin ccea65dbae CMakeLists.txt: Fixed package description summary 2016-04-28 18:56:49 +01:00
Olivier Martin 0c77aec7c9 README.md: Added link to release packages 2016-04-28 12:08:48 +01:00
218 changed files with 63299 additions and 1115 deletions

118
.github/workflows/github-actions.yml vendored Normal file
View File

@ -0,0 +1,118 @@
name: gattlib
on: [push]
jobs:
build-debug:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt install libbluetooth-dev
- run: mkdir build && pushd build && cmake -DCMAKE_BUILD_TYPE=Debug -DGATTLIB_PYTHON_INTERFACE=ON .. && make
build-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt install libbluetooth-dev doxygen
- run: mkdir build && pushd build && cmake -DCMAKE_BUILD_TYPE=Release -DGATTLIB_BUILD_DOCS=ON -DGATTLIB_PYTHON_INTERFACE=ON .. && make
- run: pushd build && cpack ..
if: startsWith(github.ref, 'refs/tags/')
env:
PACKAGE_VERSION: '${{github.ref_name}}'
- name: Archive Distribution packages
uses: actions/upload-artifact@v4
if: startsWith(github.ref, 'refs/tags/')
with:
name: distribution-packages
path: |
build/*.deb
build/*.rpm
build/*.zip
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
build/*.deb
build/*.rpm
build/*.zip
build-release-force-dbus:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt install libbluetooth-dev
- run: mkdir build && pushd build && cmake -DGATTLIB_FORCE_DBUS=TRUE -DCMAKE_BUILD_TYPE=Release -DGATTLIB_PYTHON_INTERFACE=ON .. && make
build-release-without-python-support:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt install libbluetooth-dev
- run: mkdir build && pushd build && cmake -DCMAKE_BUILD_TYPE=Release -DGATTLIB_PYTHON_INTERFACE=OFF .. && make
test-pylint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python3 -m pip install PyGObject>=3.44.0
- run: python3 -m pip install pylint
- run: python3 -m pylint gattlib-py/gattlib --rcfile gattlib-py/.pylintrc
generate-python-binary-packages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt install -y libbluetooth-dev
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
- run: ./ci/generate-python-package.sh
if: startsWith(github.ref, 'refs/tags/')
env:
CIBW_BEFORE_BUILD_LINUX: "sh ci/install-bluez.sh"
GATTLIB_PY_VERSION: '${{github.ref_name}}'
CIBW_ENVIRONMENT_PASS_LINUX: "GATTLIB_PY_VERSION"
#TODO: To support 'musllinux', we need to replace 'yum install' by 'apk install' - and detect which platform we are
CIBW_SKIP: "*-musllinux_*"
- run: ./ci/generate-python-package.sh
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}
env:
CIBW_BEFORE_BUILD_LINUX: "sh ci/install-bluez.sh"
GATTLIB_PY_VERSION: '0.0.1'
CIBW_ENVIRONMENT_PASS_LINUX: "GATTLIB_PY_VERSION"
#TODO: To support 'musllinux', we need to replace 'yum install' by 'apk install' - and detect which platform we are
CIBW_SKIP: "*-musllinux_*"
- name: Archive Python packages
uses: actions/upload-artifact@v4
with:
name: python-binary-packages
path: dist/*
# publish-python-packages:
# needs:
# - generate-python-binary-packages
# runs-on: ubuntu-latest
# steps:
# - uses: actions/download-artifact@master
# - run: ls *
publish-to-pypi:
name: >-
Publish Python 🐍 distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- generate-python-binary-packages
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/gattlib-py # Replace <package-name> with your PyPI project name
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- uses: actions/download-artifact@master
- run: |
mkdir dist/
mv python-binary-packages/*.tar.gz dist/
mv python-binary-packages/*.whl dist/
ls dist/*
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# IDE files
.vscode/
# Generated files
build
__pycache__
MANIFEST.in
dist
gattlib-py/gattlib_py.egg-info/

111
.travis.yml Normal file
View File

@ -0,0 +1,111 @@
language: c
compiler:
- gcc
#Disable Clang for now until we support ARM cross-toolchain - clang
dist: xenial
addons:
apt:
packages:
- gcc-aarch64-linux-gnu
- g++-aarch64-linux-gnu
- libbluetooth-dev
- rpm
- python3-pip
- python3-setuptools
- doxygen
install:
- |
if [ ! -f $PWD/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf ]; then
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz
tar xf gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz
fi
- pip3 install --upgrade cross-sysroot
- pip3 install Sphinx
- pip3 install breathe
script:
# Build default Gattlib - Debug
- mkdir build-debug && pushd build-debug
- cmake -DCMAKE_BUILD_TYPE=Debug .. && make
- popd
# Build and Package default Gattlib - Release
- mkdir build-release && pushd build-release
- cmake -DCMAKE_BUILD_TYPE=Release .. && make && cpack ..
- popd
# Build Gattlib with DBus support - Debug
- mkdir build-dbus-debug && pushd build-dbus-debug
- cmake -DGATTLIB_FORCE_DBUS=TRUE -DCMAKE_BUILD_TYPE=Debug .. && make
- popd
# Build and Package Gattlib with DBus support - Release
- mkdir build-dbus-release && pushd build-dbus-release
- cmake -DGATTLIB_FORCE_DBUS=TRUE -DCMAKE_BUILD_TYPE=Release .. && make && cpack ..
- popd
#
# Setup build for ARM 32-bit
#
# Set environment variables
- export SYSROOT=$PWD/debian-stable-arm
- export CROSS_COMPILE=$PWD/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
# Ensure folder is empty
- rm -Rf $PWD/debian-stable-arm/*
- cross-sysroot --distribution debian --distribution-version stable --architecture armhf --cross-gcc ${CROSS_COMPILE}gcc --build-root $PWD/debian-stable-arm requirements.dep
# Build and Package Gattlib with DBus support - Release - ARM32
- mkdir build-dbus-release-arm32 && pushd build-dbus-release-arm32
- cmake -DGATTLIB_FORCE_DBUS=TRUE -DCMAKE_BUILD_TYPE=Release .. && make VERBOSE=1 && cpack ..
- popd
#
# Setup build for ARM 64-bit
#
# Ensure folder is empty
- rm -Rf $PWD/debian-stable-arm64/*
- cross-sysroot --distribution debian --distribution-version stable --architecture arm64 --build-root $PWD/debian-stable-arm64 requirements.dep
# Set environment variables
- export SYSROOT=$PWD/debian-stable-arm64
- export CROSS_COMPILE=aarch64-linux-gnu-
# Build and Package Gattlib with DBus support - Release - ARM64
- mkdir build-dbus-release-arm64 && pushd build-dbus-release-arm64
- cmake -DGATTLIB_FORCE_DBUS=TRUE -DCMAKE_BUILD_TYPE=Release .. && make VERBOSE=1 && cpack ..
- popd
after_success:
- if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then ./update-dev-tag.sh; fi
before_deploy:
# Create directory to store the artifacts we want to deploy
- mkdir artifacts
# Copy packages to artifacts
- cp build-release/gattlib_*_x86_64.deb artifacts/
- cp build-release/gattlib_*_x86_64.rpm artifacts/
- cp build-release/gattlib_*_x86_64.zip artifacts/
# Copy DBUS packages to artifacts
- for f in build-dbus-release/gattlib_*; do cp "$f" "`echo $f | sed 's/build-dbus-release\/gattlib_/artifacts\/gattlib_dbus_/'`"; done
# Copy DBUS ARM packages to artifacts
- cp build-dbus-release-arm32/gattlib_*_armhf.deb artifacts/
- cp build-dbus-release-arm32/gattlib_*_armhf.zip artifacts/
# Copy DBUS ARM64 packages to artifacts
- cp build-dbus-release-arm64/gattlib_*_arm64.deb artifacts/
- cp build-dbus-release-arm64/gattlib_*_arm64.zip artifacts/
deploy:
provider: releases
api-key: ${GITHUB_OAUTH_TOKEN}
file_glob: true
file: artifacts/*
skip_cleanup: true
overwrite: true
on:
tags: true

View File

@ -1,90 +1,178 @@
#
# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
#
# GattLib - GATT Library
#
# Copyright (C) 2016 Olivier Martin <olivier@labapart.org>
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Copyright (c) 2016-2024, Olivier Martin <olivier@labapart.org>
#
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 3.22.0)
# Add Cross-Compilation support when the environment variables
# CROSS_COMPILE and SYSROOT are defined
include(CrossCompilation.cmake)
project(gattlib)
#TODO: Gattlib examples must be ported to new gattlib_connect()
option(GATTLIB_BUILD_EXAMPLES "Build GattLib examples" YES)
option(GATTLIB_SHARED_LIB "Build GattLib as a shared library" YES)
option(GATTLIB_BUILD_DOCS "Build GattLib docs" NO)
option(GATTLIB_PYTHON_INTERFACE "Build GattLib Python Interface" NO)
option(GATTLIB_ENABLE_ADDRESS_SANITIZER "Enable address sanitizer" NO)
find_package(PkgConfig REQUIRED)
find_package(Doxygen)
include_directories(include bluez/attrib bluez/btio bluez/src)
# Define 'Debug' as the default build type
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# Bluez specific files
set(gattlib_SRCS bluez/attrib/att.c
bluez/attrib/gatt.c
bluez/attrib/gattrib.c
bluez/btio/btio.c
bluez/lib/bluetooth.c
bluez/lib/hci.c
bluez/lib/sdp.c
bluez/lib/uuid.c
bluez/src/log.c)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG)
endif()
add_definitions(-DVERSION="4.101")
# Show all the warnings
if (MSVC)
# warning level 4
add_compile_options(/W4)
else()
# additional warnings
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-variadic-macros)
endif()
# Add stack protector
add_compile_options(-fstack-protector-strong)
# Gattlib files
list(APPEND gattlib_SRCS src/gattlib_connect.c
src/gattlib_discover.c
src/gattlib_read_write.c)
if (GATTLIB_ENABLE_ADDRESS_SANITIZER)
add_compile_options(-fsanitize=address -fsanitize=bounds -fsanitize=undefined -fsanitize-recover=address)
add_link_options(-fsanitize=address -fsanitize=bounds -fsanitize=undefined -fsanitize-recover=address -static-libasan)
endif()
# Added Glib support
pkg_search_module(GLIB REQUIRED glib-2.0)
include_directories(${GLIB_INCLUDE_DIRS})
list(APPEND gattlib_LIBS ${GLIB_LIBRARIES})
# Expose 'gattlib.h' to all sub-directories
include_directories(include)
# gattlib
add_library(gattlib SHARED ${gattlib_SRCS})
target_link_libraries(gattlib ${gattlib_LIBS})
if (NOT BLUEZ_VERSION)
# Check version of Bluez to know which backend we use (ie: Bluez code or DBus)
pkg_search_module(BLUEZ bluez)
if (NOT BLUEZ_FOUND)
message(FATAL_ERROR "Please install 'libbluetooth-dev'")
endif()
endif()
# Examples
add_subdirectory(examples/discover)
add_subdirectory(examples/read_write)
add_subdirectory(examples/gatttool)
# Extract Bluez version
string(REPLACE "." ";" BLUEZ_VERSIONS "${BLUEZ_VERSION}")
list(GET BLUEZ_VERSIONS 0 BLUEZ_VERSION_MAJOR)
list(GET BLUEZ_VERSIONS 1 BLUEZ_VERSION_MINOR)
add_definitions(-DBLUEZ_VERSION_MAJOR=${BLUEZ_VERSION_MAJOR} -DBLUEZ_VERSION_MINOR=${BLUEZ_VERSION_MINOR})
set(GATTLIB_FORCE_DBUS OFF CACHE BOOL "Build gattlib with D-Bus support on Bluez version < v5.42")
if (BLUEZ_VERSION_MAJOR LESS 5)
set(GATTLIB_DBUS FALSE)
elseif (BLUEZ_VERSION_MINOR LESS 42)
if (GATTLIB_FORCE_DBUS)
set(GATTLIB_DBUS TRUE)
else()
set(GATTLIB_DBUS FALSE)
endif()
else()
set(GATTLIB_DBUS TRUE)
endif()
# With 'syslog' backend, we enable all logs (ie: up to level debug) and we leave the
# application to set the level using 'setlogmask()'
set(GATTLIB_LOG_LEVEL 3 CACHE STRING "Define the minimum logging level for Gattlib (0=error, 1=warning, 2=info, 3=debug)")
set(GATTLIB_LOG_BACKEND syslog CACHE STRING "Define logging backend: syslog, printf, python (default: syslog)")
if (GATTLIB_DBUS)
# Build dbus-based gattlib
add_subdirectory(dbus)
# Add the Gattlib build directory for the examples
link_directories(${PROJECT_BINARY_DIR}/dbus)
else()
# Build bluez-based gattlib
add_subdirectory(bluez)
# Add the Gattlib build directory for the examples
link_directories(${PROJECT_BINARY_DIR}/bluez)
endif()
if(GATTLIB_BUILD_DOCS)
if (NOT Doxygen_FOUND)
message(FATAL_ERROR "Gattlib documentation requires Doxygen. Or disable doc generation with '-DGATTLIB_BUILD_DOCS=OFF'")
endif()
add_subdirectory(docs)
endif()
# Generate pkg-config file before building the examples
configure_file(dbus/gattlib.pc.in ${PROJECT_BINARY_DIR}/gattlib.pc @ONLY)
# Add the build directory to PKG_CONFIG_PATH
set(ENV{PKG_CONFIG_PATH} "${PROJECT_BINARY_DIR}:$ENV{PKG_CONFIG_PATH}")
if(GATTLIB_BUILD_EXAMPLES)
# Examples
add_subdirectory(examples/advertisement_data)
add_subdirectory(examples/ble_scan)
add_subdirectory(examples/discover)
add_subdirectory(examples/find_eddystone)
add_subdirectory(examples/read_write)
#add_subdirectory(examples/read_write_memory)
add_subdirectory(examples/notification)
#add_subdirectory(examples/nordic_uart)
add_subdirectory(tests/test_continuous_connection)
# Some examples require Bluez code and other DBus support
if (NOT GATTLIB_DBUS)
add_subdirectory(examples/gatttool)
endif()
endif()
#
# Packaging
#
set(CPACK_PACKAGE_INSTALL_DIRECTORY /usr CACHE STRING "Install directory (default: /usr).")
set(CPACK_PACKAGE_VERSION 0.1)
if (ENV{PACKAGE_VERSION} AND (NOT "ENV{PACKAGE_VERSION}" STREQUAL "dev"))
message("Package Gattlib for tagged version $ENV{PACKAGE_VERSION}")
# Transform 'v0.3' into '0.3' and 'v0.3-rc1' into '0.3-rc1'
string(REGEX REPLACE "v([0-9]+).([0-9]+)(.*)" "\\1.\\2\\3" CPACK_PACKAGE_VERSION $ENV{PACKAGE_VERSION})
else()
set(CPACK_PACKAGE_VERSION 0.4-dev)
message("Package Gattlib for development version $ENV{CPACK_PACKAGE_VERSION}")
endif()
set(CPACK_PACKAGE_CONTACT "Olivier Martin <olivier@labapart.com>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Library to access GATT information from Bluetooth Low Power devices")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Library to access GATT information from Bluetooth Low Energy (BLE) devices")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_PACKAGE_ARCHITECTURE}")
#
# Debian package
# Debian, RPM and ZIP packages
#
set(CPACK_GENERATOR "DEB;RPM;ZIP")
if (CMAKE_SYSROOT)
# CPack does like RPM package in a cross-toolchain context
set(CPACK_GENERATOR "DEB;ZIP")
else()
set(CPACK_GENERATOR "DEB;RPM;ZIP")
endif()
if (NOT CMAKE_SYSROOT)
# Detect platform architecture to use it for the Debian package
execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_QUIET)
execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_QUIET)
endif()
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libglib2.0-0")
# Bluez DBus API changed from v5.40
if (GATTLIB_DBUS AND (BLUEZ_VERSION_MAJOR EQUAL 5) AND (BLUEZ_VERSION_MINOR GREATER 39))
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, bluez (>= 5.40)")
endif()
#
# List of file to install
#
configure_file(gattlib.pc.in gattlib.pc @ONLY)
install(TARGETS gattlib LIBRARY DESTINATION lib)
install(FILES include/gattlib.h DESTINATION include)
install(FILES ${PROJECT_BINARY_DIR}/gattlib.pc DESTINATION lib/pkgconfig)
include(GNUInstallDirs)
install(FILES include/gattlib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${PROJECT_BINARY_DIR}/gattlib.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
include(CPack)

95
CrossCompilation.cmake Normal file
View File

@ -0,0 +1,95 @@
#
# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
#
# Copyright (c) 2016-2021, Olivier Martin <olivier@labapart.org>
#
#
# Version: 1.0
# Repository: https://gist.github.com/oliviermartin/
# Description:
#
# Add Cross-Compilation support when the environment variables
# CROSS_COMPILE and SYSROOT are defined
#
# Check required environment variables
#
if ("$ENV{CROSS_COMPILE}" STREQUAL "")
# Cross compilation is not needed
# We still set CPACK_PACKAGE_ARCHITECTURE
if (NOT DEFINED CPACK_PACKAGE_ARCHITECTURE)
execute_process(COMMAND uname -m OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
return()
endif()
if ("$ENV{SYSROOT}" STREQUAL "")
message(WARNING "Environment variable SYSROOT is not defined.")
endif()
# Trigger cross-compilation in CMake
set(CMAKE_SYSTEM_NAME Linux)
# Specify the cross compiler
set(CMAKE_C_COMPILER $ENV{CROSS_COMPILE}gcc)
set(CMAKE_CXX_COMPILER $ENV{CROSS_COMPILE}g++)
# Specify the target environment
set(CMAKE_FIND_ROOT_PATH $ENV{SYSROOT})
set(CMAKE_SYSROOT $ENV{SYSROOT})
# Retrieve the machine supported by the toolchain
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE TOOLCHAIN_MACHINE OUTPUT_STRIP_TRAILING_WHITESPACE)
# Add '--sysroot' to the compiler flags
set(ENV{CFLAGS} "--sysroot=$ENV{SYSROOT} $ENV{CFLAGS}")
# Add '-rpath' to the linker flags
set(ENV{LDFLAGS} "--sysroot=$ENV{SYSROOT} -Wl,-rpath,$ENV{SYSROOT}/lib/${TOOLCHAIN_MACHINE} $ENV{LDFLAGS}")
#
# Configure pkg-config for cross-compilation
#
if(IS_DIRECTORY "$ENV{SYSROOT}/usr/lib/pkgconfig")
set(ENV{PKG_CONFIG_PATH} $ENV{SYSROOT}/usr/lib/pkgconfig)
endif()
if(IS_DIRECTORY "$ENV{SYSROOT}/usr/lib/${TOOLCHAIN_MACHINE}/pkgconfig")
set(ENV{PKG_CONFIG_PATH} $ENV{SYSROOT}/usr/lib/${TOOLCHAIN_MACHINE}/pkgconfig)
endif()
if (NOT "$ENV{PKG_CONFIG_PATH}" STREQUAL "")
set(ENV{PKG_CONFIG_SYSROOT_DIR} $ENV{SYSROOT})
# Don't strip -I/usr/include out of cflags
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1)
# Don't strip -L/usr/lib out of libs
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 1)
endif()
# Workaround as some pkgconfig file forgot to add the architecture specific include folder
# such as openssl.pc
include_directories($ENV{SYSROOT}/usr/include $ENV{SYSROOT}/usr/include/${TOOLCHAIN_MACHINE})
# Workaround as some library are installed in $ENV{SYSROOT}/lib/${TOOLCHAIN_MACHINE}
# such as libpcre.so (required by glib-2.0)
link_directories($ENV{SYSROOT}/lib/${TOOLCHAIN_MACHINE})
link_directories($ENV{SYSROOT}/usr/lib/${TOOLCHAIN_MACHINE})
# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
#
# Set architecture for CPack
#
if ("${TOOLCHAIN_MACHINE}" STREQUAL "arm-linux-gnueabihf")
set(CPACK_PACKAGE_ARCHITECTURE armhf)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE armhf)
set(CPACK_RPM_PACKAGE_ARCHITECTURE armv7hl)
endif()
if ("${TOOLCHAIN_MACHINE}" STREQUAL "aarch64-linux-gnu")
set(CPACK_PACKAGE_ARCHITECTURE arm64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)
set(CPACK_RPM_PACKAGE_ARCHITECTURE aarch64)
endif()

100
README.md
View File

@ -1,14 +1,25 @@
GattLib is a library used to access Generic Attribute Profile (GATT) protocol of BLE (Bluetooth Low Energy) devices.
It has been introduced to allow to build applications that could easily communicate with BLE devices.
It is based on Bluez 4.101 GATT code (prior to Bluez D-BUS API).
It supports Bluez v4 and v5.
It has been introduced to allow to build applications hosted on platform with a version of Bluez prior to v5.x that could easily communicate with BLE devices.
Latest GattLib Release packages
===============================
Potentially, D-BUS API could also be added to GattLib to provide an abstraction layer between different versions of BlueZ.
* The latest release can be found [here](https://github.com/labapart/gattlib/releases/latest). It contains:
- Prebuilt Debian, RPM and ZIP packages for x86_64 and Bluez v5.x
- Packages for ARM 32bit and 64bit would have to be built by the developer - see section [Package GattLib](#package-gattlib).
- Prebuilt Python packages are available on [Pypi repository](https://pypi.org/project/gattlib-py/).
Build GattLib
=============
* Gattlib requires the following packages: `libbluetooth-dev`, `libreadline-dev`.
On Debian based system (such as Ubuntu), you can installed these packages with the
following command: `sudo apt install libbluetooth-dev libreadline-dev`
```
cd <gattlib-src-root>
mkdir build && cd build
@ -16,6 +27,42 @@ cmake ..
make
```
* Gattlib can also be built for a specific version of Bluez by specifying its version at build time:
```
mkdir build && cd build
cmake -DBLUEZ_VERSION=5.50 ..
make
```
* **On Bluez versions prior to v5.42**, gattlib used Bluez source code while it uses D-Bus API
from v5.42. D-Bus API can be used on version prior to Bluez v5.42 by using the CMake flag `-DGATTLIB_FORCE_DBUS=TRUE`:
```
mkdir build && cd build
cmake -DGATTLIB_FORCE_DBUS=TRUE ..
make
```
### Cross-Compilation
To cross-compile GattLib, you must provide the following environment variables:
- `CROSS_COMPILE`: prefix of your cross-compile toolchain
- `SYSROOT`: an existing system root that contains the libraries and include files required by your application
Example:
```
cd <gattlib-src-root>
mkdir build && cd build
export CROSS_COMPILE=~/Toolchains/gcc-linaro-4.9-2015.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
export SYSROOT=~/Distributions/debian-wheezy
cmake ..
make
```
Package GattLib
===============
@ -31,24 +78,40 @@ To change the install directory to `/usr/local` run: `cpack -DCPACK_PACKAGE_INST
Examples
========
* Demonstrate discovering of primary services and characteristics:
* [Demonstrate discovering of primary services and characteristics](/examples/discover/discover.c):
./examples/discover/discover 78:A5:04:22:45:4F
* Demonstrate characteristic read/write:
* [Demonstrate characteristic read/write](/examples/read_write/read_write.c):
./examples/read_write/read_write 78:A5:04:22:45:4F read 00002a29-0000-1000-8000-00805f9b34fb
./examples/read_write/read_write 78:A5:04:22:45:4F write 00002a6b-0000-1000-8000-00805f9b34fb 0x1234
**Note:** `examples/gatttool` has been partially ported to gattlib. There are two reasons the laziness
* [Demonstrate BLE scanning and connection](/examples/ble_scan/ble_scan.c):
./examples/ble_scan/ble_scan
* [Demonstrate GATT notification using GATT Battery service](/examples/notification/notification.c):
./examples/notification/notification
* [Demonstrate GATT Write Without Response](/examples/nordic_uart/nordic_uart.c):
./examples/nordic_uart/nordic_uart
**Note 1:** [The example 'read/write mem'](/examples/read_write_mem/read_write.c) is similar to
[the example 'read/write'](/examples/read_write/read_write.c) except a GLib loop is used to allows
the memory to be freed by Glib. Without this loop, some memory could be locked.
**Note 2:** `examples/gatttool` has been partially ported to gattlib. There are two reasons: the laziness
(some of the GATT functions could be replaced by their gattlib equivalent) and the completeness (there
are still some missing functions in gattlib).
* Notification is also supported. Example:
```
void notification_cb(uint16_t handle, const uint8_t* data, size_t data_length) {
printf("Notification on handle 0x%02x : ", handle);
void notification_cb(uint16_t handle, const uint8_t* data, size_t data_length, void* user_data) {
printf("Notification on handle 0x%02x\n", handle);
}
main() {
@ -58,13 +121,30 @@ main() {
// Enable Status Notification
gattlib_write_char_by_handle(connection, status_handle + 1, &enable_notification, sizeof(enable_notification));
// Register notification handler
gattlib_register_notification(notification_cb);
gattlib_register_notification(connection, notification_cb, NULL);
}
```
Known limitations
-----------------
* **gattlib and BLE**: gattlib requires at least Bluez v4.100 to work with Bluetooth Low Energy (BLE) devices. Bluez does not allow to connect to BLE device prior to this version. But gattlib can still work with Bluetooth Classic (BR/EDR) prior to Bluez v4.100.
Debian 7 "Wheezy" (supported until 31st of May 2018) relies on Bluez v4.99 while Debian 8 "Jessie" (supported until April/May 2020) uses Bluez v5.23.
TODO List
=========
- Complete `examples/gatttool` port to GattLib to demonstrate the completeness of GattLib.
- Support Bluez v5.x GATT D-BUS API in addition to the current Bluez v4.101 support.
- Remove GLib dependencies to GattLib (mainly replacing GLib IO Channels by Unix Domain Socket).
License
=======
Gattlib with Bluez Legacy support (for Bluez v4) has a GPL v2.0 or later license.
While Gattlib for recent version of Bluez (v5.40+) has a BSD-3-Clause license - except `dbus/bluez5/lib/uuid.c`
and `dbus/bluez5/lib/uuid.h` that have a GPL v2.0 or later license.
Support
=======
Commercial Support can be obtained through [Lab A Part](https://labapart.com). Please contact us: [https://labapart.com/about/](https://labapart.com/about/).

120
bluez/CMakeLists.txt Normal file
View File

@ -0,0 +1,120 @@
#
# GattLib - GATT Library
#
# Copyright (C) 2016-2024 Olivier Martin <olivier@labapart.org>
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
cmake_minimum_required(VERSION 3.22.0)
find_package(PkgConfig REQUIRED)
message("Build gattlib for Bluez v${BLUEZ_VERSION_MAJOR}.${BLUEZ_VERSION_MINOR}")
set(bluez4_DIR bluez4)
set(bluez5_DIR bluez5)
# Bluez specific files
set(bluez4_SRCS ${bluez4_DIR}/attrib/att.c
${bluez4_DIR}/attrib/gatt.c
${bluez4_DIR}/attrib/gattrib.c
${bluez4_DIR}/btio/btio.c
${bluez4_DIR}/lib/bluetooth.c
${bluez4_DIR}/lib/hci.c
${bluez4_DIR}/lib/sdp.c
${bluez4_DIR}/lib/uuid.c
${bluez4_DIR}/src/log.c)
set(bluez5_SRCS ${bluez5_DIR}/attrib/att.c
${bluez5_DIR}/attrib/gatt.c
${bluez5_DIR}/attrib/gattrib.c
${bluez5_DIR}/btio/btio.c
${bluez5_DIR}/lib/bluetooth.c
${bluez5_DIR}/lib/hci.c
${bluez5_DIR}/lib/sdp.c
${bluez5_DIR}/lib/uuid.c
${bluez5_DIR}/src/log.c
${bluez5_DIR}/src/shared/queue.c
${bluez5_DIR}/src/shared/util.c
${bluez5_DIR}/src/shared/mgmt.c
${bluez5_DIR}/src/shared/crypto.c
${bluez5_DIR}/src/shared/ecc.c
${bluez5_DIR}/src/shared/ringbuf.c
${bluez5_DIR}/src/shared/tester.c
${bluez5_DIR}/src/shared/hci.c
${bluez5_DIR}/src/shared/hci-crypto.c
${bluez5_DIR}/src/shared/hfp.c
${bluez5_DIR}/src/shared/uhid.c
${bluez5_DIR}/src/shared/pcap.c
${bluez5_DIR}/src/shared/btsnoop.c
${bluez5_DIR}/src/shared/ad.c
${bluez5_DIR}/src/shared/att.c
${bluez5_DIR}/src/shared/gatt-helpers.c
${bluez5_DIR}/src/shared/gatt-client.c
${bluez5_DIR}/src/shared/gatt-server.c
${bluez5_DIR}/src/shared/gatt-db.c
${bluez5_DIR}/src/shared/gap.c
${bluez5_DIR}/src/shared/io-glib.c
${bluez5_DIR}/src/shared/timeout-glib.c)
# Gattlib files
set(gattlib_SRCS gattlib_adapter.c
gattlib_connect.c
gattlib_discover.c
gattlib_read_write.c
${CMAKE_SOURCE_DIR}/common/gattlib_common.c
${CMAKE_SOURCE_DIR}/common/gattlib_eddystone.c
${CMAKE_SOURCE_DIR}/common/logging_backend/${GATTLIB_LOG_BACKEND}/gattlib_logging.c)
# Added Glib support
pkg_search_module(GLIB REQUIRED glib-2.0)
include_directories(${GLIB_INCLUDE_DIRS})
list(APPEND gattlib_LIBS ${GLIB_LDFLAGS})
# Added Bluetooth support
include_directories(${BLUEZ_INCLUDE_DIRS})
list(APPEND gattlib_LIBS ${BLUEZ_LDFLAGS})
include_directories(. ${CMAKE_SOURCE_DIR}/common)
if(BLUEZ_VERSION_MAJOR STREQUAL "4")
list(APPEND gattlib_SRCS ${bluez4_SRCS})
include_directories(${bluez4_DIR}/attrib ${bluez4_DIR}/btio ${bluez4_DIR}/src ${bluez4_DIR}/lib)
else()
list(APPEND gattlib_SRCS ${bluez5_SRCS})
include_directories(${bluez5_DIR} ${bluez5_DIR}/attrib ${bluez5_DIR}/btio ${bluez5_DIR}/lib)
add_definitions(-D_GNU_SOURCE)
endif()
# gattlib
target_compile_definitions(gattlib PUBLIC -DGATTLIB_LOG_LEVEL=${GATTLIB_LOG_LEVEL})
if (GATTLIB_LOG_BACKEND STREQUAL "syslog")
target_compile_definitions(gattlib PUBLIC -DGATTLIB_LOG_BACKEND_SYSLOG)
endif()
include(GNUInstallDirs)
if(GATTLIB_SHARED_LIB)
add_library(gattlib SHARED ${gattlib_SRCS})
target_link_libraries(gattlib ${gattlib_LIBS})
install(TARGETS gattlib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
else()
add_library(gattlib ${gattlib_SRCS})
target_include_directories(gattlib INTERFACE ../include)
target_link_libraries(gattlib ${gattlib_LIBS})
install(TARGETS gattlib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()

View File

@ -27,7 +27,7 @@
#include <stdlib.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
#include "uuid.h"
#include <glib.h>

View File

@ -29,7 +29,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <glib.h>
#include <bluetooth/uuid.h>
#include "uuid.h"
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

View File

@ -29,7 +29,7 @@
#include <stdio.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
#include "uuid.h"
#include "log.h"
#include "att.h"

View File

@ -65,6 +65,7 @@ struct set_opts {
uint8_t mode;
int flushable;
uint32_t priority;
int timeout;
};
struct connect {
@ -172,11 +173,27 @@ static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm,
}
static int l2cap_connect(int sock, const bdaddr_t *dst, uint8_t dst_type,
uint16_t psm, uint16_t cid)
uint16_t psm, uint16_t cid, uint16_t timeout)
{
int err;
struct sockaddr_l2 addr;
if (timeout > 0) {
struct timeval timeval;
timeval.tv_sec = timeout;
timeval.tv_usec = 0;
if (setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeval, sizeof(timeval)) < 0) {
fprintf(stderr, "l2cap_connect: Failed to setsockopt for receive timeout.\n");
return -1;
}
if (setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeval, sizeof(timeval)) < 0) {
fprintf(stderr, "l2cap_connect: Failed to setsockopt for sending timeout.\n");
return -1;
}
}
memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
bacpy(&addr.l2_bdaddr, dst);
@ -185,7 +202,14 @@ static int l2cap_connect(int sock, const bdaddr_t *dst, uint8_t dst_type,
else
addr.l2_psm = htobs(psm);
#if BLUEZ_VERSION < BLUEZ_VERSIONS(4, 100)
if (dst_type != BDADDR_BREDR) {
fprintf(stderr, "Require Bluez >= 4.100 to support BLE connections.\n");
return -1;
}
#else
addr.l2_bdaddr_type = dst_type;
#endif
err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
@ -592,6 +616,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
opts->flushable = -1;
opts->priority = 0;
opts->dst_type = BDADDR_BREDR;
opts->timeout = 0;
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
@ -653,6 +678,9 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
case BT_IO_OPT_PRIORITY:
opts->priority = va_arg(args, int);
break;
case BT_IO_OPT_TIMEOUT:
opts->timeout = va_arg(args, int);
break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@ -1238,12 +1266,12 @@ GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
switch (type) {
case BT_IO_L2RAW:
err = l2cap_connect(sock, &opts.dst, opts.dst_type, 0,
opts.cid);
opts.cid, opts.timeout);
break;
case BT_IO_L2CAP:
case BT_IO_L2ERTM:
err = l2cap_connect(sock, &opts.dst, opts.dst_type,
opts.psm, opts.cid);
opts.psm, opts.cid, opts.timeout);
break;
case BT_IO_RFCOMM:
err = rfcomm_connect(sock, &opts.dst, opts.channel);

View File

@ -70,8 +70,16 @@ typedef enum {
BT_IO_OPT_MODE,
BT_IO_OPT_FLUSHABLE,
BT_IO_OPT_PRIORITY,
BT_IO_OPT_TIMEOUT
} BtIOOption;
typedef enum {
BT_IO_SEC_SDP = 0,
BT_IO_SEC_LOW,
BT_IO_SEC_MEDIUM,
BT_IO_SEC_HIGH,
} BtIOSecLevel;
typedef enum {
BT_IO_MODE_BASIC = 0,
BT_IO_MODE_RETRANS,

View File

@ -1383,14 +1383,16 @@ static void attr_print_func(void *value, void *userData)
{
sdp_data_t *d = (sdp_data_t *)value;
SDPDBG("=====================================\n");
SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n", d->attrId);
SDPDBG("ATTRIBUTE VALUE PTR : %p\n", value);
if (d)
if (d) {
SDPDBG("=====================================\n");
SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n", d->attrId);
SDPDBG("ATTRIBUTE VALUE PTR : %p\n", value);
sdp_data_print(d);
else
}
else {
SDPDBG("NULL value\n");
SDPDBG("=====================================\n");
SDPDBG("=====================================\n");
}
}
void sdp_print_service_attr(sdp_list_t *svcAttrList)

View File

@ -133,7 +133,7 @@ void __btd_log_init(const char *debug, int detach)
openlog("bluetoothd", option, LOG_DAEMON);
syslog(LOG_INFO, "Bluetooth daemon %s", VERSION);
syslog(LOG_INFO, "Bluetooth daemon %d.%d", BLUEZ_VERSION_MAJOR, BLUEZ_VERSION_MINOR);
}
void __btd_log_cleanup(void)

View File

@ -0,0 +1,43 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012 Texas Instruments Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* Requirements for read/write operations */
enum {
ATT_NONE, /* No restrictions */
ATT_AUTHENTICATION, /* Authentication required */
ATT_AUTHORIZATION, /* Authorization required */
ATT_NOT_PERMITTED, /* Operation not permitted */
};
struct attribute {
uint16_t handle;
bt_uuid_t uuid;
int read_req; /* Read requirement */
int write_req; /* Write requirement */
uint8_t (*read_cb)(struct attribute *a, struct btd_device *device,
gpointer user_data);
uint8_t (*write_cb)(struct attribute *a, struct btd_device *device,
gpointer user_data);
gpointer cb_user_data;
size_t len;
uint8_t *data;
};

1251
bluez/bluez5/attrib/att.c Normal file

File diff suppressed because it is too large Load Diff

202
bluez/bluez5/attrib/att.h Normal file
View File

@ -0,0 +1,202 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "src/shared/crypto.h"
/* Len of signature in write signed packet */
#define ATT_SIGNATURE_LEN 12
/* Attribute Protocol Opcodes */
#define ATT_OP_ERROR 0x01
#define ATT_OP_MTU_REQ 0x02
#define ATT_OP_MTU_RESP 0x03
#define ATT_OP_FIND_INFO_REQ 0x04
#define ATT_OP_FIND_INFO_RESP 0x05
#define ATT_OP_FIND_BY_TYPE_REQ 0x06
#define ATT_OP_FIND_BY_TYPE_RESP 0x07
#define ATT_OP_READ_BY_TYPE_REQ 0x08
#define ATT_OP_READ_BY_TYPE_RESP 0x09
#define ATT_OP_READ_REQ 0x0A
#define ATT_OP_READ_RESP 0x0B
#define ATT_OP_READ_BLOB_REQ 0x0C
#define ATT_OP_READ_BLOB_RESP 0x0D
#define ATT_OP_READ_MULTI_REQ 0x0E
#define ATT_OP_READ_MULTI_RESP 0x0F
#define ATT_OP_READ_BY_GROUP_REQ 0x10
#define ATT_OP_READ_BY_GROUP_RESP 0x11
#define ATT_OP_WRITE_REQ 0x12
#define ATT_OP_WRITE_RESP 0x13
#define ATT_OP_WRITE_CMD 0x52
#define ATT_OP_PREP_WRITE_REQ 0x16
#define ATT_OP_PREP_WRITE_RESP 0x17
#define ATT_OP_EXEC_WRITE_REQ 0x18
#define ATT_OP_EXEC_WRITE_RESP 0x19
#define ATT_OP_HANDLE_NOTIFY 0x1B
#define ATT_OP_HANDLE_IND 0x1D
#define ATT_OP_HANDLE_CNF 0x1E
#define ATT_OP_SIGNED_WRITE_CMD 0xD2
/* Error codes for Error response PDU */
#define ATT_ECODE_INVALID_HANDLE 0x01
#define ATT_ECODE_READ_NOT_PERM 0x02
#define ATT_ECODE_WRITE_NOT_PERM 0x03
#define ATT_ECODE_INVALID_PDU 0x04
#define ATT_ECODE_AUTHENTICATION 0x05
#define ATT_ECODE_REQ_NOT_SUPP 0x06
#define ATT_ECODE_INVALID_OFFSET 0x07
#define ATT_ECODE_AUTHORIZATION 0x08
#define ATT_ECODE_PREP_QUEUE_FULL 0x09
#define ATT_ECODE_ATTR_NOT_FOUND 0x0A
#define ATT_ECODE_ATTR_NOT_LONG 0x0B
#define ATT_ECODE_INSUFF_ENCR_KEY_SIZE 0x0C
#define ATT_ECODE_INVAL_ATTR_VALUE_LEN 0x0D
#define ATT_ECODE_UNLIKELY 0x0E
#define ATT_ECODE_INSUFF_ENC 0x0F
#define ATT_ECODE_UNSUPP_GRP_TYPE 0x10
#define ATT_ECODE_INSUFF_RESOURCES 0x11
/* Application error */
#define ATT_ECODE_IO 0x80
#define ATT_ECODE_TIMEOUT 0x81
#define ATT_ECODE_ABORTED 0x82
#define ATT_MAX_VALUE_LEN 512
#define ATT_DEFAULT_L2CAP_MTU 48
#define ATT_DEFAULT_LE_MTU 23
#define ATT_CID 4
#define ATT_PSM 31
/* Flags for Execute Write Request Operation */
#define ATT_CANCEL_ALL_PREP_WRITES 0x00
#define ATT_WRITE_ALL_PREP_WRITES 0x01
/* Find Information Response Formats */
#define ATT_FIND_INFO_RESP_FMT_16BIT 0x01
#define ATT_FIND_INFO_RESP_FMT_128BIT 0x02
struct att_data_list {
uint16_t num;
uint16_t len;
uint8_t **data;
};
struct att_range {
uint16_t start;
uint16_t end;
};
struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len);
void att_data_list_free(struct att_data_list *list);
const char *att_ecode2str(uint8_t status);
uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, size_t len);
uint16_t dec_read_by_grp_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end, bt_uuid_t *uuid);
uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu,
size_t len);
uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
const uint8_t *value, size_t vlen, uint8_t *pdu,
size_t len);
uint16_t dec_find_by_type_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end, bt_uuid_t *uuid, uint8_t *value, size_t *vlen);
uint16_t enc_find_by_type_resp(GSList *ranges, uint8_t *pdu, size_t len);
GSList *dec_find_by_type_resp(const uint8_t *pdu, size_t len);
struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, size_t len);
uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, size_t len);
uint16_t dec_read_by_type_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end, bt_uuid_t *uuid);
uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu,
size_t len);
uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t dec_write_cmd(const uint8_t *pdu, size_t len, uint16_t *handle,
uint8_t *value, size_t *vlen);
uint16_t enc_signed_write_cmd(uint16_t handle,
const uint8_t *value, size_t vlen,
struct bt_crypto *crypto,
const uint8_t csrk[16],
uint32_t sign_cnt,
uint8_t *pdu, size_t len);
uint16_t dec_signed_write_cmd(const uint8_t *pdu, size_t len,
uint16_t *handle,
uint8_t *value, size_t *vlen,
uint8_t signature[12]);
struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, size_t len);
uint16_t enc_write_req(uint16_t handle, const uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t dec_write_req(const uint8_t *pdu, size_t len, uint16_t *handle,
uint8_t *value, size_t *vlen);
uint16_t enc_write_resp(uint8_t *pdu);
uint16_t dec_write_resp(const uint8_t *pdu, size_t len);
uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, size_t len);
uint16_t enc_read_blob_req(uint16_t handle, uint16_t offset, uint8_t *pdu,
size_t len);
uint16_t dec_read_req(const uint8_t *pdu, size_t len, uint16_t *handle);
uint16_t dec_read_blob_req(const uint8_t *pdu, size_t len, uint16_t *handle,
uint16_t *offset);
uint16_t enc_read_resp(uint8_t *value, size_t vlen, uint8_t *pdu, size_t len);
uint16_t enc_read_blob_resp(uint8_t *value, size_t vlen, uint16_t offset,
uint8_t *pdu, size_t len);
ssize_t dec_read_resp(const uint8_t *pdu, size_t len, uint8_t *value,
size_t vlen);
uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status,
uint8_t *pdu, size_t len);
uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu,
size_t len);
uint16_t dec_find_info_req(const uint8_t *pdu, size_t len, uint16_t *start,
uint16_t *end);
uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
uint8_t *pdu, size_t len);
struct att_data_list *dec_find_info_resp(const uint8_t *pdu, size_t len,
uint8_t *format);
uint16_t enc_notification(uint16_t handle, uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t enc_indication(uint16_t handle, uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t dec_indication(const uint8_t *pdu, size_t len, uint16_t *handle,
uint8_t *value, size_t vlen);
uint16_t enc_confirmation(uint8_t *pdu, size_t len);
uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, size_t len);
uint16_t dec_mtu_req(const uint8_t *pdu, size_t len, uint16_t *mtu);
uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, size_t len);
uint16_t dec_mtu_resp(const uint8_t *pdu, size_t len, uint16_t *mtu);
uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
const uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t dec_prep_write_req(const uint8_t *pdu, size_t len, uint16_t *handle,
uint16_t *offset, uint8_t *value, size_t *vlen);
uint16_t enc_prep_write_resp(uint16_t handle, uint16_t offset,
const uint8_t *value, size_t vlen,
uint8_t *pdu, size_t len);
uint16_t dec_prep_write_resp(const uint8_t *pdu, size_t len, uint16_t *handle,
uint16_t *offset, uint8_t *value,
size_t *vlen);
uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, size_t len);
uint16_t dec_exec_write_req(const uint8_t *pdu, size_t len, uint8_t *flags);
uint16_t enc_exec_write_resp(uint8_t *pdu);
uint16_t dec_exec_write_resp(const uint8_t *pdu, size_t len);

View File

@ -0,0 +1,57 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
typedef enum {
GATT_OPT_INVALID = 0,
/* bt_uuid_t* value */
GATT_OPT_CHR_UUID,
/* a uint16 value */
GATT_OPT_CHR_UUID16,
GATT_OPT_CHR_PROPS,
GATT_OPT_CHR_VALUE_CB,
GATT_OPT_CHR_AUTHENTICATION,
GATT_OPT_CHR_AUTHORIZATION,
/* Get attribute handle for characteristic value */
GATT_OPT_CHR_VALUE_GET_HANDLE,
/* Get handle for ccc attribute */
GATT_OPT_CCC_GET_HANDLE,
/* arguments for authentication/authorization */
GATT_CHR_VALUE_READ,
GATT_CHR_VALUE_WRITE,
GATT_CHR_VALUE_BOTH,
} gatt_option;
typedef enum {
ATTRIB_READ,
ATTRIB_WRITE,
} attrib_event_t;
gboolean gatt_service_add(struct btd_adapter *adapter, uint16_t uuid,
bt_uuid_t *svc_uuid, gatt_option opt1, ...);

1261
bluez/bluez5/attrib/gatt.c Normal file

File diff suppressed because it is too large Load Diff

122
bluez/bluez5/attrib/gatt.h Normal file
View File

@ -0,0 +1,122 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* GATT Characteristic Property bit field
* Reference: Core SPEC 4.1 page 2183 (Table 3.5: Characteristic Properties
* bit field) defines how the Characteristic Value can be used, or how the
* characteristic descriptors (see Section 3.3.3 - page 2184) can be accessed.
* In the core spec, regular properties are included in the characteristic
* declaration, and the extended properties are defined as descriptor.
*/
#define GATT_CHR_PROP_BROADCAST 0x01
#define GATT_CHR_PROP_READ 0x02
#define GATT_CHR_PROP_WRITE_WITHOUT_RESP 0x04
#define GATT_CHR_PROP_WRITE 0x08
#define GATT_CHR_PROP_NOTIFY 0x10
#define GATT_CHR_PROP_INDICATE 0x20
#define GATT_CHR_PROP_AUTH 0x40
#define GATT_CHR_PROP_EXT_PROP 0x80
/* Client Characteristic Configuration bit field */
#define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT 0x0001
#define GATT_CLIENT_CHARAC_CFG_IND_BIT 0x0002
typedef void (*gatt_cb_t) (uint8_t status, GSList *l, void *user_data);
struct gatt_primary {
char uuid[MAX_LEN_UUID_STR + 1];
gboolean changed;
struct att_range range;
};
struct gatt_included {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
struct att_range range;
};
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
uint8_t properties;
uint16_t value_handle;
};
struct gatt_desc {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
uint16_t uuid16;
};
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
gatt_cb_t func, gpointer user_data);
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
gpointer user_data);
guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
size_t vlen, GAttribResultFunc func,
gpointer user_data);
guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
const uint8_t *value, size_t vlen,
GAttribResultFunc func,
gpointer user_data);
guint gatt_execute_write(GAttrib *attrib, uint8_t flags,
GAttribResultFunc func, gpointer user_data);
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, const uint8_t *value,
int vlen, GDestroyNotify notify, gpointer user_data);
guint gatt_signed_write_cmd(GAttrib *attrib, uint16_t handle,
const uint8_t *value, int vlen,
struct bt_crypto *crypto,
const uint8_t csrk[16],
uint32_t sign_cnt,
GDestroyNotify notify,
gpointer user_data);
guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, GAttribResultFunc func,
gpointer user_data);
guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
gpointer user_data);
gboolean gatt_parse_record(const sdp_record_t *rec,
uuid_t *prim_uuid, uint16_t *psm,
uint16_t *start, uint16_t *end);

View File

@ -0,0 +1,488 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <glib.h>
#include <bluetooth/bluetooth.h>
#include "btio/btio.h"
#include "src/log.h"
#include "src/shared/util.h"
#include "src/shared/att.h"
#include "src/shared/queue.h"
#include "attrib/gattrib.h"
struct _GAttrib {
int ref_count;
struct bt_att *att;
GIOChannel *io;
GDestroyNotify destroy;
gpointer destroy_user_data;
struct queue *callbacks;
uint8_t *buf;
int buflen;
struct queue *track_ids;
};
struct id_pair {
unsigned int org_id;
unsigned int pend_id;
};
struct attrib_callbacks {
struct id_pair *id;
GAttribResultFunc result_func;
GAttribNotifyFunc notify_func;
GDestroyNotify destroy_func;
gpointer user_data;
GAttrib *parent;
uint16_t notify_handle;
};
static bool find_with_org_id(const void *data, const void *user_data)
{
const struct id_pair *p = data;
unsigned int orig_id = PTR_TO_UINT(user_data);
return (p->org_id == orig_id);
}
static struct id_pair *store_id(GAttrib *attrib, unsigned int org_id,
unsigned int pend_id)
{
struct id_pair *t;
t = new0(struct id_pair, 1);
if (!t)
return NULL;
t->org_id = org_id;
t->pend_id = pend_id;
if (queue_push_tail(attrib->track_ids, t))
return t;
return NULL;
}
GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu, bool ext_signed)
{
gint fd;
GAttrib *attr;
if (!io)
return NULL;
fd = g_io_channel_unix_get_fd(io);
attr = new0(GAttrib, 1);
if (!attr)
return NULL;
g_io_channel_ref(io);
attr->io = io;
attr->att = bt_att_new(fd, ext_signed);
if (!attr->att)
goto fail;
bt_att_set_close_on_unref(attr->att, true);
g_io_channel_set_close_on_unref(io, FALSE);
if (!bt_att_set_mtu(attr->att, mtu))
goto fail;
attr->buf = malloc0(mtu);
attr->buflen = mtu;
if (!attr->buf)
goto fail;
attr->callbacks = queue_new();
if (!attr->callbacks)
goto fail;
attr->track_ids = queue_new();
if (!attr->track_ids)
goto fail;
return g_attrib_ref(attr);
fail:
free(attr->buf);
bt_att_unref(attr->att);
g_io_channel_unref(io);
free(attr);
return NULL;
}
GAttrib *g_attrib_ref(GAttrib *attrib)
{
if (!attrib)
return NULL;
__sync_fetch_and_add(&attrib->ref_count, 1);
DBG("%p: g_attrib_ref=%d ", attrib, attrib->ref_count);
return attrib;
}
static void attrib_callbacks_destroy(void *data)
{
struct attrib_callbacks *cb = data;
if (cb->destroy_func)
cb->destroy_func(cb->user_data);
if (queue_remove(cb->parent->track_ids, cb->id))
free(cb->id);
free(data);
}
static void attrib_callbacks_remove(void *data)
{
struct attrib_callbacks *cb = data;
if (!data || !queue_remove(cb->parent->callbacks, data))
return;
attrib_callbacks_destroy(data);
}
void g_attrib_unref(GAttrib *attrib)
{
if (!attrib)
return;
DBG("%p: g_attrib_unref=%d ", attrib, attrib->ref_count - 1);
if (__sync_sub_and_fetch(&attrib->ref_count, 1))
return;
if (attrib->destroy)
attrib->destroy(attrib->destroy_user_data);
bt_att_unref(attrib->att);
queue_destroy(attrib->callbacks, attrib_callbacks_destroy);
queue_destroy(attrib->track_ids, free);
free(attrib->buf);
g_io_channel_unref(attrib->io);
free(attrib);
}
GIOChannel *g_attrib_get_channel(GAttrib *attrib)
{
if (!attrib)
return NULL;
return attrib->io;
}
struct bt_att *g_attrib_get_att(GAttrib *attrib)
{
if (!attrib)
return NULL;
return attrib->att;
}
gboolean g_attrib_set_destroy_function(GAttrib *attrib, GDestroyNotify destroy,
gpointer user_data)
{
if (!attrib)
return FALSE;
attrib->destroy = destroy;
attrib->destroy_user_data = user_data;
return TRUE;
}
static uint8_t *construct_full_pdu(uint8_t opcode, const void *pdu,
uint16_t length)
{
uint8_t *buf = malloc0(length + 1);
if (!buf)
return NULL;
buf[0] = opcode;
memcpy(buf + 1, pdu, length);
return buf;
}
static void attrib_callback_result(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
uint8_t *buf;
struct attrib_callbacks *cb = user_data;
guint8 status = 0;
if (!cb)
return;
buf = construct_full_pdu(opcode, pdu, length);
if (!buf)
return;
if (opcode == BT_ATT_OP_ERROR_RSP) {
/* Error code is the third byte of the PDU data */
if (length < 4)
status = BT_ATT_ERROR_UNLIKELY;
else
status = ((guint8 *)pdu)[3];
}
if (cb->result_func)
cb->result_func(status, buf, length + 1, cb->user_data);
free(buf);
}
static void attrib_callback_notify(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
uint8_t *buf;
struct attrib_callbacks *cb = user_data;
if (!cb || !cb->notify_func)
return;
if (cb->notify_handle != GATTRIB_ALL_HANDLES && length < 2)
return;
if (cb->notify_handle != GATTRIB_ALL_HANDLES &&
cb->notify_handle != get_le16(pdu))
return;
buf = construct_full_pdu(opcode, pdu, length);
if (!buf)
return;
cb->notify_func(buf, length + 1, cb->user_data);
free(buf);
}
guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
GAttribResultFunc func, gpointer user_data,
GDestroyNotify notify)
{
struct attrib_callbacks *cb = NULL;
bt_att_response_func_t response_cb = NULL;
bt_att_destroy_func_t destroy_cb = NULL;
unsigned int pend_id;
if (!attrib)
return 0;
if (!pdu || !len)
return 0;
if (func || notify) {
cb = new0(struct attrib_callbacks, 1);
if (!cb)
return 0;
cb->result_func = func;
cb->user_data = user_data;
cb->destroy_func = notify;
cb->parent = attrib;
queue_push_head(attrib->callbacks, cb);
response_cb = attrib_callback_result;
destroy_cb = attrib_callbacks_remove;
}
pend_id = bt_att_send(attrib->att, pdu[0], (void *) pdu + 1, len - 1,
response_cb, cb, destroy_cb);
/*
* We store here pair as it is easier to handle it in response and in
* case where user request us to use specific id request - see below.
*/
if (id == 0)
id = pend_id;
/*
* If user what us to use given id, lets keep track on that so we give
* user a possibility to cancel ongoing request.
*/
if (cb)
cb->id = store_id(attrib, id, pend_id);
return id;
}
gboolean g_attrib_cancel(GAttrib *attrib, guint id)
{
struct id_pair *p;
if (!attrib)
return FALSE;
/*
* If request belongs to gattrib and is not yet done it has to be on
* the tracking id queue
*
* FIXME: It can happen that on the queue there is id_pair with
* given id which was provided by the user. In the same time it might
* happen that other attrib user got dynamic allocated req_id with same
* value as the one provided by the other user.
* In such case there are two clients having same request id and in
* this point of time we don't know which one calls cancel. For
* now we cancel request in which id was specified by the user.
*/
p = queue_remove_if(attrib->track_ids, find_with_org_id,
UINT_TO_PTR(id));
if (!p)
return FALSE;
id = p->pend_id;
free(p);
return bt_att_cancel(attrib->att, id);
}
static void cancel_request(void *data, void *user_data)
{
struct id_pair *p = data;
GAttrib *attrib = user_data;
bt_att_cancel(attrib->att, p->pend_id);
}
gboolean g_attrib_cancel_all(GAttrib *attrib)
{
if (!attrib)
return FALSE;
/* Cancel only request which belongs to gattrib */
queue_foreach(attrib->track_ids, cancel_request, attrib);
queue_remove_all(attrib->track_ids, NULL, NULL, free);
return TRUE;
}
guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
GAttribNotifyFunc func, gpointer user_data,
GDestroyNotify notify)
{
struct attrib_callbacks *cb = NULL;
if (!attrib)
return 0;
if (func || notify) {
cb = new0(struct attrib_callbacks, 1);
if (!cb)
return 0;
cb->notify_func = func;
cb->notify_handle = handle;
cb->user_data = user_data;
cb->destroy_func = notify;
cb->parent = attrib;
queue_push_head(attrib->callbacks, cb);
}
if (opcode == GATTRIB_ALL_REQS)
opcode = BT_ATT_ALL_REQUESTS;
return bt_att_register(attrib->att, opcode, attrib_callback_notify,
cb, attrib_callbacks_remove);
}
uint8_t *g_attrib_get_buffer(GAttrib *attrib, size_t *len)
{
uint16_t mtu;
if (!attrib || !len)
return NULL;
mtu = bt_att_get_mtu(attrib->att);
/*
* Clients of this expect a buffer to use.
*
* Pdu encoding in shared/att verifies if whole buffer fits the mtu,
* thus we should set the buflen also when mtu is reduced. But we
* need to reallocate the buffer only if mtu is larger.
*/
if (mtu > attrib->buflen)
attrib->buf = g_realloc(attrib->buf, mtu);
attrib->buflen = mtu;
*len = attrib->buflen;
return attrib->buf;
}
gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
{
if (!attrib)
return FALSE;
/*
* Clients of this expect a buffer to use.
*
* Pdu encoding in sharred/att verifies if whole buffer fits the mtu,
* thus we should set the buflen also when mtu is reduced. But we
* need to reallocate the buffer only if mtu is larger.
*/
if (mtu > attrib->buflen)
attrib->buf = g_realloc(attrib->buf, mtu);
attrib->buflen = mtu;
return bt_att_set_mtu(attrib->att, mtu);
}
gboolean g_attrib_unregister(GAttrib *attrib, guint id)
{
if (!attrib)
return FALSE;
return bt_att_unregister(attrib->att, id);
}
gboolean g_attrib_unregister_all(GAttrib *attrib)
{
if (!attrib)
return false;
return bt_att_unregister_all(attrib->att);
}

View File

@ -0,0 +1,78 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __GATTRIB_H
#define __GATTRIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#define GATTRIB_ALL_REQS 0xFE
#define GATTRIB_ALL_HANDLES 0x0000
struct bt_att; /* Forward declaration for compatibility */
struct _GAttrib;
typedef struct _GAttrib GAttrib;
typedef void (*GAttribResultFunc) (guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data);
typedef void (*GAttribDisconnectFunc)(gpointer user_data);
typedef void (*GAttribDebugFunc)(const char *str, gpointer user_data);
typedef void (*GAttribNotifyFunc)(const guint8 *pdu, guint16 len,
gpointer user_data);
GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu, bool ext_signed);
GAttrib *g_attrib_ref(GAttrib *attrib);
void g_attrib_unref(GAttrib *attrib);
GIOChannel *g_attrib_get_channel(GAttrib *attrib);
struct bt_att *g_attrib_get_att(GAttrib *attrib);
gboolean g_attrib_set_destroy_function(GAttrib *attrib,
GDestroyNotify destroy, gpointer user_data);
guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
GAttribResultFunc func, gpointer user_data,
GDestroyNotify notify);
gboolean g_attrib_cancel(GAttrib *attrib, guint id);
gboolean g_attrib_cancel_all(GAttrib *attrib);
guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
GAttribNotifyFunc func, gpointer user_data,
GDestroyNotify notify);
uint8_t *g_attrib_get_buffer(GAttrib *attrib, size_t *len);
gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu);
gboolean g_attrib_unregister(GAttrib *attrib, guint id);
gboolean g_attrib_unregister_all(GAttrib *attrib);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,30 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011 Nokia Corporation
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
int interactive(const char *src, const char *dst, const char *dst_type,
int psm);
GIOChannel *gatt_connect(const char *src, const char *dst,
const char *dst_type, const char *sec_level,
int psm, int mtu, BtIOConnect connect_cb,
GError **gerr);
size_t gatt_attr_data_from_string(const char *str, uint8_t **data);

1704
bluez/bluez5/btio/btio.c Normal file

File diff suppressed because it is too large Load Diff

96
bluez/bluez5/btio/btio.h Normal file
View File

@ -0,0 +1,96 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2009-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2009-2010 Nokia Corporation
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef BT_IO_H
#define BT_IO_H
#include <glib.h>
#define BT_IO_ERROR bt_io_error_quark()
GQuark bt_io_error_quark(void);
typedef enum {
BT_IO_OPT_INVALID = 0,
BT_IO_OPT_SOURCE,
BT_IO_OPT_SOURCE_BDADDR,
BT_IO_OPT_SOURCE_TYPE,
BT_IO_OPT_DEST,
BT_IO_OPT_DEST_BDADDR,
BT_IO_OPT_DEST_TYPE,
BT_IO_OPT_DEFER_TIMEOUT,
BT_IO_OPT_SEC_LEVEL,
BT_IO_OPT_KEY_SIZE,
BT_IO_OPT_CHANNEL,
BT_IO_OPT_SOURCE_CHANNEL,
BT_IO_OPT_DEST_CHANNEL,
BT_IO_OPT_PSM,
BT_IO_OPT_CID,
BT_IO_OPT_MTU,
BT_IO_OPT_OMTU,
BT_IO_OPT_IMTU,
BT_IO_OPT_MASTER,
BT_IO_OPT_HANDLE,
BT_IO_OPT_CLASS,
BT_IO_OPT_MODE,
BT_IO_OPT_FLUSHABLE,
BT_IO_OPT_PRIORITY,
BT_IO_OPT_VOICE,
BT_IO_OPT_TIMEOUT,
} BtIOOption;
typedef enum {
BT_IO_SEC_SDP = 0,
BT_IO_SEC_LOW,
BT_IO_SEC_MEDIUM,
BT_IO_SEC_HIGH,
} BtIOSecLevel;
typedef enum {
BT_IO_MODE_BASIC = 0,
BT_IO_MODE_RETRANS,
BT_IO_MODE_FLOWCTL,
BT_IO_MODE_ERTM,
BT_IO_MODE_STREAMING
} BtIOMode;
typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data);
typedef void (*BtIOConnect)(GIOChannel *io, GError *err, gpointer user_data);
gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
GDestroyNotify destroy, GError **err);
gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...);
gboolean bt_io_get(GIOChannel *io, GError **err, BtIOOption opt1, ...);
GIOChannel *bt_io_connect(BtIOConnect connect, gpointer user_data,
GDestroyNotify destroy, GError **gerr,
BtIOOption opt1, ...);
GIOChannel *bt_io_listen(BtIOConnect connect, BtIOConfirm confirm,
gpointer user_data, GDestroyNotify destroy,
GError **err, BtIOOption opt1, ...);
#endif

149
bluez/bluez5/lib/a2mp.h Normal file
View File

@ -0,0 +1,149 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012 Intel Corporation. All rights reserved.
* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __A2MP_H
#define __A2MP_H
#ifdef __cplusplus
extern "C" {
#endif
/* A2MP Protocol */
/* A2MP command codes */
#define A2MP_COMMAND_REJ 0x01
#define A2MP_DISCOVER_REQ 0x02
#define A2MP_DISCOVER_RSP 0x03
#define A2MP_CHANGE_NOTIFY 0x04
#define A2MP_CHANGE_RSP 0x05
#define A2MP_INFO_REQ 0x06
#define A2MP_INFO_RSP 0x07
#define A2MP_ASSOC_REQ 0x08
#define A2MP_ASSOC_RSP 0x09
#define A2MP_CREATE_REQ 0x0a
#define A2MP_CREATE_RSP 0x0b
#define A2MP_DISCONN_REQ 0x0c
#define A2MP_DISCONN_RSP 0x0d
struct a2mp_hdr {
uint8_t code;
uint8_t ident;
uint16_t len;
} __attribute__ ((packed));
#define A2MP_HDR_SIZE 4
struct a2mp_command_rej {
uint16_t reason;
} __attribute__ ((packed));
struct a2mp_discover_req {
uint16_t mtu;
uint16_t mask;
} __attribute__ ((packed));
struct a2mp_ctrl {
uint8_t id;
uint8_t type;
uint8_t status;
} __attribute__ ((packed));
struct a2mp_discover_rsp {
uint16_t mtu;
uint16_t mask;
struct a2mp_ctrl ctrl_list[0];
} __attribute__ ((packed));
struct a2mp_info_req {
uint8_t id;
} __attribute__ ((packed));
struct a2mp_info_rsp {
uint8_t id;
uint8_t status;
uint32_t total_bw;
uint32_t max_bw;
uint32_t min_latency;
uint16_t pal_caps;
uint16_t assoc_size;
} __attribute__ ((packed));
struct a2mp_assoc_req {
uint8_t id;
} __attribute__ ((packed));
struct a2mp_assoc_rsp {
uint8_t id;
uint8_t status;
uint8_t assoc_data[0];
} __attribute__ ((packed));
struct a2mp_create_req {
uint8_t local_id;
uint8_t remote_id;
uint8_t assoc_data[0];
} __attribute__ ((packed));
struct a2mp_create_rsp {
uint8_t local_id;
uint8_t remote_id;
uint8_t status;
} __attribute__ ((packed));
struct a2mp_disconn_req {
uint8_t local_id;
uint8_t remote_id;
} __attribute__ ((packed));
struct a2mp_disconn_rsp {
uint8_t local_id;
uint8_t remote_id;
uint8_t status;
} __attribute__ ((packed));
#define A2MP_COMMAND_NOT_RECOGNIZED 0x0000
/* AMP controller status */
#define AMP_CTRL_POWERED_DOWN 0x00
#define AMP_CTRL_BLUETOOTH_ONLY 0x01
#define AMP_CTRL_NO_CAPACITY 0x02
#define AMP_CTRL_LOW_CAPACITY 0x03
#define AMP_CTRL_MEDIUM_CAPACITY 0x04
#define AMP_CTRL_HIGH_CAPACITY 0x05
#define AMP_CTRL_FULL_CAPACITY 0x06
/* A2MP response status */
#define A2MP_STATUS_SUCCESS 0x00
#define A2MP_STATUS_INVALID_CTRL_ID 0x01
#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02
#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02
#define A2MP_STATUS_COLLISION_OCCURED 0x03
#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
#ifdef __cplusplus
}
#endif
#endif /* __A2MP_H */

172
bluez/bluez5/lib/amp.h Normal file
View File

@ -0,0 +1,172 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010-2011 Code Aurora Forum. All rights reserved.
* Copyright (C) 2012 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program 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 General Public License for more details.
*
*/
#ifndef __AMP_H
#define __AMP_H
#ifdef __cplusplus
extern "C" {
#endif
#define AMP_MGR_CID 0x03
/* AMP manager codes */
#define AMP_COMMAND_REJ 0x01
#define AMP_DISCOVER_REQ 0x02
#define AMP_DISCOVER_RSP 0x03
#define AMP_CHANGE_NOTIFY 0x04
#define AMP_CHANGE_RSP 0x05
#define AMP_INFO_REQ 0x06
#define AMP_INFO_RSP 0x07
#define AMP_ASSOC_REQ 0x08
#define AMP_ASSOC_RSP 0x09
#define AMP_LINK_REQ 0x0a
#define AMP_LINK_RSP 0x0b
#define AMP_DISCONN_REQ 0x0c
#define AMP_DISCONN_RSP 0x0d
typedef struct {
uint8_t code;
uint8_t ident;
uint16_t len;
} __attribute__ ((packed)) amp_mgr_hdr;
#define AMP_MGR_HDR_SIZE 4
/* AMP ASSOC structure */
typedef struct {
uint8_t type_id;
uint16_t len;
uint8_t data[0];
} __attribute__ ((packed)) amp_assoc_tlv;
typedef struct {
uint16_t reason;
} __attribute__ ((packed)) amp_cmd_rej_parms;
typedef struct {
uint16_t mtu;
uint16_t mask;
} __attribute__ ((packed)) amp_discover_req_parms;
typedef struct {
uint16_t mtu;
uint16_t mask;
uint8_t controller_list[0];
} __attribute__ ((packed)) amp_discover_rsp_parms;
typedef struct {
uint8_t id;
} __attribute__ ((packed)) amp_info_req_parms;
typedef struct {
uint8_t id;
uint8_t status;
uint32_t total_bandwidth;
uint32_t max_bandwidth;
uint32_t min_latency;
uint16_t pal_caps;
uint16_t assoc_size;
} __attribute__ ((packed)) amp_info_rsp_parms;
typedef struct {
uint8_t id;
uint8_t status;
amp_assoc_tlv assoc;
} __attribute__ ((packed)) amp_assoc_rsp_parms;
typedef struct {
uint8_t local_id;
uint8_t remote_id;
amp_assoc_tlv assoc;
} __attribute__ ((packed)) amp_link_req_parms;
typedef struct {
uint8_t local_id;
uint8_t remote_id;
uint8_t status;
} __attribute__ ((packed)) amp_link_rsp_parms;
typedef struct {
uint8_t local_id;
uint8_t remote_id;
} __attribute__ ((packed)) amp_disconn_req_parms;
#define A2MP_MAC_ADDR_TYPE 1
#define A2MP_PREF_CHANLIST_TYPE 2
#define A2MP_CONNECTED_CHAN 3
#define A2MP_PAL_CAP_TYPE 4
#define A2MP_PAL_VER_INFO 5
struct amp_tlv {
uint8_t type;
uint16_t len;
uint8_t val[0];
} __attribute__ ((packed));
struct amp_pal_ver {
uint8_t ver;
uint16_t company_id;
uint16_t sub_ver;
} __attribute__ ((packed));
struct amp_country_triplet {
union {
struct {
uint8_t first_channel;
uint8_t num_channels;
int8_t max_power;
} __attribute__ ((packed)) chans;
struct {
uint8_t reg_extension_id;
uint8_t reg_class;
uint8_t coverage_class;
} __attribute__ ((packed)) ext;
};
} __attribute__ ((packed));
struct amp_chan_list {
uint8_t country_code[3];
struct amp_country_triplet triplets[0];
} __attribute__ ((packed));
#define AMP_COMMAND_NOT_RECOGNIZED 0x0000
/* AMP controller status */
#define AMP_CT_POWERED_DOWN 0x00
#define AMP_CT_BLUETOOTH_ONLY 0x01
#define AMP_CT_NO_CAPACITY 0x02
#define AMP_CT_LOW_CAPACITY 0x03
#define AMP_CT_MEDIUM_CAPACITY 0x04
#define AMP_CT_HIGH_CAPACITY 0x05
#define AMP_CT_FULL_CAPACITY 0x06
/* AMP response status */
#define AMP_STATUS_SUCCESS 0x00
#define AMP_STATUS_INVALID_CTRL_ID 0x01
#define AMP_STATUS_UNABLE_START_LINK_CREATION 0x02
#define AMP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02
#define AMP_STATUS_COLLISION_OCCURED 0x03
#define AMP_STATUS_DISCONN_REQ_RECVD 0x04
#define AMP_STATUS_PHYS_LINK_EXISTS 0x05
#define AMP_STATUS_SECURITY_VIOLATION 0x06
#ifdef __cplusplus
}
#endif
#endif /* __AMP_H */

2345
bluez/bluez5/lib/bluetooth.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,404 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <endian.h>
#include <byteswap.h>
#include <netinet/in.h>
#ifndef AF_BLUETOOTH
#define AF_BLUETOOTH 31
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7
#define SOL_HCI 0
#define SOL_L2CAP 6
#define SOL_SCO 17
#define SOL_RFCOMM 18
#ifndef SOL_BLUETOOTH
#define SOL_BLUETOOTH 274
#endif
#define BT_SECURITY 4
struct bt_security {
uint8_t level;
uint8_t key_size;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3
#define BT_SECURITY_FIPS 4
#define BT_DEFER_SETUP 7
#define BT_FLUSHABLE 8
#define BT_FLUSHABLE_OFF 0
#define BT_FLUSHABLE_ON 1
#define BT_POWER 9
struct bt_power {
uint8_t force_active;
};
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
#define BT_CHANNEL_POLICY 10
/* BR/EDR only (default policy)
* AMP controllers cannot be used.
* Channel move requests from the remote device are denied.
* If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
*/
#define BT_CHANNEL_POLICY_BREDR_ONLY 0
/* BR/EDR Preferred
* Allow use of AMP controllers.
* If the L2CAP channel is currently on AMP, move it to BR/EDR.
* Channel move requests from the remote device are allowed.
*/
#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
/* AMP Preferred
* Allow use of AMP controllers
* If the L2CAP channel is currently on BR/EDR and AMP controller
* resources are available, initiate a channel move to AMP.
* Channel move requests from the remote device are allowed.
* If the L2CAP socket has not been connected yet, try to create
* and configure the channel directly on an AMP controller rather
* than BR/EDR.
*/
#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
#define BT_VOICE 11
struct bt_voice {
uint16_t setting;
};
#define BT_SNDMTU 12
#define BT_RCVMTU 13
#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
/* Connection and socket states */
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
/* Byte order conversions */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define htobs(d) (d)
#define htobl(d) (d)
#define htobll(d) (d)
#define btohs(d) (d)
#define btohl(d) (d)
#define btohll(d) (d)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define htobs(d) bswap_16(d)
#define htobl(d) bswap_32(d)
#define htobll(d) bswap_64(d)
#define btohs(d) bswap_16(d)
#define btohl(d) bswap_32(d)
#define btohll(d) bswap_64(d)
#else
#error "Unknown byte order"
#endif
/* Bluetooth unaligned access */
#define bt_get_unaligned(ptr) \
__extension__ ({ \
struct __attribute__((packed)) { \
__typeof__(*(ptr)) __v; \
} *__p = (__typeof__(__p)) (ptr); \
__p->__v; \
})
#define bt_put_unaligned(val, ptr) \
do { \
struct __attribute__((packed)) { \
__typeof__(*(ptr)) __v; \
} *__p = (__typeof__(__p)) (ptr); \
__p->__v = (val); \
} while(0)
#if __BYTE_ORDER == __LITTLE_ENDIAN
static inline uint64_t bt_get_le64(const void *ptr)
{
return bt_get_unaligned((const uint64_t *) ptr);
}
static inline uint64_t bt_get_be64(const void *ptr)
{
return bswap_64(bt_get_unaligned((const uint64_t *) ptr));
}
static inline uint32_t bt_get_le32(const void *ptr)
{
return bt_get_unaligned((const uint32_t *) ptr);
}
static inline uint32_t bt_get_be32(const void *ptr)
{
return bswap_32(bt_get_unaligned((const uint32_t *) ptr));
}
static inline uint16_t bt_get_le16(const void *ptr)
{
return bt_get_unaligned((const uint16_t *) ptr);
}
static inline uint16_t bt_get_be16(const void *ptr)
{
return bswap_16(bt_get_unaligned((const uint16_t *) ptr));
}
static inline void bt_put_le64(uint64_t val, const void *ptr)
{
bt_put_unaligned(val, (uint64_t *) ptr);
}
static inline void bt_put_be64(uint64_t val, const void *ptr)
{
bt_put_unaligned(bswap_64(val), (uint64_t *) ptr);
}
static inline void bt_put_le32(uint32_t val, const void *ptr)
{
bt_put_unaligned(val, (uint32_t *) ptr);
}
static inline void bt_put_be32(uint32_t val, const void *ptr)
{
bt_put_unaligned(bswap_32(val), (uint32_t *) ptr);
}
static inline void bt_put_le16(uint16_t val, const void *ptr)
{
bt_put_unaligned(val, (uint16_t *) ptr);
}
static inline void bt_put_be16(uint16_t val, const void *ptr)
{
bt_put_unaligned(bswap_16(val), (uint16_t *) ptr);
}
#elif __BYTE_ORDER == __BIG_ENDIAN
static inline uint64_t bt_get_le64(const void *ptr)
{
return bswap_64(bt_get_unaligned((const uint64_t *) ptr));
}
static inline uint64_t bt_get_be64(const void *ptr)
{
return bt_get_unaligned((const uint64_t *) ptr);
}
static inline uint32_t bt_get_le32(const void *ptr)
{
return bswap_32(bt_get_unaligned((const uint32_t *) ptr));
}
static inline uint32_t bt_get_be32(const void *ptr)
{
return bt_get_unaligned((const uint32_t *) ptr);
}
static inline uint16_t bt_get_le16(const void *ptr)
{
return bswap_16(bt_get_unaligned((const uint16_t *) ptr));
}
static inline uint16_t bt_get_be16(const void *ptr)
{
return bt_get_unaligned((const uint16_t *) ptr);
}
static inline void bt_put_le64(uint64_t val, const void *ptr)
{
bt_put_unaligned(bswap_64(val), (uint64_t *) ptr);
}
static inline void bt_put_be64(uint64_t val, const void *ptr)
{
bt_put_unaligned(val, (uint64_t *) ptr);
}
static inline void bt_put_le32(uint32_t val, const void *ptr)
{
bt_put_unaligned(bswap_32(val), (uint32_t *) ptr);
}
static inline void bt_put_be32(uint32_t val, const void *ptr)
{
bt_put_unaligned(val, (uint32_t *) ptr);
}
static inline void bt_put_le16(uint16_t val, const void *ptr)
{
bt_put_unaligned(bswap_16(val), (uint16_t *) ptr);
}
static inline void bt_put_be16(uint16_t val, const void *ptr)
{
bt_put_unaligned(val, (uint16_t *) ptr);
}
#else
#error "Unknown byte order"
#endif
/* BD Address */
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
/* BD Address type */
#define BDADDR_BREDR 0x00
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
void baswap(bdaddr_t *dst, const bdaddr_t *src);
bdaddr_t *strtoba(const char *str);
char *batostr(const bdaddr_t *ba);
int ba2str(const bdaddr_t *ba, char *str);
int str2ba(const char *str, bdaddr_t *ba);
int ba2oui(const bdaddr_t *ba, char *oui);
int bachk(const char *str);
int baprintf(const char *format, ...);
int bafprintf(FILE *stream, const char *format, ...);
int basprintf(char *str, const char *format, ...);
int basnprintf(char *str, size_t size, const char *format, ...);
void *bt_malloc(size_t size);
void bt_free(void *ptr);
int bt_error(uint16_t code);
const char *bt_compidtostr(int id);
typedef struct {
uint8_t data[16];
} uint128_t;
static inline void bswap_128(const void *src, void *dst)
{
const uint8_t *s = (const uint8_t *) src;
uint8_t *d = (uint8_t *) dst;
int i;
for (i = 0; i < 16; i++)
d[15 - i] = s[i];
}
#if __BYTE_ORDER == __BIG_ENDIAN
#define ntoh64(x) (x)
static inline void ntoh128(const uint128_t *src, uint128_t *dst)
{
memcpy(dst, src, sizeof(uint128_t));
}
static inline void btoh128(const uint128_t *src, uint128_t *dst)
{
bswap_128(src, dst);
}
#else
static inline uint64_t ntoh64(uint64_t n)
{
uint64_t h;
uint64_t tmp = ntohl(n & 0x00000000ffffffff);
h = ntohl(n >> 32);
h |= tmp << 32;
return h;
}
static inline void ntoh128(const uint128_t *src, uint128_t *dst)
{
bswap_128(src, dst);
}
static inline void btoh128(const uint128_t *src, uint128_t *dst)
{
memcpy(dst, src, sizeof(uint128_t));
}
#endif
#define hton64(x) ntoh64(x)
#define hton128(x, y) ntoh128(x, y)
#define htob128(x, y) btoh128(x, y)
#ifdef __cplusplus
}
#endif
#endif /* __BLUETOOTH_H */

10
bluez/bluez5/lib/bluez.pc Normal file
View File

@ -0,0 +1,10 @@
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: BlueZ
Description: Bluetooth protocol stack for Linux
Version: 5.43
Libs: -L${libdir} -lbluetooth
Cflags: -I${includedir}

View File

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: BlueZ
Description: Bluetooth protocol stack for Linux
Version: @VERSION@
Libs: -L${libdir} -lbluetooth
Cflags: -I${includedir}

162
bluez/bluez5/lib/bnep.h Normal file
View File

@ -0,0 +1,162 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __BNEP_H
#define __BNEP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <bluetooth/bluetooth.h>
#ifndef ETH_ALEN
#define ETH_ALEN 6 /* from <net/ethernet.h> */
#endif
/* BNEP UUIDs */
#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB
#define BNEP_UUID16 0x02
#define BNEP_UUID32 0x04
#define BNEP_UUID128 0x16
#define BNEP_SVC_PANU 0x1115
#define BNEP_SVC_NAP 0x1116
#define BNEP_SVC_GN 0x1117
/* BNEP packet types */
#define BNEP_GENERAL 0x00
#define BNEP_CONTROL 0x01
#define BNEP_COMPRESSED 0x02
#define BNEP_COMPRESSED_SRC_ONLY 0x03
#define BNEP_COMPRESSED_DST_ONLY 0x04
/* BNEP control types */
#define BNEP_CMD_NOT_UNDERSTOOD 0x00
#define BNEP_SETUP_CONN_REQ 0x01
#define BNEP_SETUP_CONN_RSP 0x02
#define BNEP_FILTER_NET_TYPE_SET 0x03
#define BNEP_FILTER_NET_TYPE_RSP 0x04
#define BNEP_FILTER_MULT_ADDR_SET 0x05
#define BNEP_FILTER_MULT_ADDR_RSP 0x06
/* BNEP response messages */
#define BNEP_SUCCESS 0x00
#define BNEP_CONN_INVALID_DST 0x01
#define BNEP_CONN_INVALID_SRC 0x02
#define BNEP_CONN_INVALID_SVC 0x03
#define BNEP_CONN_NOT_ALLOWED 0x04
#define BNEP_FILTER_UNSUPPORTED_REQ 0x01
#define BNEP_FILTER_INVALID_RANGE 0x02
#define BNEP_FILTER_INVALID_MCADDR 0x02
#define BNEP_FILTER_LIMIT_REACHED 0x03
#define BNEP_FILTER_DENIED_SECURITY 0x04
/* L2CAP settings */
#define BNEP_MTU 1691
#define BNEP_FLUSH_TO 0xffff
#define BNEP_CONNECT_TO 15
#define BNEP_FILTER_TO 15
#ifndef BNEP_PSM
#define BNEP_PSM 0x0f
#endif
/* BNEP headers */
#define BNEP_TYPE_MASK 0x7f
#define BNEP_EXT_HEADER 0x80
struct bnep_setup_conn_req {
uint8_t type;
uint8_t ctrl;
uint8_t uuid_size;
uint8_t service[0];
} __attribute__((packed));
struct bnep_set_filter_req {
uint8_t type;
uint8_t ctrl;
uint16_t len;
uint8_t list[0];
} __attribute__((packed));
struct bnep_ctrl_cmd_not_understood_cmd {
uint8_t type;
uint8_t ctrl;
uint8_t unkn_ctrl;
} __attribute__((packed));
struct bnep_control_rsp {
uint8_t type;
uint8_t ctrl;
uint16_t resp;
} __attribute__((packed));
struct bnep_ext_hdr {
uint8_t type;
uint8_t len;
uint8_t data[0];
} __attribute__((packed));
/* BNEP ioctl defines */
#define BNEPCONNADD _IOW('B', 200, int)
#define BNEPCONNDEL _IOW('B', 201, int)
#define BNEPGETCONNLIST _IOR('B', 210, int)
#define BNEPGETCONNINFO _IOR('B', 211, int)
#define BNEPGETSUPPFEAT _IOR('B', 212, int)
#define BNEP_SETUP_RESPONSE 0
struct bnep_connadd_req {
int sock; /* Connected socket */
uint32_t flags;
uint16_t role;
char device[16]; /* Name of the Ethernet device */
};
struct bnep_conndel_req {
uint32_t flags;
uint8_t dst[ETH_ALEN];
};
struct bnep_conninfo {
uint32_t flags;
uint16_t role;
uint16_t state;
uint8_t dst[ETH_ALEN];
char device[16];
};
struct bnep_connlist_req {
uint32_t cnum;
struct bnep_conninfo *ci;
};
#ifdef __cplusplus
}
#endif
#endif /* __BNEP_H */

69
bluez/bluez5/lib/cmtp.h Normal file
View File

@ -0,0 +1,69 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __CMTP_H
#define __CMTP_H
#ifdef __cplusplus
extern "C" {
#endif
/* CMTP defaults */
#define CMTP_MINIMUM_MTU 152
#define CMTP_DEFAULT_MTU 672
/* CMTP ioctl defines */
#define CMTPCONNADD _IOW('C', 200, int)
#define CMTPCONNDEL _IOW('C', 201, int)
#define CMTPGETCONNLIST _IOR('C', 210, int)
#define CMTPGETCONNINFO _IOR('C', 211, int)
#define CMTP_LOOPBACK 0
struct cmtp_connadd_req {
int sock; /* Connected socket */
uint32_t flags;
};
struct cmtp_conndel_req {
bdaddr_t bdaddr;
uint32_t flags;
};
struct cmtp_conninfo {
bdaddr_t bdaddr;
uint32_t flags;
uint16_t state;
int num;
};
struct cmtp_connlist_req {
uint32_t cnum;
struct cmtp_conninfo *ci;
};
#ifdef __cplusplus
}
#endif
#endif /* __CMTP_H */

3121
bluez/bluez5/lib/hci.c Normal file

File diff suppressed because it is too large Load Diff

2454
bluez/bluez5/lib/hci.h Normal file

File diff suppressed because it is too large Load Diff

242
bluez/bluez5/lib/hci_lib.h Normal file
View File

@ -0,0 +1,242 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __HCI_LIB_H
#define __HCI_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
struct hci_request {
uint16_t ogf;
uint16_t ocf;
int event;
void *cparam;
int clen;
void *rparam;
int rlen;
};
struct hci_version {
uint16_t manufacturer;
uint8_t hci_ver;
uint16_t hci_rev;
uint8_t lmp_ver;
uint16_t lmp_subver;
};
int hci_open_dev(int dev_id);
int hci_close_dev(int dd);
int hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param);
int hci_send_req(int dd, struct hci_request *req, int timeout);
int hci_create_connection(int dd, const bdaddr_t *bdaddr, uint16_t ptype, uint16_t clkoffset, uint8_t rswitch, uint16_t *handle, int to);
int hci_disconnect(int dd, uint16_t handle, uint8_t reason, int to);
int hci_inquiry(int dev_id, int len, int num_rsp, const uint8_t *lap, inquiry_info **ii, long flags);
int hci_devinfo(int dev_id, struct hci_dev_info *di);
int hci_devba(int dev_id, bdaddr_t *bdaddr);
int hci_devid(const char *str);
int hci_read_local_name(int dd, int len, char *name, int to);
int hci_write_local_name(int dd, const char *name, int to);
int hci_read_remote_name(int dd, const bdaddr_t *bdaddr, int len, char *name, int to);
int hci_read_remote_name_with_clock_offset(int dd, const bdaddr_t *bdaddr, uint8_t pscan_rep_mode, uint16_t clkoffset, int len, char *name, int to);
int hci_read_remote_name_cancel(int dd, const bdaddr_t *bdaddr, int to);
int hci_read_remote_version(int dd, uint16_t handle, struct hci_version *ver, int to);
int hci_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to);
int hci_read_remote_ext_features(int dd, uint16_t handle, uint8_t page, uint8_t *max_page, uint8_t *features, int to);
int hci_read_clock_offset(int dd, uint16_t handle, uint16_t *clkoffset, int to);
int hci_read_local_version(int dd, struct hci_version *ver, int to);
int hci_read_local_commands(int dd, uint8_t *commands, int to);
int hci_read_local_features(int dd, uint8_t *features, int to);
int hci_read_local_ext_features(int dd, uint8_t page, uint8_t *max_page, uint8_t *features, int to);
int hci_read_bd_addr(int dd, bdaddr_t *bdaddr, int to);
int hci_read_class_of_dev(int dd, uint8_t *cls, int to);
int hci_write_class_of_dev(int dd, uint32_t cls, int to);
int hci_read_voice_setting(int dd, uint16_t *vs, int to);
int hci_write_voice_setting(int dd, uint16_t vs, int to);
int hci_read_current_iac_lap(int dd, uint8_t *num_iac, uint8_t *lap, int to);
int hci_write_current_iac_lap(int dd, uint8_t num_iac, uint8_t *lap, int to);
int hci_read_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to);
int hci_write_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t *key, int to);
int hci_delete_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to);
int hci_authenticate_link(int dd, uint16_t handle, int to);
int hci_encrypt_link(int dd, uint16_t handle, uint8_t encrypt, int to);
int hci_change_link_key(int dd, uint16_t handle, int to);
int hci_switch_role(int dd, bdaddr_t *bdaddr, uint8_t role, int to);
int hci_park_mode(int dd, uint16_t handle, uint16_t max_interval, uint16_t min_interval, int to);
int hci_exit_park_mode(int dd, uint16_t handle, int to);
int hci_read_inquiry_scan_type(int dd, uint8_t *type, int to);
int hci_write_inquiry_scan_type(int dd, uint8_t type, int to);
int hci_read_inquiry_mode(int dd, uint8_t *mode, int to);
int hci_write_inquiry_mode(int dd, uint8_t mode, int to);
int hci_read_afh_mode(int dd, uint8_t *mode, int to);
int hci_write_afh_mode(int dd, uint8_t mode, int to);
int hci_read_ext_inquiry_response(int dd, uint8_t *fec, uint8_t *data, int to);
int hci_write_ext_inquiry_response(int dd, uint8_t fec, uint8_t *data, int to);
int hci_read_simple_pairing_mode(int dd, uint8_t *mode, int to);
int hci_write_simple_pairing_mode(int dd, uint8_t mode, int to);
int hci_read_local_oob_data(int dd, uint8_t *hash, uint8_t *randomizer, int to);
int hci_read_inq_response_tx_power_level(int dd, int8_t *level, int to);
int hci_read_inquiry_transmit_power_level(int dd, int8_t *level, int to);
int hci_write_inquiry_transmit_power_level(int dd, int8_t level, int to);
int hci_read_transmit_power_level(int dd, uint16_t handle, uint8_t type, int8_t *level, int to);
int hci_read_link_policy(int dd, uint16_t handle, uint16_t *policy, int to);
int hci_write_link_policy(int dd, uint16_t handle, uint16_t policy, int to);
int hci_read_link_supervision_timeout(int dd, uint16_t handle, uint16_t *timeout, int to);
int hci_write_link_supervision_timeout(int dd, uint16_t handle, uint16_t timeout, int to);
int hci_set_afh_classification(int dd, uint8_t *map, int to);
int hci_read_link_quality(int dd, uint16_t handle, uint8_t *link_quality, int to);
int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to);
int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map, int to);
int hci_read_clock(int dd, uint16_t handle, uint8_t which, uint32_t *clock, uint16_t *accuracy, int to);
int hci_le_set_scan_enable(int dev_id, uint8_t enable, uint8_t filter_dup, int to);
int hci_le_set_scan_parameters(int dev_id, uint8_t type, uint16_t interval,
uint16_t window, uint8_t own_type,
uint8_t filter, int to);
int hci_le_set_advertise_enable(int dev_id, uint8_t enable, int to);
int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
uint8_t initiator_filter, uint8_t peer_bdaddr_type,
bdaddr_t peer_bdaddr, uint8_t own_bdaddr_type,
uint16_t min_interval, uint16_t max_interval,
uint16_t latency, uint16_t supervision_timeout,
uint16_t min_ce_length, uint16_t max_ce_length,
uint16_t *handle, int to);
int hci_le_conn_update(int dd, uint16_t handle, uint16_t min_interval,
uint16_t max_interval, uint16_t latency,
uint16_t supervision_timeout, int to);
int hci_le_add_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to);
int hci_le_rm_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to);
int hci_le_read_white_list_size(int dd, uint8_t *size, int to);
int hci_le_clear_white_list(int dd, int to);
int hci_le_add_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type,
uint8_t *peer_irk, uint8_t *local_irk, int to);
int hci_le_rm_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to);
int hci_le_clear_resolving_list(int dd, int to);
int hci_le_read_resolving_list_size(int dd, uint8_t *size, int to);
int hci_le_set_address_resolution_enable(int dev_id, uint8_t enable, int to);
int hci_le_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to);
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
char *hci_bustostr(int bus);
char *hci_typetostr(int type);
char *hci_dtypetostr(int type);
char *hci_dflagstostr(uint32_t flags);
char *hci_ptypetostr(unsigned int ptype);
int hci_strtoptype(char *str, unsigned int *val);
char *hci_scoptypetostr(unsigned int ptype);
int hci_strtoscoptype(char *str, unsigned int *val);
char *hci_lptostr(unsigned int ptype);
int hci_strtolp(char *str, unsigned int *val);
char *hci_lmtostr(unsigned int ptype);
int hci_strtolm(char *str, unsigned int *val);
char *hci_cmdtostr(unsigned int cmd);
char *hci_commandstostr(uint8_t *commands, char *pref, int width);
char *hci_vertostr(unsigned int ver);
int hci_strtover(char *str, unsigned int *ver);
char *lmp_vertostr(unsigned int ver);
int lmp_strtover(char *str, unsigned int *ver);
char *pal_vertostr(unsigned int ver);
int pal_strtover(char *str, unsigned int *ver);
char *lmp_featurestostr(uint8_t *features, char *pref, int width);
static inline void hci_set_bit(int nr, void *addr)
{
*((uint32_t *) addr + (nr >> 5)) |= (1 << (nr & 31));
}
static inline void hci_clear_bit(int nr, void *addr)
{
*((uint32_t *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
}
static inline int hci_test_bit(int nr, void *addr)
{
return *((uint32_t *) addr + (nr >> 5)) & (1 << (nr & 31));
}
/* HCI filter tools */
static inline void hci_filter_clear(struct hci_filter *f)
{
memset(f, 0, sizeof(*f));
}
static inline void hci_filter_set_ptype(int t, struct hci_filter *f)
{
hci_set_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
}
static inline void hci_filter_clear_ptype(int t, struct hci_filter *f)
{
hci_clear_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
}
static inline int hci_filter_test_ptype(int t, struct hci_filter *f)
{
return hci_test_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
}
static inline void hci_filter_all_ptypes(struct hci_filter *f)
{
memset((void *) &f->type_mask, 0xff, sizeof(f->type_mask));
}
static inline void hci_filter_set_event(int e, struct hci_filter *f)
{
hci_set_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
}
static inline void hci_filter_clear_event(int e, struct hci_filter *f)
{
hci_clear_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
}
static inline int hci_filter_test_event(int e, struct hci_filter *f)
{
return hci_test_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
}
static inline void hci_filter_all_events(struct hci_filter *f)
{
memset((void *) f->event_mask, 0xff, sizeof(f->event_mask));
}
static inline void hci_filter_set_opcode(int opcode, struct hci_filter *f)
{
f->opcode = opcode;
}
static inline void hci_filter_clear_opcode(struct hci_filter *f)
{
f->opcode = 0;
}
static inline int hci_filter_test_opcode(int opcode, struct hci_filter *f)
{
return (f->opcode == opcode);
}
#ifdef __cplusplus
}
#endif
#endif /* __HCI_LIB_H */

85
bluez/bluez5/lib/hidp.h Normal file
View File

@ -0,0 +1,85 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2003-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __HIDP_H
#define __HIDP_H
#ifdef __cplusplus
extern "C" {
#endif
/* HIDP defaults */
#define HIDP_MINIMUM_MTU 48
#define HIDP_DEFAULT_MTU 48
/* HIDP ioctl defines */
#define HIDPCONNADD _IOW('H', 200, int)
#define HIDPCONNDEL _IOW('H', 201, int)
#define HIDPGETCONNLIST _IOR('H', 210, int)
#define HIDPGETCONNINFO _IOR('H', 211, int)
#define HIDP_VIRTUAL_CABLE_UNPLUG 0
#define HIDP_BOOT_PROTOCOL_MODE 1
#define HIDP_BLUETOOTH_VENDOR_ID 9
struct hidp_connadd_req {
int ctrl_sock; /* Connected control socket */
int intr_sock; /* Connected interrupt socket */
uint16_t parser; /* Parser version */
uint16_t rd_size; /* Report descriptor size */
uint8_t *rd_data; /* Report descriptor data */
uint8_t country;
uint8_t subclass;
uint16_t vendor;
uint16_t product;
uint16_t version;
uint32_t flags;
uint32_t idle_to;
char name[128]; /* Device name */
};
struct hidp_conndel_req {
bdaddr_t bdaddr;
uint32_t flags;
};
struct hidp_conninfo {
bdaddr_t bdaddr;
uint32_t flags;
uint16_t state;
uint16_t vendor;
uint16_t product;
uint16_t version;
char name[128];
};
struct hidp_connlist_req {
uint32_t cnum;
struct hidp_conninfo *ci;
};
#ifdef __cplusplus
}
#endif
#endif /* __HIDP_H */

279
bluez/bluez5/lib/l2cap.h Normal file
View File

@ -0,0 +1,279 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __L2CAP_H
#define __L2CAP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/socket.h>
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
/* L2CAP socket address */
struct sockaddr_l2 {
sa_family_t l2_family;
unsigned short l2_psm;
bdaddr_t l2_bdaddr;
unsigned short l2_cid;
uint8_t l2_bdaddr_type;
};
/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
uint16_t omtu;
uint16_t imtu;
uint16_t flush_to;
uint8_t mode;
uint8_t fcs;
uint8_t max_tx;
uint16_t txwin_size;
};
#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
uint16_t hci_handle;
uint8_t dev_class[3];
};
#define L2CAP_LM 0x03
#define L2CAP_LM_MASTER 0x0001
#define L2CAP_LM_AUTH 0x0002
#define L2CAP_LM_ENCRYPT 0x0004
#define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
#define L2CAP_CONN_RSP 0x03
#define L2CAP_CONF_REQ 0x04
#define L2CAP_CONF_RSP 0x05
#define L2CAP_DISCONN_REQ 0x06
#define L2CAP_DISCONN_RSP 0x07
#define L2CAP_ECHO_REQ 0x08
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
#define L2CAP_CREATE_REQ 0x0c
#define L2CAP_CREATE_RSP 0x0d
#define L2CAP_MOVE_REQ 0x0e
#define L2CAP_MOVE_RSP 0x0f
#define L2CAP_MOVE_CFM 0x10
#define L2CAP_MOVE_CFM_RSP 0x11
/* L2CAP extended feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
#define L2CAP_FEAT_RETRANS 0x00000002
#define L2CAP_FEAT_BIDIR_QOS 0x00000004
#define L2CAP_FEAT_ERTM 0x00000008
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
#define L2CAP_FEAT_EXT_FLOW 0x00000040
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
#define L2CAP_FEAT_EXT_WINDOW 0x00000100
#define L2CAP_FEAT_UCD 0x00000200
/* L2CAP fixed channels */
#define L2CAP_FC_L2CAP 0x02
#define L2CAP_FC_CONNLESS 0x04
#define L2CAP_FC_A2MP 0x08
/* L2CAP structures */
typedef struct {
uint16_t len;
uint16_t cid;
} __attribute__ ((packed)) l2cap_hdr;
#define L2CAP_HDR_SIZE 4
typedef struct {
uint8_t code;
uint8_t ident;
uint16_t len;
} __attribute__ ((packed)) l2cap_cmd_hdr;
#define L2CAP_CMD_HDR_SIZE 4
typedef struct {
uint16_t reason;
} __attribute__ ((packed)) l2cap_cmd_rej;
#define L2CAP_CMD_REJ_SIZE 2
typedef struct {
uint16_t psm;
uint16_t scid;
} __attribute__ ((packed)) l2cap_conn_req;
#define L2CAP_CONN_REQ_SIZE 4
typedef struct {
uint16_t dcid;
uint16_t scid;
uint16_t result;
uint16_t status;
} __attribute__ ((packed)) l2cap_conn_rsp;
#define L2CAP_CONN_RSP_SIZE 8
/* connect result */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004
/* connect status */
#define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002
typedef struct {
uint16_t dcid;
uint16_t flags;
uint8_t data[0];
} __attribute__ ((packed)) l2cap_conf_req;
#define L2CAP_CONF_REQ_SIZE 4
typedef struct {
uint16_t scid;
uint16_t flags;
uint16_t result;
uint8_t data[0];
} __attribute__ ((packed)) l2cap_conf_rsp;
#define L2CAP_CONF_RSP_SIZE 6
#define L2CAP_CONF_SUCCESS 0x0000
#define L2CAP_CONF_UNACCEPT 0x0001
#define L2CAP_CONF_REJECT 0x0002
#define L2CAP_CONF_UNKNOWN 0x0003
#define L2CAP_CONF_PENDING 0x0004
#define L2CAP_CONF_EFS_REJECT 0x0005
typedef struct {
uint8_t type;
uint8_t len;
uint8_t val[0];
} __attribute__ ((packed)) l2cap_conf_opt;
#define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
#define L2CAP_CONF_EFS 0x06
#define L2CAP_CONF_EWS 0x07
#define L2CAP_CONF_MAX_SIZE 22
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAMING 0x04
#define L2CAP_SERVTYPE_NOTRAFFIC 0x00
#define L2CAP_SERVTYPE_BESTEFFORT 0x01
#define L2CAP_SERVTYPE_GUARANTEED 0x02
typedef struct {
uint16_t dcid;
uint16_t scid;
} __attribute__ ((packed)) l2cap_disconn_req;
#define L2CAP_DISCONN_REQ_SIZE 4
typedef struct {
uint16_t dcid;
uint16_t scid;
} __attribute__ ((packed)) l2cap_disconn_rsp;
#define L2CAP_DISCONN_RSP_SIZE 4
typedef struct {
uint16_t type;
} __attribute__ ((packed)) l2cap_info_req;
#define L2CAP_INFO_REQ_SIZE 2
typedef struct {
uint16_t type;
uint16_t result;
uint8_t data[0];
} __attribute__ ((packed)) l2cap_info_rsp;
#define L2CAP_INFO_RSP_SIZE 4
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
/* info result */
#define L2CAP_IR_SUCCESS 0x0000
#define L2CAP_IR_NOTSUPP 0x0001
typedef struct {
uint16_t psm;
uint16_t scid;
uint8_t id;
} __attribute__ ((packed)) l2cap_create_req;
#define L2CAP_CREATE_REQ_SIZE 5
typedef struct {
uint16_t dcid;
uint16_t scid;
uint16_t result;
uint16_t status;
} __attribute__ ((packed)) l2cap_create_rsp;
#define L2CAP_CREATE_RSP_SIZE 8
typedef struct {
uint16_t icid;
uint8_t id;
} __attribute__ ((packed)) l2cap_move_req;
#define L2CAP_MOVE_REQ_SIZE 3
typedef struct {
uint16_t icid;
uint16_t result;
} __attribute__ ((packed)) l2cap_move_rsp;
#define L2CAP_MOVE_RSP_SIZE 4
typedef struct {
uint16_t icid;
uint16_t result;
} __attribute__ ((packed)) l2cap_move_cfm;
#define L2CAP_MOVE_CFM_SIZE 4
typedef struct {
uint16_t icid;
} __attribute__ ((packed)) l2cap_move_cfm_rsp;
#define L2CAP_MOVE_CFM_RSP_SIZE 2
#ifdef __cplusplus
}
#endif
#endif /* __L2CAP_H */

View File

@ -0,0 +1,41 @@
# libbluetooth-internal.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-0.1
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname=''
# Names of this library.
library_names=''
# The name of the static archive.
old_library='libbluetooth-internal.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=''
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libbluetooth-internal.
current=
age=
revision=
# Is this an already installed library?
installed=no
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir=''

926
bluez/bluez5/lib/mgmt.h Normal file
View File

@ -0,0 +1,926 @@
/*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_STATUS_SUCCESS 0x00
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
#define MGMT_STATUS_NOT_CONNECTED 0x02
#define MGMT_STATUS_FAILED 0x03
#define MGMT_STATUS_CONNECT_FAILED 0x04
#define MGMT_STATUS_AUTH_FAILED 0x05
#define MGMT_STATUS_NOT_PAIRED 0x06
#define MGMT_STATUS_NO_RESOURCES 0x07
#define MGMT_STATUS_TIMEOUT 0x08
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
#define MGMT_STATUS_BUSY 0x0a
#define MGMT_STATUS_REJECTED 0x0b
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
#define MGMT_STATUS_INVALID_PARAMS 0x0d
#define MGMT_STATUS_DISCONNECTED 0x0e
#define MGMT_STATUS_NOT_POWERED 0x0f
#define MGMT_STATUS_CANCELLED 0x10
#define MGMT_STATUS_INVALID_INDEX 0x11
#define MGMT_STATUS_RFKILLED 0x12
#define MGMT_STATUS_ALREADY_PAIRED 0x13
#define MGMT_STATUS_PERMISSION_DENIED 0x14
struct mgmt_hdr {
uint16_t opcode;
uint16_t index;
uint16_t len;
} __packed;
#define MGMT_HDR_SIZE 6
struct mgmt_addr_info {
bdaddr_t bdaddr;
uint8_t type;
} __packed;
#define MGMT_OP_READ_VERSION 0x0001
struct mgmt_rp_read_version {
uint8_t version;
uint16_t revision;
} __packed;
#define MGMT_OP_READ_COMMANDS 0x0002
struct mgmt_rp_read_commands {
uint16_t num_commands;
uint16_t num_events;
uint16_t opcodes[0];
} __packed;
#define MGMT_OP_READ_INDEX_LIST 0x0003
struct mgmt_rp_read_index_list {
uint16_t num_controllers;
uint16_t index[0];
} __packed;
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH (248 + 1)
#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1)
#define MGMT_SETTING_POWERED 0x00000001
#define MGMT_SETTING_CONNECTABLE 0x00000002
#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
#define MGMT_SETTING_DISCOVERABLE 0x00000008
#define MGMT_SETTING_BONDABLE 0x00000010
#define MGMT_SETTING_LINK_SECURITY 0x00000020
#define MGMT_SETTING_SSP 0x00000040
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000
#define MGMT_OP_READ_INFO 0x0004
struct mgmt_rp_read_info {
bdaddr_t bdaddr;
uint8_t version;
uint16_t manufacturer;
uint32_t supported_settings;
uint32_t current_settings;
uint8_t dev_class[3];
uint8_t name[MGMT_MAX_NAME_LENGTH];
uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
struct mgmt_mode {
uint8_t val;
} __packed;
struct mgmt_cod {
uint8_t val[3];
} __packed;
#define MGMT_OP_SET_POWERED 0x0005
#define MGMT_OP_SET_DISCOVERABLE 0x0006
struct mgmt_cp_set_discoverable {
uint8_t val;
uint16_t timeout;
} __packed;
#define MGMT_OP_SET_CONNECTABLE 0x0007
#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008
#define MGMT_OP_SET_BONDABLE 0x0009
#define MGMT_OP_SET_LINK_SECURITY 0x000A
#define MGMT_OP_SET_SSP 0x000B
#define MGMT_OP_SET_HS 0x000C
#define MGMT_OP_SET_LE 0x000D
#define MGMT_OP_SET_DEV_CLASS 0x000E
struct mgmt_cp_set_dev_class {
uint8_t major;
uint8_t minor;
} __packed;
#define MGMT_OP_SET_LOCAL_NAME 0x000F
struct mgmt_cp_set_local_name {
uint8_t name[MGMT_MAX_NAME_LENGTH];
uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_OP_ADD_UUID 0x0010
struct mgmt_cp_add_uuid {
uint8_t uuid[16];
uint8_t svc_hint;
} __packed;
#define MGMT_OP_REMOVE_UUID 0x0011
struct mgmt_cp_remove_uuid {
uint8_t uuid[16];
} __packed;
struct mgmt_link_key_info {
struct mgmt_addr_info addr;
uint8_t type;
uint8_t val[16];
uint8_t pin_len;
} __packed;
#define MGMT_OP_LOAD_LINK_KEYS 0x0012
struct mgmt_cp_load_link_keys {
uint8_t debug_keys;
uint16_t key_count;
struct mgmt_link_key_info keys[0];
} __packed;
struct mgmt_ltk_info {
struct mgmt_addr_info addr;
uint8_t type;
uint8_t master;
uint8_t enc_size;
uint16_t ediv;
uint64_t rand;
uint8_t val[16];
} __packed;
#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
struct mgmt_cp_load_long_term_keys {
uint16_t key_count;
struct mgmt_ltk_info keys[0];
} __packed;
#define MGMT_OP_DISCONNECT 0x0014
struct mgmt_cp_disconnect {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_rp_disconnect {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_GET_CONNECTIONS 0x0015
struct mgmt_rp_get_connections {
uint16_t conn_count;
struct mgmt_addr_info addr[0];
} __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0016
struct mgmt_cp_pin_code_reply {
struct mgmt_addr_info addr;
uint8_t pin_len;
uint8_t pin_code[16];
} __packed;
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017
struct mgmt_cp_pin_code_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_SET_IO_CAPABILITY 0x0018
struct mgmt_cp_set_io_capability {
uint8_t io_capability;
} __packed;
#define MGMT_OP_PAIR_DEVICE 0x0019
struct mgmt_cp_pair_device {
struct mgmt_addr_info addr;
uint8_t io_cap;
} __packed;
struct mgmt_rp_pair_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_CANCEL_PAIR_DEVICE 0x001A
#define MGMT_OP_UNPAIR_DEVICE 0x001B
struct mgmt_cp_unpair_device {
struct mgmt_addr_info addr;
uint8_t disconnect;
} __packed;
struct mgmt_rp_unpair_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_CONFIRM_REPLY 0x001C
struct mgmt_cp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_rp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001D
#define MGMT_OP_USER_PASSKEY_REPLY 0x001E
struct mgmt_cp_user_passkey_reply {
struct mgmt_addr_info addr;
uint32_t passkey;
} __packed;
struct mgmt_rp_user_passkey_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001F
struct mgmt_cp_user_passkey_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020
struct mgmt_rp_read_local_oob_data {
uint8_t hash192[16];
uint8_t rand192[16];
uint8_t hash256[16];
uint8_t rand256[16];
} __packed;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
struct mgmt_cp_add_remote_oob_data {
struct mgmt_addr_info addr;
uint8_t hash192[16];
uint8_t rand192[16];
uint8_t hash256[16];
uint8_t rand256[16];
} __packed;
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022
struct mgmt_cp_remove_remote_oob_data {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_START_DISCOVERY 0x0023
struct mgmt_cp_start_discovery {
uint8_t type;
} __packed;
#define MGMT_OP_STOP_DISCOVERY 0x0024
struct mgmt_cp_stop_discovery {
uint8_t type;
} __packed;
#define MGMT_OP_CONFIRM_NAME 0x0025
struct mgmt_cp_confirm_name {
struct mgmt_addr_info addr;
uint8_t name_known;
} __packed;
struct mgmt_rp_confirm_name {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_BLOCK_DEVICE 0x0026
struct mgmt_cp_block_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_UNBLOCK_DEVICE 0x0027
struct mgmt_cp_unblock_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_SET_DEVICE_ID 0x0028
struct mgmt_cp_set_device_id {
uint16_t source;
uint16_t vendor;
uint16_t product;
uint16_t version;
} __packed;
#define MGMT_OP_SET_ADVERTISING 0x0029
#define MGMT_OP_SET_BREDR 0x002A
#define MGMT_OP_SET_STATIC_ADDRESS 0x002B
struct mgmt_cp_set_static_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_OP_SET_SCAN_PARAMS 0x002C
struct mgmt_cp_set_scan_params {
uint16_t interval;
uint16_t window;
} __packed;
#define MGMT_OP_SET_SECURE_CONN 0x002D
#define MGMT_OP_SET_DEBUG_KEYS 0x002E
struct mgmt_irk_info {
struct mgmt_addr_info addr;
uint8_t val[16];
} __packed;
#define MGMT_OP_SET_PRIVACY 0x002F
struct mgmt_cp_set_privacy {
uint8_t privacy;
uint8_t irk[16];
} __packed;
#define MGMT_OP_LOAD_IRKS 0x0030
struct mgmt_cp_load_irks {
uint16_t irk_count;
struct mgmt_irk_info irks[0];
} __packed;
#define MGMT_OP_GET_CONN_INFO 0x0031
struct mgmt_cp_get_conn_info {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_rp_get_conn_info {
struct mgmt_addr_info addr;
int8_t rssi;
int8_t tx_power;
int8_t max_tx_power;
} __packed;
#define MGMT_OP_GET_CLOCK_INFO 0x0032
struct mgmt_cp_get_clock_info {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_rp_get_clock_info {
struct mgmt_addr_info addr;
uint32_t local_clock;
uint32_t piconet_clock;
uint16_t accuracy;
} __packed;
#define MGMT_OP_ADD_DEVICE 0x0033
struct mgmt_cp_add_device {
struct mgmt_addr_info addr;
uint8_t action;
} __packed;
struct mgmt_rp_add_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_REMOVE_DEVICE 0x0034
struct mgmt_cp_remove_device {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_rp_remove_device {
struct mgmt_addr_info addr;
} __packed;
struct mgmt_conn_param {
struct mgmt_addr_info addr;
uint16_t min_interval;
uint16_t max_interval;
uint16_t latency;
uint16_t timeout;
} __packed;
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
struct mgmt_cp_load_conn_param {
uint16_t param_count;
struct mgmt_conn_param params[0];
} __packed;
#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036
struct mgmt_rp_read_unconf_index_list {
uint16_t num_controllers;
uint16_t index[0];
} __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002
#define MGMT_OP_READ_CONFIG_INFO 0x0037
struct mgmt_rp_read_config_info {
uint16_t manufacturer;
uint32_t supported_options;
uint32_t missing_options;
} __packed;
#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038
struct mgmt_cp_set_external_config {
uint8_t config;
} __packed;
#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039
struct mgmt_cp_set_public_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_OP_START_SERVICE_DISCOVERY 0x003A
struct mgmt_cp_start_service_discovery {
uint8_t type;
int8_t rssi;
uint16_t uuid_count;
uint8_t uuids[0][16];
} __packed;
#define MGMT_OP_READ_LOCAL_OOB_EXT_DATA 0x003B
struct mgmt_cp_read_local_oob_ext_data {
uint8_t type;
} __packed;
struct mgmt_rp_read_local_oob_ext_data {
uint8_t type;
uint16_t eir_len;
uint8_t eir[0];
} __packed;
#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C
struct mgmt_rp_read_ext_index_list {
uint16_t num_controllers;
struct {
uint16_t index;
uint8_t type;
uint8_t bus;
} entry[0];
} __packed;
#define MGMT_OP_READ_ADV_FEATURES 0x003D
struct mgmt_rp_read_adv_features {
uint32_t supported_flags;
uint8_t max_adv_data_len;
uint8_t max_scan_rsp_len;
uint8_t max_instances;
uint8_t num_instances;
uint8_t instance[0];
} __packed;
#define MGMT_OP_ADD_ADVERTISING 0x003E
struct mgmt_cp_add_advertising {
uint8_t instance;
uint32_t flags;
uint16_t duration;
uint16_t timeout;
uint8_t adv_data_len;
uint8_t scan_rsp_len;
uint8_t data[0];
} __packed;
struct mgmt_rp_add_advertising {
uint8_t instance;
} __packed;
#define MGMT_ADV_FLAG_CONNECTABLE (1 << 0)
#define MGMT_ADV_FLAG_DISCOV (1 << 1)
#define MGMT_ADV_FLAG_LIMITED_DISCOV (1 << 2)
#define MGMT_ADV_FLAG_MANAGED_FLAGS (1 << 3)
#define MGMT_ADV_FLAG_TX_POWER (1 << 4)
#define MGMT_ADV_FLAG_APPEARANCE (1 << 5)
#define MGMT_ADV_FLAG_LOCAL_NAME (1 << 6)
#define MGMT_OP_REMOVE_ADVERTISING 0x003F
struct mgmt_cp_remove_advertising {
uint8_t instance;
} __packed;
#define MGMT_REMOVE_ADVERTISING_SIZE 1
struct mgmt_rp_remove_advertising {
uint8_t instance;
} __packed;
#define MGMT_OP_GET_ADV_SIZE_INFO 0x0040
struct mgmt_cp_get_adv_size_info {
uint8_t instance;
uint32_t flags;
} __packed;
#define MGMT_GET_ADV_SIZE_INFO_SIZE 5
struct mgmt_rp_get_adv_size_info {
uint8_t instance;
uint32_t flags;
uint8_t max_adv_data_len;
uint8_t max_scan_rsp_len;
} __packed;
#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041
#define MGMT_OP_READ_EXT_INFO 0x0042
struct mgmt_rp_read_ext_info {
bdaddr_t bdaddr;
uint8_t version;
uint16_t manufacturer;
uint32_t supported_settings;
uint32_t current_settings;
uint16_t eir_len;
uint8_t eir[0];
} __packed;
#define MGMT_OP_SET_APPEARANCE 0x0043
struct mgmt_cp_set_appearance {
uint16_t appearance;
} __packed;
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
uint8_t status;
uint8_t data[0];
} __packed;
#define MGMT_EV_CMD_STATUS 0x0002
struct mgmt_ev_cmd_status {
uint16_t opcode;
uint8_t status;
} __packed;
#define MGMT_EV_CONTROLLER_ERROR 0x0003
struct mgmt_ev_controller_error {
uint8_t error_code;
} __packed;
#define MGMT_EV_INDEX_ADDED 0x0004
#define MGMT_EV_INDEX_REMOVED 0x0005
#define MGMT_EV_NEW_SETTINGS 0x0006
#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
struct mgmt_ev_class_of_dev_changed {
uint8_t dev_class[3];
} __packed;
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
struct mgmt_ev_local_name_changed {
uint8_t name[MGMT_MAX_NAME_LENGTH];
uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_EV_NEW_LINK_KEY 0x0009
struct mgmt_ev_new_link_key {
uint8_t store_hint;
struct mgmt_link_key_info key;
} __packed;
#define MGMT_EV_NEW_LONG_TERM_KEY 0x000A
struct mgmt_ev_new_long_term_key {
uint8_t store_hint;
struct mgmt_ltk_info key;
} __packed;
#define MGMT_EV_DEVICE_CONNECTED 0x000B
struct mgmt_ev_device_connected {
struct mgmt_addr_info addr;
uint32_t flags;
uint16_t eir_len;
uint8_t eir[0];
} __packed;
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
#define MGMT_DEV_DISCONN_TIMEOUT 0x01
#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02
#define MGMT_DEV_DISCONN_REMOTE 0x03
#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
struct mgmt_ev_device_disconnected {
struct mgmt_addr_info addr;
uint8_t reason;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
struct mgmt_ev_connect_failed {
struct mgmt_addr_info addr;
uint8_t status;
} __packed;
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
struct mgmt_addr_info addr;
uint8_t secure;
} __packed;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct mgmt_ev_user_confirm_request {
struct mgmt_addr_info addr;
uint8_t confirm_hint;
uint32_t value;
} __packed;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0010
struct mgmt_ev_user_passkey_request {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_AUTH_FAILED 0x0011
struct mgmt_ev_auth_failed {
struct mgmt_addr_info addr;
uint8_t status;
} __packed;
#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01
#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02
#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04
#define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found {
struct mgmt_addr_info addr;
int8_t rssi;
uint32_t flags;
uint16_t eir_len;
uint8_t eir[0];
} __packed;
#define MGMT_EV_DISCOVERING 0x0013
struct mgmt_ev_discovering {
uint8_t type;
uint8_t discovering;
} __packed;
#define MGMT_EV_DEVICE_BLOCKED 0x0014
struct mgmt_ev_device_blocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNBLOCKED 0x0015
struct mgmt_ev_device_unblocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNPAIRED 0x0016
struct mgmt_ev_device_unpaired {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_PASSKEY_NOTIFY 0x0017
struct mgmt_ev_passkey_notify {
struct mgmt_addr_info addr;
uint32_t passkey;
uint8_t entered;
} __packed;
#define MGMT_EV_NEW_IRK 0x0018
struct mgmt_ev_new_irk {
uint8_t store_hint;
bdaddr_t rpa;
struct mgmt_irk_info key;
} __packed;
struct mgmt_csrk_info {
struct mgmt_addr_info addr;
uint8_t type;
uint8_t val[16];
} __packed;
#define MGMT_EV_NEW_CSRK 0x0019
struct mgmt_ev_new_csrk {
uint8_t store_hint;
struct mgmt_csrk_info key;
} __packed;
#define MGMT_EV_DEVICE_ADDED 0x001a
struct mgmt_ev_device_added {
struct mgmt_addr_info addr;
uint8_t action;
} __packed;
#define MGMT_EV_DEVICE_REMOVED 0x001b
struct mgmt_ev_device_removed {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_NEW_CONN_PARAM 0x001c
struct mgmt_ev_new_conn_param {
struct mgmt_addr_info addr;
uint8_t store_hint;
uint16_t min_interval;
uint16_t max_interval;
uint16_t latency;
uint16_t timeout;
} __packed;
#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d
#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e
#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f
#define MGMT_EV_EXT_INDEX_ADDED 0x0020
struct mgmt_ev_ext_index_added {
uint8_t type;
uint8_t bus;
} __packed;
#define MGMT_EV_EXT_INDEX_REMOVED 0x0021
struct mgmt_ev_ext_index_removed {
uint8_t type;
uint8_t bus;
} __packed;
#define MGMT_EV_LOCAL_OOB_DATA_UPDATED 0x0022
struct mgmt_ev_local_oob_data_updated {
uint8_t type;
uint16_t eir_len;
uint8_t eir[0];
} __packed;
#define MGMT_EV_ADVERTISING_ADDED 0x0023
struct mgmt_ev_advertising_added {
uint8_t instance;
} __packed;
#define MGMT_EV_ADVERTISING_REMOVED 0x0024
struct mgmt_ev_advertising_removed {
uint8_t instance;
} __packed;
#define MGMT_EV_EXT_INFO_CHANGED 0x0025
struct mgmt_ev_ext_info_changed {
uint16_t eir_len;
uint8_t eir[0];
} __packed;
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
"Read Commands",
"Read Index List",
"Read Controller Info",
"Set Powered",
"Set Discoverable",
"Set Connectable",
"Set Fast Connectable", /* 0x0008 */
"Set Bondable",
"Set Link Security",
"Set Secure Simple Pairing",
"Set High Speed",
"Set Low Energy",
"Set Dev Class",
"Set Local Name",
"Add UUID", /* 0x0010 */
"Remove UUID",
"Load Link Keys",
"Load Long Term Keys",
"Disconnect",
"Get Connections",
"PIN Code Reply",
"PIN Code Neg Reply",
"Set IO Capability", /* 0x0018 */
"Pair Device",
"Cancel Pair Device",
"Unpair Device",
"User Confirm Reply",
"User Confirm Neg Reply",
"User Passkey Reply",
"User Passkey Neg Reply",
"Read Local OOB Data", /* 0x0020 */
"Add Remote OOB Data",
"Remove Remove OOB Data",
"Start Discovery",
"Stop Discovery",
"Confirm Name",
"Block Device",
"Unblock Device",
"Set Device ID", /* 0x0028 */
"Set Advertising",
"Set BR/EDR",
"Set Static Address",
"Set Scan Parameters",
"Set Secure Connections",
"Set Debug Keys",
"Set Privacy",
"Load Identity Resolving Keys", /* 0x0030 */
"Get Connection Information",
"Get Clock Information",
"Add Device",
"Remove Device",
"Load Connection Parameters",
"Read Unconfigured Index List",
"Read Controller Configuration Information",
"Set External Configuration", /* 0x0038 */
"Set Public Address",
"Start Service Discovery",
"Read Local Out Of Band Extended Data",
"Read Extended Controller Index List",
"Read Advertising Features",
"Add Advertising",
"Remove Advertising",
"Get Advertising Size Information", /* 0x0040 */
"Start Limited Discovery",
"Read Extended Controller Information",
"Set Appearance",
};
static const char *mgmt_ev[] = {
"<0x0000>",
"Command Complete",
"Command Status",
"Controller Error",
"Index Added",
"Index Removed",
"New Settings",
"Class of Device Changed",
"Local Name Changed", /* 0x0008 */
"New Link Key",
"New Long Term Key",
"Device Connected",
"Device Disconnected",
"Connect Failed",
"PIN Code Request",
"User Confirm Request",
"User Passkey Request", /* 0x0010 */
"Authentication Failed",
"Device Found",
"Discovering",
"Device Blocked",
"Device Unblocked",
"Device Unpaired",
"Passkey Notify",
"New Identity Resolving Key", /* 0x0018 */
"New Signature Resolving Key",
"Device Added",
"Device Removed",
"New Connection Parameter",
"Unconfigured Index Added",
"Unconfigured Index Removed",
"New Configuration Options",
"Extended Index Added", /* 0x0020 */
"Extended Index Removed",
"Local Out Of Band Extended Data Updated",
"Advertising Added",
"Advertising Removed",
"Extended Controller Information Changed",
};
static const char *mgmt_status[] = {
"Success",
"Unknown Command",
"Not Connected",
"Failed",
"Connect Failed",
"Authentication Failed",
"Not Paired",
"No Resources",
"Timeout",
"Already Connected",
"Busy",
"Rejected",
"Not Supported",
"Invalid Parameters",
"Disconnected",
"Not Powered",
"Cancelled",
"Invalid Index",
"Blocked through rfkill",
"Already Paired",
"Permission Denied",
};
#ifndef NELEM
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
#endif
static inline const char *mgmt_opstr(uint16_t op)
{
if (op >= NELEM(mgmt_op))
return "<unknown opcode>";
return mgmt_op[op];
}
static inline const char *mgmt_evstr(uint16_t ev)
{
if (ev >= NELEM(mgmt_ev))
return "<unknown event>";
return mgmt_ev[ev];
}
static inline const char *mgmt_errstr(uint8_t status)
{
if (status >= NELEM(mgmt_status))
return "<unknown status>";
return mgmt_status[status];
}

99
bluez/bluez5/lib/rfcomm.h Normal file
View File

@ -0,0 +1,99 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __RFCOMM_H
#define __RFCOMM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/socket.h>
/* RFCOMM defaults */
#define RFCOMM_DEFAULT_MTU 127
#define RFCOMM_PSM 3
/* RFCOMM socket address */
struct sockaddr_rc {
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
uint8_t rc_channel;
};
/* RFCOMM socket options */
#define RFCOMM_CONNINFO 0x02
struct rfcomm_conninfo {
uint16_t hci_handle;
uint8_t dev_class[3];
};
#define RFCOMM_LM 0x03
#define RFCOMM_LM_MASTER 0x0001
#define RFCOMM_LM_AUTH 0x0002
#define RFCOMM_LM_ENCRYPT 0x0004
#define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
/* RFCOMM TTY support */
#define RFCOMM_MAX_DEV 256
#define RFCOMMCREATEDEV _IOW('R', 200, int)
#define RFCOMMRELEASEDEV _IOW('R', 201, int)
#define RFCOMMGETDEVLIST _IOR('R', 210, int)
#define RFCOMMGETDEVINFO _IOR('R', 211, int)
struct rfcomm_dev_req {
int16_t dev_id;
uint32_t flags;
bdaddr_t src;
bdaddr_t dst;
uint8_t channel;
};
#define RFCOMM_REUSE_DLC 0
#define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3
struct rfcomm_dev_info {
int16_t id;
uint32_t flags;
uint16_t state;
bdaddr_t src;
bdaddr_t dst;
uint8_t channel;
};
struct rfcomm_dev_list_req {
uint16_t dev_num;
struct rfcomm_dev_info dev_info[0];
};
#ifdef __cplusplus
}
#endif
#endif /* __RFCOMM_H */

62
bluez/bluez5/lib/sco.h Normal file
View File

@ -0,0 +1,62 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __SCO_H
#define __SCO_H
#ifdef __cplusplus
extern "C" {
#endif
/* SCO defaults */
#define SCO_DEFAULT_MTU 500
#define SCO_DEFAULT_FLUSH_TO 0xFFFF
#define SCO_CONN_TIMEOUT (HZ * 40)
#define SCO_DISCONN_TIMEOUT (HZ * 2)
#define SCO_CONN_IDLE_TIMEOUT (HZ * 60)
/* SCO socket address */
struct sockaddr_sco {
sa_family_t sco_family;
bdaddr_t sco_bdaddr;
};
/* set/get sockopt defines */
#define SCO_OPTIONS 0x01
struct sco_options {
uint16_t mtu;
};
#define SCO_CONNINFO 0x02
struct sco_conninfo {
uint16_t hci_handle;
uint8_t dev_class[3];
};
#ifdef __cplusplus
}
#endif
#endif /* __SCO_H */

4951
bluez/bluez5/lib/sdp.c Normal file

File diff suppressed because it is too large Load Diff

543
bluez/bluez5/lib/sdp.h Normal file
View File

@ -0,0 +1,543 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2001-2002 Nokia Corporation
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __SDP_H
#define __SDP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <bluetooth/bluetooth.h>
#define SDP_UNIX_PATH "/var/run/sdp"
#define SDP_RESPONSE_TIMEOUT 20
#define SDP_REQ_BUFFER_SIZE 2048
#define SDP_RSP_BUFFER_SIZE 65535
#define SDP_PDU_CHUNK_SIZE 1024
/*
* All definitions are based on Bluetooth Assigned Numbers
* of the Bluetooth Specification
*/
#define SDP_PSM 0x0001
/*
* Protocol UUIDs
*/
#define SDP_UUID 0x0001
#define UDP_UUID 0x0002
#define RFCOMM_UUID 0x0003
#define TCP_UUID 0x0004
#define TCS_BIN_UUID 0x0005
#define TCS_AT_UUID 0x0006
#define ATT_UUID 0x0007
#define OBEX_UUID 0x0008
#define IP_UUID 0x0009
#define FTP_UUID 0x000a
#define HTTP_UUID 0x000c
#define WSP_UUID 0x000e
#define BNEP_UUID 0x000f
#define UPNP_UUID 0x0010
#define HIDP_UUID 0x0011
#define HCRP_CTRL_UUID 0x0012
#define HCRP_DATA_UUID 0x0014
#define HCRP_NOTE_UUID 0x0016
#define AVCTP_UUID 0x0017
#define AVDTP_UUID 0x0019
#define CMTP_UUID 0x001b
#define UDI_UUID 0x001d
#define MCAP_CTRL_UUID 0x001e
#define MCAP_DATA_UUID 0x001f
#define L2CAP_UUID 0x0100
/*
* Service class identifiers of standard services and service groups
*/
#define SDP_SERVER_SVCLASS_ID 0x1000
#define BROWSE_GRP_DESC_SVCLASS_ID 0x1001
#define PUBLIC_BROWSE_GROUP 0x1002
#define SERIAL_PORT_SVCLASS_ID 0x1101
#define LAN_ACCESS_SVCLASS_ID 0x1102
#define DIALUP_NET_SVCLASS_ID 0x1103
#define IRMC_SYNC_SVCLASS_ID 0x1104
#define OBEX_OBJPUSH_SVCLASS_ID 0x1105
#define OBEX_FILETRANS_SVCLASS_ID 0x1106
#define IRMC_SYNC_CMD_SVCLASS_ID 0x1107
#define HEADSET_SVCLASS_ID 0x1108
#define CORDLESS_TELEPHONY_SVCLASS_ID 0x1109
#define AUDIO_SOURCE_SVCLASS_ID 0x110a
#define AUDIO_SINK_SVCLASS_ID 0x110b
#define AV_REMOTE_TARGET_SVCLASS_ID 0x110c
#define ADVANCED_AUDIO_SVCLASS_ID 0x110d
#define AV_REMOTE_SVCLASS_ID 0x110e
#define AV_REMOTE_CONTROLLER_SVCLASS_ID 0x110f
#define INTERCOM_SVCLASS_ID 0x1110
#define FAX_SVCLASS_ID 0x1111
#define HEADSET_AGW_SVCLASS_ID 0x1112
#define WAP_SVCLASS_ID 0x1113
#define WAP_CLIENT_SVCLASS_ID 0x1114
#define PANU_SVCLASS_ID 0x1115
#define NAP_SVCLASS_ID 0x1116
#define GN_SVCLASS_ID 0x1117
#define DIRECT_PRINTING_SVCLASS_ID 0x1118
#define REFERENCE_PRINTING_SVCLASS_ID 0x1119
#define IMAGING_SVCLASS_ID 0x111a
#define IMAGING_RESPONDER_SVCLASS_ID 0x111b
#define IMAGING_ARCHIVE_SVCLASS_ID 0x111c
#define IMAGING_REFOBJS_SVCLASS_ID 0x111d
#define HANDSFREE_SVCLASS_ID 0x111e
#define HANDSFREE_AGW_SVCLASS_ID 0x111f
#define DIRECT_PRT_REFOBJS_SVCLASS_ID 0x1120
#define REFLECTED_UI_SVCLASS_ID 0x1121
#define BASIC_PRINTING_SVCLASS_ID 0x1122
#define PRINTING_STATUS_SVCLASS_ID 0x1123
#define HID_SVCLASS_ID 0x1124
#define HCR_SVCLASS_ID 0x1125
#define HCR_PRINT_SVCLASS_ID 0x1126
#define HCR_SCAN_SVCLASS_ID 0x1127
#define CIP_SVCLASS_ID 0x1128
#define VIDEO_CONF_GW_SVCLASS_ID 0x1129
#define UDI_MT_SVCLASS_ID 0x112a
#define UDI_TA_SVCLASS_ID 0x112b
#define AV_SVCLASS_ID 0x112c
#define SAP_SVCLASS_ID 0x112d
#define PBAP_PCE_SVCLASS_ID 0x112e
#define PBAP_PSE_SVCLASS_ID 0x112f
#define PBAP_SVCLASS_ID 0x1130
#define MAP_MSE_SVCLASS_ID 0x1132
#define MAP_MCE_SVCLASS_ID 0x1133
#define MAP_SVCLASS_ID 0x1134
#define GNSS_SVCLASS_ID 0x1135
#define GNSS_SERVER_SVCLASS_ID 0x1136
#define MPS_SC_SVCLASS_ID 0x113A
#define MPS_SVCLASS_ID 0x113B
#define PNP_INFO_SVCLASS_ID 0x1200
#define GENERIC_NETWORKING_SVCLASS_ID 0x1201
#define GENERIC_FILETRANS_SVCLASS_ID 0x1202
#define GENERIC_AUDIO_SVCLASS_ID 0x1203
#define GENERIC_TELEPHONY_SVCLASS_ID 0x1204
#define UPNP_SVCLASS_ID 0x1205
#define UPNP_IP_SVCLASS_ID 0x1206
#define UPNP_PAN_SVCLASS_ID 0x1300
#define UPNP_LAP_SVCLASS_ID 0x1301
#define UPNP_L2CAP_SVCLASS_ID 0x1302
#define VIDEO_SOURCE_SVCLASS_ID 0x1303
#define VIDEO_SINK_SVCLASS_ID 0x1304
#define VIDEO_DISTRIBUTION_SVCLASS_ID 0x1305
#define HDP_SVCLASS_ID 0x1400
#define HDP_SOURCE_SVCLASS_ID 0x1401
#define HDP_SINK_SVCLASS_ID 0x1402
#define GENERIC_ACCESS_SVCLASS_ID 0x1800
#define GENERIC_ATTRIB_SVCLASS_ID 0x1801
#define APPLE_AGENT_SVCLASS_ID 0x2112
/*
* Standard profile descriptor identifiers; note these
* may be identical to some of the service classes defined above
*/
#define SDP_SERVER_PROFILE_ID SDP_SERVER_SVCLASS_ID
#define BROWSE_GRP_DESC_PROFILE_ID BROWSE_GRP_DESC_SVCLASS_ID
#define SERIAL_PORT_PROFILE_ID SERIAL_PORT_SVCLASS_ID
#define LAN_ACCESS_PROFILE_ID LAN_ACCESS_SVCLASS_ID
#define DIALUP_NET_PROFILE_ID DIALUP_NET_SVCLASS_ID
#define IRMC_SYNC_PROFILE_ID IRMC_SYNC_SVCLASS_ID
#define OBEX_OBJPUSH_PROFILE_ID OBEX_OBJPUSH_SVCLASS_ID
#define OBEX_FILETRANS_PROFILE_ID OBEX_FILETRANS_SVCLASS_ID
#define IRMC_SYNC_CMD_PROFILE_ID IRMC_SYNC_CMD_SVCLASS_ID
#define HEADSET_PROFILE_ID HEADSET_SVCLASS_ID
#define CORDLESS_TELEPHONY_PROFILE_ID CORDLESS_TELEPHONY_SVCLASS_ID
#define AUDIO_SOURCE_PROFILE_ID AUDIO_SOURCE_SVCLASS_ID
#define AUDIO_SINK_PROFILE_ID AUDIO_SINK_SVCLASS_ID
#define AV_REMOTE_TARGET_PROFILE_ID AV_REMOTE_TARGET_SVCLASS_ID
#define ADVANCED_AUDIO_PROFILE_ID ADVANCED_AUDIO_SVCLASS_ID
#define AV_REMOTE_PROFILE_ID AV_REMOTE_SVCLASS_ID
#define VIDEO_CONF_PROFILE_ID VIDEO_CONF_SVCLASS_ID
#define INTERCOM_PROFILE_ID INTERCOM_SVCLASS_ID
#define FAX_PROFILE_ID FAX_SVCLASS_ID
#define HEADSET_AGW_PROFILE_ID HEADSET_AGW_SVCLASS_ID
#define WAP_PROFILE_ID WAP_SVCLASS_ID
#define WAP_CLIENT_PROFILE_ID WAP_CLIENT_SVCLASS_ID
#define PANU_PROFILE_ID PANU_SVCLASS_ID
#define NAP_PROFILE_ID NAP_SVCLASS_ID
#define GN_PROFILE_ID GN_SVCLASS_ID
#define DIRECT_PRINTING_PROFILE_ID DIRECT_PRINTING_SVCLASS_ID
#define REFERENCE_PRINTING_PROFILE_ID REFERENCE_PRINTING_SVCLASS_ID
#define IMAGING_PROFILE_ID IMAGING_SVCLASS_ID
#define IMAGING_RESPONDER_PROFILE_ID IMAGING_RESPONDER_SVCLASS_ID
#define IMAGING_ARCHIVE_PROFILE_ID IMAGING_ARCHIVE_SVCLASS_ID
#define IMAGING_REFOBJS_PROFILE_ID IMAGING_REFOBJS_SVCLASS_ID
#define HANDSFREE_PROFILE_ID HANDSFREE_SVCLASS_ID
#define HANDSFREE_AGW_PROFILE_ID HANDSFREE_AGW_SVCLASS_ID
#define DIRECT_PRT_REFOBJS_PROFILE_ID DIRECT_PRT_REFOBJS_SVCLASS_ID
#define REFLECTED_UI_PROFILE_ID REFLECTED_UI_SVCLASS_ID
#define BASIC_PRINTING_PROFILE_ID BASIC_PRINTING_SVCLASS_ID
#define PRINTING_STATUS_PROFILE_ID PRINTING_STATUS_SVCLASS_ID
#define HID_PROFILE_ID HID_SVCLASS_ID
#define HCR_PROFILE_ID HCR_SCAN_SVCLASS_ID
#define HCR_PRINT_PROFILE_ID HCR_PRINT_SVCLASS_ID
#define HCR_SCAN_PROFILE_ID HCR_SCAN_SVCLASS_ID
#define CIP_PROFILE_ID CIP_SVCLASS_ID
#define VIDEO_CONF_GW_PROFILE_ID VIDEO_CONF_GW_SVCLASS_ID
#define UDI_MT_PROFILE_ID UDI_MT_SVCLASS_ID
#define UDI_TA_PROFILE_ID UDI_TA_SVCLASS_ID
#define AV_PROFILE_ID AV_SVCLASS_ID
#define SAP_PROFILE_ID SAP_SVCLASS_ID
#define PBAP_PCE_PROFILE_ID PBAP_PCE_SVCLASS_ID
#define PBAP_PSE_PROFILE_ID PBAP_PSE_SVCLASS_ID
#define PBAP_PROFILE_ID PBAP_SVCLASS_ID
#define MAP_PROFILE_ID MAP_SVCLASS_ID
#define PNP_INFO_PROFILE_ID PNP_INFO_SVCLASS_ID
#define GENERIC_NETWORKING_PROFILE_ID GENERIC_NETWORKING_SVCLASS_ID
#define GENERIC_FILETRANS_PROFILE_ID GENERIC_FILETRANS_SVCLASS_ID
#define GENERIC_AUDIO_PROFILE_ID GENERIC_AUDIO_SVCLASS_ID
#define GENERIC_TELEPHONY_PROFILE_ID GENERIC_TELEPHONY_SVCLASS_ID
#define UPNP_PROFILE_ID UPNP_SVCLASS_ID
#define UPNP_IP_PROFILE_ID UPNP_IP_SVCLASS_ID
#define UPNP_PAN_PROFILE_ID UPNP_PAN_SVCLASS_ID
#define UPNP_LAP_PROFILE_ID UPNP_LAP_SVCLASS_ID
#define UPNP_L2CAP_PROFILE_ID UPNP_L2CAP_SVCLASS_ID
#define VIDEO_SOURCE_PROFILE_ID VIDEO_SOURCE_SVCLASS_ID
#define VIDEO_SINK_PROFILE_ID VIDEO_SINK_SVCLASS_ID
#define VIDEO_DISTRIBUTION_PROFILE_ID VIDEO_DISTRIBUTION_SVCLASS_ID
#define HDP_PROFILE_ID HDP_SVCLASS_ID
#define HDP_SOURCE_PROFILE_ID HDP_SOURCE_SVCLASS_ID
#define HDP_SINK_PROFILE_ID HDP_SINK_SVCLASS_ID
#define GENERIC_ACCESS_PROFILE_ID GENERIC_ACCESS_SVCLASS_ID
#define GENERIC_ATTRIB_PROFILE_ID GENERIC_ATTRIB_SVCLASS_ID
#define APPLE_AGENT_PROFILE_ID APPLE_AGENT_SVCLASS_ID
#define MPS_PROFILE_ID MPS_SC_SVCLASS_ID
/*
* Compatibility macros for the old MDP acronym
*/
#define MDP_SVCLASS_ID HDP_SVCLASS_ID
#define MDP_SOURCE_SVCLASS_ID HDP_SOURCE_SVCLASS_ID
#define MDP_SINK_SVCLASS_ID HDP_SINK_SVCLASS_ID
#define MDP_PROFILE_ID HDP_PROFILE_ID
#define MDP_SOURCE_PROFILE_ID HDP_SOURCE_PROFILE_ID
#define MDP_SINK_PROFILE_ID HDP_SINK_PROFILE_ID
/*
* Attribute identifier codes
*/
#define SDP_SERVER_RECORD_HANDLE 0x0000
/*
* Possible values for attribute-id are listed below.
* See SDP Spec, section "Service Attribute Definitions" for more details.
*/
#define SDP_ATTR_RECORD_HANDLE 0x0000
#define SDP_ATTR_SVCLASS_ID_LIST 0x0001
#define SDP_ATTR_RECORD_STATE 0x0002
#define SDP_ATTR_SERVICE_ID 0x0003
#define SDP_ATTR_PROTO_DESC_LIST 0x0004
#define SDP_ATTR_BROWSE_GRP_LIST 0x0005
#define SDP_ATTR_LANG_BASE_ATTR_ID_LIST 0x0006
#define SDP_ATTR_SVCINFO_TTL 0x0007
#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008
#define SDP_ATTR_PFILE_DESC_LIST 0x0009
#define SDP_ATTR_DOC_URL 0x000a
#define SDP_ATTR_CLNT_EXEC_URL 0x000b
#define SDP_ATTR_ICON_URL 0x000c
#define SDP_ATTR_ADD_PROTO_DESC_LIST 0x000d
#define SDP_ATTR_GROUP_ID 0x0200
#define SDP_ATTR_IP_SUBNET 0x0200
#define SDP_ATTR_VERSION_NUM_LIST 0x0200
#define SDP_ATTR_SUPPORTED_FEATURES_LIST 0x0200
#define SDP_ATTR_GOEP_L2CAP_PSM 0x0200
#define SDP_ATTR_SVCDB_STATE 0x0201
#define SDP_ATTR_MPSD_SCENARIOS 0x0200
#define SDP_ATTR_MPMD_SCENARIOS 0x0201
#define SDP_ATTR_MPS_DEPENDENCIES 0x0202
#define SDP_ATTR_SERVICE_VERSION 0x0300
#define SDP_ATTR_EXTERNAL_NETWORK 0x0301
#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301
#define SDP_ATTR_DATA_EXCHANGE_SPEC 0x0301
#define SDP_ATTR_NETWORK 0x0301
#define SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302
#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302
#define SDP_ATTR_MCAP_SUPPORTED_PROCEDURES 0x0302
#define SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303
#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303
#define SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304
#define SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305
#define SDP_ATTR_NETWORK_ADDRESS 0x0306
#define SDP_ATTR_WAP_GATEWAY 0x0307
#define SDP_ATTR_HOMEPAGE_URL 0x0308
#define SDP_ATTR_WAP_STACK_TYPE 0x0309
#define SDP_ATTR_SECURITY_DESC 0x030a
#define SDP_ATTR_NET_ACCESS_TYPE 0x030b
#define SDP_ATTR_MAX_NET_ACCESSRATE 0x030c
#define SDP_ATTR_IP4_SUBNET 0x030d
#define SDP_ATTR_IP6_SUBNET 0x030e
#define SDP_ATTR_SUPPORTED_CAPABILITIES 0x0310
#define SDP_ATTR_SUPPORTED_FEATURES 0x0311
#define SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312
#define SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313
#define SDP_ATTR_SUPPORTED_REPOSITORIES 0x0314
#define SDP_ATTR_MAS_INSTANCE_ID 0x0315
#define SDP_ATTR_SUPPORTED_MESSAGE_TYPES 0x0316
#define SDP_ATTR_PBAP_SUPPORTED_FEATURES 0x0317
#define SDP_ATTR_MAP_SUPPORTED_FEATURES 0x0317
#define SDP_ATTR_SPECIFICATION_ID 0x0200
#define SDP_ATTR_VENDOR_ID 0x0201
#define SDP_ATTR_PRODUCT_ID 0x0202
#define SDP_ATTR_VERSION 0x0203
#define SDP_ATTR_PRIMARY_RECORD 0x0204
#define SDP_ATTR_VENDOR_ID_SOURCE 0x0205
#define SDP_ATTR_HID_DEVICE_RELEASE_NUMBER 0x0200
#define SDP_ATTR_HID_PARSER_VERSION 0x0201
#define SDP_ATTR_HID_DEVICE_SUBCLASS 0x0202
#define SDP_ATTR_HID_COUNTRY_CODE 0x0203
#define SDP_ATTR_HID_VIRTUAL_CABLE 0x0204
#define SDP_ATTR_HID_RECONNECT_INITIATE 0x0205
#define SDP_ATTR_HID_DESCRIPTOR_LIST 0x0206
#define SDP_ATTR_HID_LANG_ID_BASE_LIST 0x0207
#define SDP_ATTR_HID_SDP_DISABLE 0x0208
#define SDP_ATTR_HID_BATTERY_POWER 0x0209
#define SDP_ATTR_HID_REMOTE_WAKEUP 0x020a
#define SDP_ATTR_HID_PROFILE_VERSION 0x020b
#define SDP_ATTR_HID_SUPERVISION_TIMEOUT 0x020c
#define SDP_ATTR_HID_NORMALLY_CONNECTABLE 0x020d
#define SDP_ATTR_HID_BOOT_DEVICE 0x020e
/*
* These identifiers are based on the SDP spec stating that
* "base attribute id of the primary (universal) language must be 0x0100"
*
* Other languages should have their own offset; e.g.:
* #define XXXLangBase yyyy
* #define AttrServiceName_XXX 0x0000+XXXLangBase
*/
#define SDP_PRIMARY_LANG_BASE 0x0100
#define SDP_ATTR_SVCNAME_PRIMARY 0x0000 + SDP_PRIMARY_LANG_BASE
#define SDP_ATTR_SVCDESC_PRIMARY 0x0001 + SDP_PRIMARY_LANG_BASE
#define SDP_ATTR_PROVNAME_PRIMARY 0x0002 + SDP_PRIMARY_LANG_BASE
/*
* The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec)
* These are the exact data type+size descriptor values
* that go into the PDU buffer.
*
* The datatype (leading 5bits) + size descriptor (last 3 bits)
* is 8 bits. The size descriptor is critical to extract the
* right number of bytes for the data value from the PDU.
*
* For most basic types, the datatype+size descriptor is
* straightforward. However for constructed types and strings,
* the size of the data is in the next "n" bytes following the
* 8 bits (datatype+size) descriptor. Exactly what the "n" is
* specified in the 3 bits of the data size descriptor.
*
* TextString and URLString can be of size 2^{8, 16, 32} bytes
* DataSequence and DataSequenceAlternates can be of size 2^{8, 16, 32}
* The size are computed post-facto in the API and are not known apriori
*/
#define SDP_DATA_NIL 0x00
#define SDP_UINT8 0x08
#define SDP_UINT16 0x09
#define SDP_UINT32 0x0A
#define SDP_UINT64 0x0B
#define SDP_UINT128 0x0C
#define SDP_INT8 0x10
#define SDP_INT16 0x11
#define SDP_INT32 0x12
#define SDP_INT64 0x13
#define SDP_INT128 0x14
#define SDP_UUID_UNSPEC 0x18
#define SDP_UUID16 0x19
#define SDP_UUID32 0x1A
#define SDP_UUID128 0x1C
#define SDP_TEXT_STR_UNSPEC 0x20
#define SDP_TEXT_STR8 0x25
#define SDP_TEXT_STR16 0x26
#define SDP_TEXT_STR32 0x27
#define SDP_BOOL 0x28
#define SDP_SEQ_UNSPEC 0x30
#define SDP_SEQ8 0x35
#define SDP_SEQ16 0x36
#define SDP_SEQ32 0x37
#define SDP_ALT_UNSPEC 0x38
#define SDP_ALT8 0x3D
#define SDP_ALT16 0x3E
#define SDP_ALT32 0x3F
#define SDP_URL_STR_UNSPEC 0x40
#define SDP_URL_STR8 0x45
#define SDP_URL_STR16 0x46
#define SDP_URL_STR32 0x47
/*
* The PDU identifiers of SDP packets between client and server
*/
#define SDP_ERROR_RSP 0x01
#define SDP_SVC_SEARCH_REQ 0x02
#define SDP_SVC_SEARCH_RSP 0x03
#define SDP_SVC_ATTR_REQ 0x04
#define SDP_SVC_ATTR_RSP 0x05
#define SDP_SVC_SEARCH_ATTR_REQ 0x06
#define SDP_SVC_SEARCH_ATTR_RSP 0x07
/*
* Some additions to support service registration.
* These are outside the scope of the Bluetooth specification
*/
#define SDP_SVC_REGISTER_REQ 0x75
#define SDP_SVC_REGISTER_RSP 0x76
#define SDP_SVC_UPDATE_REQ 0x77
#define SDP_SVC_UPDATE_RSP 0x78
#define SDP_SVC_REMOVE_REQ 0x79
#define SDP_SVC_REMOVE_RSP 0x80
/*
* SDP Error codes
*/
#define SDP_INVALID_VERSION 0x0001
#define SDP_INVALID_RECORD_HANDLE 0x0002
#define SDP_INVALID_SYNTAX 0x0003
#define SDP_INVALID_PDU_SIZE 0x0004
#define SDP_INVALID_CSTATE 0x0005
/*
* SDP PDU
*/
typedef struct {
uint8_t pdu_id;
uint16_t tid;
uint16_t plen;
} __attribute__ ((packed)) sdp_pdu_hdr_t;
/*
* Common definitions for attributes in the SDP.
* Should the type of any of these change, you need only make a change here.
*/
typedef struct {
uint8_t type;
union {
uint16_t uuid16;
uint32_t uuid32;
uint128_t uuid128;
} value;
} uuid_t;
#define SDP_IS_UUID(x) ((x) == SDP_UUID16 || (x) == SDP_UUID32 || \
(x) == SDP_UUID128)
#define SDP_IS_ALT(x) ((x) == SDP_ALT8 || (x) == SDP_ALT16 || (x) == SDP_ALT32)
#define SDP_IS_SEQ(x) ((x) == SDP_SEQ8 || (x) == SDP_SEQ16 || (x) == SDP_SEQ32)
#define SDP_IS_TEXT_STR(x) ((x) == SDP_TEXT_STR8 || (x) == SDP_TEXT_STR16 || \
(x) == SDP_TEXT_STR32)
typedef struct _sdp_list sdp_list_t;
struct _sdp_list {
sdp_list_t *next;
void *data;
};
/*
* User-visible strings can be in many languages
* in addition to the universal language.
*
* Language meta-data includes language code in ISO639
* followed by the encoding format. The third field in this
* structure is the attribute offset for the language.
* User-visible strings in the specified language can be
* obtained at this offset.
*/
typedef struct {
uint16_t code_ISO639;
uint16_t encoding;
uint16_t base_offset;
} sdp_lang_attr_t;
/*
* Profile descriptor is the Bluetooth profile metadata. If a
* service conforms to a well-known profile, then its profile
* identifier (UUID) is an attribute of the service. In addition,
* if the profile has a version number it is specified here.
*/
typedef struct {
uuid_t uuid;
uint16_t version;
} sdp_profile_desc_t;
typedef struct {
uint8_t major;
uint8_t minor;
} sdp_version_t;
typedef struct {
uint8_t *data;
uint32_t data_size;
uint32_t buf_size;
} sdp_buf_t;
typedef struct {
uint32_t handle;
/* Search pattern: a sequence of all UUIDs seen in this record */
sdp_list_t *pattern;
sdp_list_t *attrlist;
/* Main service class for Extended Inquiry Response */
uuid_t svclass;
} sdp_record_t;
typedef struct sdp_data_struct sdp_data_t;
struct sdp_data_struct {
uint8_t dtd;
uint16_t attrId;
union {
int8_t int8;
int16_t int16;
int32_t int32;
int64_t int64;
uint128_t int128;
uint8_t uint8;
uint16_t uint16;
uint32_t uint32;
uint64_t uint64;
uint128_t uint128;
uuid_t uuid;
char *str;
sdp_data_t *dataseq;
} val;
sdp_data_t *next;
int unitSize;
};
#ifdef __cplusplus
}
#endif
#endif /* __SDP_H */

634
bluez/bluez5/lib/sdp_lib.h Normal file
View File

@ -0,0 +1,634 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2001-2002 Nokia Corporation
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __SDP_LIB_H
#define __SDP_LIB_H
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* SDP lists
*/
typedef void(*sdp_list_func_t)(void *, void *);
typedef void(*sdp_free_func_t)(void *);
typedef int (*sdp_comp_func_t)(const void *, const void *);
sdp_list_t *sdp_list_append(sdp_list_t *list, void *d);
sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d);
sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *data, sdp_comp_func_t f);
void sdp_list_free(sdp_list_t *list, sdp_free_func_t f);
static inline int sdp_list_len(const sdp_list_t *list)
{
int n = 0;
for (; list; list = list->next)
n++;
return n;
}
static inline sdp_list_t *sdp_list_find(sdp_list_t *list, void *u, sdp_comp_func_t f)
{
for (; list; list = list->next)
if (f(list->data, u) == 0)
return list;
return NULL;
}
static inline void sdp_list_foreach(sdp_list_t *list, sdp_list_func_t f, void *u)
{
for (; list; list = list->next)
f(list->data, u);
}
/*
* Values of the flags parameter to sdp_record_register
*/
#define SDP_RECORD_PERSIST 0x01
#define SDP_DEVICE_RECORD 0x02
/*
* Values of the flags parameter to sdp_connect
*/
#define SDP_RETRY_IF_BUSY 0x01
#define SDP_WAIT_ON_CLOSE 0x02
#define SDP_NON_BLOCKING 0x04
#define SDP_LARGE_MTU 0x08
/*
* a session with an SDP server
*/
typedef struct {
int sock;
int state;
int local;
int flags;
uint16_t tid; /* Current transaction ID */
void *priv;
} sdp_session_t;
typedef enum {
/*
* Attributes are specified as individual elements
*/
SDP_ATTR_REQ_INDIVIDUAL = 1,
/*
* Attributes are specified as a range
*/
SDP_ATTR_REQ_RANGE
} sdp_attrreq_type_t;
/*
* When the pdu_id(type) is a sdp error response, check the status value
* to figure out the error reason. For status values 0x0001-0x0006 check
* Bluetooth SPEC. If the status is 0xffff, call sdp_get_error function
* to get the real reason:
* - wrong transaction ID(EPROTO)
* - wrong PDU id or(EPROTO)
* - I/O error
*/
typedef void sdp_callback_t(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *udata);
/*
* create an L2CAP connection to a Bluetooth device
*
* INPUT:
*
* bdaddr_t *src:
* Address of the local device to use to make the connection
* (or BDADDR_ANY)
*
* bdaddr_t *dst:
* Address of the SDP server device
*/
sdp_session_t *sdp_connect(const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags);
int sdp_close(sdp_session_t *session);
int sdp_get_socket(const sdp_session_t *session);
/*
* SDP transaction: functions for asynchronous search.
*/
sdp_session_t *sdp_create(int sk, uint32_t flags);
int sdp_get_error(sdp_session_t *session);
int sdp_process(sdp_session_t *session);
int sdp_set_notify(sdp_session_t *session, sdp_callback_t *func, void *udata);
int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num);
int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list);
int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list);
uint16_t sdp_gen_tid(sdp_session_t *session);
/*
* find all devices in the piconet
*/
int sdp_general_inquiry(inquiry_info *ii, int dev_num, int duration, uint8_t *found);
/* flexible extraction of basic attributes - Jean II */
int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attr, int *value);
int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attr, char *value, int valuelen);
/*
* Basic sdp data functions
*/
sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value);
sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value, uint32_t length);
void sdp_data_free(sdp_data_t *data);
sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attr_id);
sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len);
sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length, int len);
sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *data);
int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *data);
void sdp_attr_remove(sdp_record_t *rec, uint16_t attr);
void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *data);
int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t attr, sdp_list_t *seq);
int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp);
/*
* NOTE that none of the functions below will update the SDP server,
* unless the {register, update}sdp_record_t() function is invoked.
* All functions which return an integer value, return 0 on success
* or -1 on failure.
*/
/*
* Create an attribute and add it to the service record's attribute list.
* This consists of the data type descriptor of the attribute,
* the value of the attribute and the attribute identifier.
*/
int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *p);
/*
* Set the information attributes of the service record.
* The set of attributes comprises service name, description
* and provider name
*/
void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc);
/*
* Set the ServiceClassID attribute to the sequence specified by seq.
* Note that the identifiers need to be in sorted order from the most
* specific to the most generic service class that this service
* conforms to.
*/
static inline int sdp_set_service_classes(sdp_record_t *rec, sdp_list_t *seq)
{
return sdp_set_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seq);
}
/*
* Get the service classes to which the service conforms.
*
* When set, the list contains elements of ServiceClassIdentifer(uint16_t)
* ordered from most specific to most generic
*/
static inline int sdp_get_service_classes(const sdp_record_t *rec, sdp_list_t **seqp)
{
return sdp_get_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seqp);
}
/*
* Set the BrowseGroupList attribute to the list specified by seq.
*
* A service can belong to one or more service groups
* and the list comprises such group identifiers (UUIDs)
*/
static inline int sdp_set_browse_groups(sdp_record_t *rec, sdp_list_t *seq)
{
return sdp_set_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seq);
}
/*
* Set the access protocols of the record to those specified in proto
*/
int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *proto);
/*
* Set the additional access protocols of the record to those specified in proto
*/
int sdp_set_add_access_protos(sdp_record_t *rec, const sdp_list_t *proto);
/*
* Get protocol port (i.e. PSM for L2CAP, Channel for RFCOMM)
*/
int sdp_get_proto_port(const sdp_list_t *list, int proto);
/*
* Get protocol descriptor.
*/
sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto);
/*
* Set the LanguageBase attributes to the values specified in list
* (a linked list of sdp_lang_attr_t objects, one for each language in
* which user-visible attributes are present).
*/
int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *list);
/*
* Set the ServiceInfoTimeToLive attribute of the service.
* This is the number of seconds that this record is guaranteed
* not to change after being obtained by a client.
*/
static inline int sdp_set_service_ttl(sdp_record_t *rec, uint32_t ttl)
{
return sdp_attr_add_new(rec, SDP_ATTR_SVCINFO_TTL, SDP_UINT32, &ttl);
}
/*
* Set the ServiceRecordState attribute of a service. This is
* guaranteed to change if there is any kind of modification to
* the record.
*/
static inline int sdp_set_record_state(sdp_record_t *rec, uint32_t state)
{
return sdp_attr_add_new(rec, SDP_ATTR_RECORD_STATE, SDP_UINT32, &state);
}
/*
* Set the ServiceID attribute of a service.
*/
void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid);
/*
* Set the GroupID attribute of a service
*/
void sdp_set_group_id(sdp_record_t *rec, uuid_t grouuuid);
/*
* Set the ServiceAvailability attribute of a service.
*
* Note that this represents the relative availability
* of the service: 0x00 means completely unavailable;
* 0xFF means maximum availability.
*/
static inline int sdp_set_service_avail(sdp_record_t *rec, uint8_t avail)
{
return sdp_attr_add_new(rec, SDP_ATTR_SERVICE_AVAILABILITY, SDP_UINT8, &avail);
}
/*
* Set the profile descriptor list attribute of a record.
*
* Each element in the list is an object of type
* sdp_profile_desc_t which is a definition of the
* Bluetooth profile that this service conforms to.
*/
int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *desc);
/*
* Set URL attributes of a record.
*
* ClientExecutableURL: a URL to a client's platform specific (WinCE,
* PalmOS) executable code that can be used to access this service.
*
* DocumentationURL: a URL pointing to service documentation
*
* IconURL: a URL to an icon that can be used to represent this service.
*
* Note: pass NULL for any URLs that you don't want to set or remove
*/
void sdp_set_url_attr(sdp_record_t *rec, const char *clientExecURL, const char *docURL, const char *iconURL);
/*
* a service search request.
*
* INPUT :
*
* sdp_list_t *search
* list containing elements of the search
* pattern. Each entry in the list is a UUID
* of the service to be searched
*
* uint16_t max_rec_num
* An integer specifying the maximum number of
* entries that the client can handle in the response.
*
* OUTPUT :
*
* int return value
* 0
* The request completed successfully. This does not
* mean the requested services were found
* -1
* The request completed unsuccessfully
*
* sdp_list_t *rsp_list
* This variable is set on a successful return if there are
* non-zero service handles. It is a singly linked list of
* service record handles (uint16_t)
*/
int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num, sdp_list_t **rsp_list);
/*
* a service attribute request.
*
* INPUT :
*
* uint32_t handle
* The handle of the service for which the attribute(s) are
* requested
*
* sdp_attrreq_type_t reqtype
* Attribute identifiers are 16 bit unsigned integers specified
* in one of 2 ways described below :
* SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
* They are the actual attribute identifiers in ascending order
*
* SDP_ATTR_REQ_RANGE - 32bit identifier range
* The high-order 16bits is the start of range
* the low-order 16bits are the end of range
* 0x0000 to 0xFFFF gets all attributes
*
* sdp_list_t *attrid_list
* Singly linked list containing attribute identifiers desired.
* Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
* or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
*
* OUTPUT :
* int return value
* 0
* The request completed successfully. This does not
* mean the requested services were found
* -1
* The request completed unsuccessfully due to a timeout
*/
sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list);
/*
* This is a service search request combined with the service
* attribute request. First a service class match is done and
* for matching service, requested attributes are extracted
*
* INPUT :
*
* sdp_list_t *search
* Singly linked list containing elements of the search
* pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16)
* of the service to be searched
*
* AttributeSpecification attrSpec
* Attribute identifiers are 16 bit unsigned integers specified
* in one of 2 ways described below :
* SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
* They are the actual attribute identifiers in ascending order
*
* SDP_ATTR_REQ_RANGE - 32bit identifier range
* The high-order 16bits is the start of range
* the low-order 16bits are the end of range
* 0x0000 to 0xFFFF gets all attributes
*
* sdp_list_t *attrid_list
* Singly linked list containing attribute identifiers desired.
* Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
* or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
*
* OUTPUT :
* int return value
* 0
* The request completed successfully. This does not
* mean the requested services were found
* -1
* The request completed unsuccessfully due to a timeout
*
* sdp_list_t *rsp_list
* This variable is set on a successful return to point to
* service(s) found. Each element of this list is of type
* sdp_record_t *.
*/
int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list, sdp_list_t **rsp_list);
/*
* Allocate/free a service record and its attributes
*/
sdp_record_t *sdp_record_alloc(void);
void sdp_record_free(sdp_record_t *rec);
/*
* Register a service record.
*
* Note: It is the responsbility of the Service Provider to create the
* record first and set its attributes using setXXX() methods.
*
* The service provider must then call sdp_record_register() to make
* the service record visible to SDP clients. This function returns 0
* on success or -1 on failure (and sets errno).
*/
int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, uint8_t *data, uint32_t size, uint8_t flags, uint32_t *handle);
int sdp_device_record_register(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec, uint8_t flags);
int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags);
/*
* Unregister a service record.
*/
int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle);
int sdp_device_record_unregister(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec);
int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec);
/*
* Update an existing service record. (Calling this function
* before a previous call to sdp_record_register() will result
* in an error.)
*/
int sdp_device_record_update_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle, uint8_t *data, uint32_t size);
int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp_record_t *rec);
int sdp_record_update(sdp_session_t *sess, const sdp_record_t *rec);
void sdp_record_print(const sdp_record_t *rec);
/*
* UUID functions
*/
uuid_t *sdp_uuid16_create(uuid_t *uuid, uint16_t data);
uuid_t *sdp_uuid32_create(uuid_t *uuid, uint32_t data);
uuid_t *sdp_uuid128_create(uuid_t *uuid, const void *data);
int sdp_uuid16_cmp(const void *p1, const void *p2);
int sdp_uuid128_cmp(const void *p1, const void *p2);
int sdp_uuid_cmp(const void *p1, const void *p2);
uuid_t *sdp_uuid_to_uuid128(const uuid_t *uuid);
void sdp_uuid16_to_uuid128(uuid_t *uuid128, const uuid_t *uuid16);
void sdp_uuid32_to_uuid128(uuid_t *uuid128, const uuid_t *uuid32);
int sdp_uuid128_to_uuid(uuid_t *uuid);
int sdp_uuid_to_proto(uuid_t *uuid);
int sdp_uuid_extract(const uint8_t *buffer, int bufsize, uuid_t *uuid, int *scanned);
void sdp_uuid_print(const uuid_t *uuid);
#define MAX_LEN_UUID_STR 37
#define MAX_LEN_PROTOCOL_UUID_STR 8
#define MAX_LEN_SERVICECLASS_UUID_STR 28
#define MAX_LEN_PROFILEDESCRIPTOR_UUID_STR 28
int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n);
int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n);
int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n);
int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n);
/*
* In all the sdp_get_XXX(handle, XXX *xxx) functions below,
* the XXX * is set to point to the value, should it exist
* and 0 is returned. If the value does not exist, -1 is
* returned and errno set to ENODATA.
*
* In all the methods below, the memory management rules are
* simple. Don't free anything! The pointer returned, in the
* case of constructed types, is a pointer to the contents
* of the sdp_record_t.
*/
/*
* Get the access protocols from the service record
*/
int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **protos);
/*
* Get the additional access protocols from the service record
*/
int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **protos);
/*
* Extract the list of browse groups to which the service belongs.
* When set, seqp contains elements of GroupID (uint16_t)
*/
static inline int sdp_get_browse_groups(const sdp_record_t *rec, sdp_list_t **seqp)
{
return sdp_get_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seqp);
}
/*
* Extract language attribute meta-data of the service record.
* For each language in the service record, LangSeq has a struct of type
* sdp_lang_attr_t.
*/
int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq);
/*
* Extract the Bluetooth profile descriptor sequence from a record.
* Each element in the list is of type sdp_profile_desc_t
* which contains the UUID of the profile and its version number
* (encoded as major and minor in the high-order 8bits
* and low-order 8bits respectively of the uint16_t)
*/
int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDesc);
/*
* Extract SDP server version numbers
*
* Note: that this is an attribute of the SDP server only and
* contains a list of uint16_t each of which represent the
* major and minor SDP version numbers supported by this server
*/
int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **pVnumList);
int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid);
int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid);
int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState);
int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail);
int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo);
int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState);
static inline int sdp_get_service_name(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_SVCNAME_PRIMARY, str, len);
}
static inline int sdp_get_service_desc(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_SVCDESC_PRIMARY, str, len);
}
static inline int sdp_get_provider_name(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_PROVNAME_PRIMARY, str, len);
}
static inline int sdp_get_doc_url(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_DOC_URL, str, len);
}
static inline int sdp_get_clnt_exec_url(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_CLNT_EXEC_URL, str, len);
}
static inline int sdp_get_icon_url(const sdp_record_t *rec, char *str, int len)
{
return sdp_get_string_attr(rec, SDP_ATTR_ICON_URL, str, len);
}
/*
* Set the supported features
* sf should be a list of list with each feature data
* Returns 0 on success -1 on fail
*/
int sdp_set_supp_feat(sdp_record_t *rec, const sdp_list_t *sf);
/*
* Get the supported features
* seqp is set to a list of list with each feature data
* Returns 0 on success, if an error occurred -1 is returned and errno is set
*/
int sdp_get_supp_feat(const sdp_record_t *rec, sdp_list_t **seqp);
sdp_record_t *sdp_extract_pdu(const uint8_t *pdata, int bufsize, int *scanned);
sdp_record_t *sdp_copy_record(sdp_record_t *rec);
void sdp_data_print(sdp_data_t *data);
void sdp_print_service_attr(sdp_list_t *alist);
int sdp_attrid_comp_func(const void *key1, const void *key2);
void sdp_set_seq_len(uint8_t *ptr, uint32_t length);
void sdp_set_attrid(sdp_buf_t *pdu, uint16_t id);
void sdp_append_to_pdu(sdp_buf_t *dst, sdp_data_t *d);
void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len);
int sdp_gen_pdu(sdp_buf_t *pdu, sdp_data_t *data);
int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *pdu);
int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size);
sdp_data_t *sdp_extract_attr(const uint8_t *pdata, int bufsize, int *extractedLength, sdp_record_t *rec);
void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid);
void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq);
int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *req, uint8_t *rsp, uint32_t reqsize, uint32_t *rspsize);
void sdp_add_lang_attr(sdp_record_t *rec);
#ifdef __cplusplus
}
#endif
#endif /* __SDP_LIB_H */

312
bluez/bluez5/lib/uuid.c Normal file
View File

@ -0,0 +1,312 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "lib/bluetooth.h"
#include "uuid.h"
static uint128_t bluetooth_base_uuid = {
.data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
};
#define BASE_UUID16_OFFSET 2
#define BASE_UUID32_OFFSET 0
static void bt_uuid16_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
uint16_t be16;
dst->value.u128 = bluetooth_base_uuid;
dst->type = BT_UUID128;
/*
* No matter the system: 128-bit UUIDs should be stored
* as big-endian. 16-bit UUIDs are stored on host order.
*/
be16 = htons(src->value.u16);
memcpy(&dst->value.u128.data[BASE_UUID16_OFFSET], &be16, sizeof(be16));
}
static void bt_uuid32_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
uint32_t be32;
dst->value.u128 = bluetooth_base_uuid;
dst->type = BT_UUID128;
/*
* No matter the system: 128-bit UUIDs should be stored
* as big-endian. 32-bit UUIDs are stored on host order.
*/
be32 = htonl(src->value.u32);
memcpy(&dst->value.u128.data[BASE_UUID32_OFFSET], &be32, sizeof(be32));
}
void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
switch (src->type) {
case BT_UUID128:
*dst = *src;
break;
case BT_UUID32:
bt_uuid32_to_uuid128(src, dst);
break;
case BT_UUID16:
bt_uuid16_to_uuid128(src, dst);
break;
case BT_UUID_UNSPEC:
default:
break;
}
}
static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
{
return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
}
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID16;
btuuid->value.u16 = value;
return 0;
}
int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID32;
btuuid->value.u32 = value;
return 0;
}
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID128;
btuuid->value.u128 = value;
return 0;
}
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
{
bt_uuid_t u1, u2;
bt_uuid_to_uuid128(uuid1, &u1);
bt_uuid_to_uuid128(uuid2, &u2);
return bt_uuid128_cmp(&u1, &u2);
}
/*
* convert the UUID to string, copying a maximum of n characters.
*/
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
{
bt_uuid_t tmp;
unsigned int data0;
unsigned short data1;
unsigned short data2;
unsigned short data3;
unsigned int data4;
unsigned short data5;
const uint8_t *data;
if (!uuid || uuid->type == BT_UUID_UNSPEC) {
snprintf(str, n, "NULL");
return -EINVAL;
}
/* Convert to 128 Bit format */
bt_uuid_to_uuid128(uuid, &tmp);
data = (uint8_t *) &tmp.value.u128;
memcpy(&data0, &data[0], 4);
memcpy(&data1, &data[4], 2);
memcpy(&data2, &data[6], 2);
memcpy(&data3, &data[8], 2);
memcpy(&data4, &data[10], 4);
memcpy(&data5, &data[14], 2);
snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
ntohl(data0), ntohs(data1),
ntohs(data2), ntohs(data3),
ntohl(data4), ntohs(data5));
return 0;
}
static inline int is_uuid128(const char *string)
{
return (strlen(string) == 36 &&
string[8] == '-' &&
string[13] == '-' &&
string[18] == '-' &&
string[23] == '-');
}
static inline int is_base_uuid128(const char *string)
{
uint16_t uuid;
char dummy[2];
if (!is_uuid128(string))
return 0;
return sscanf(string,
"0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]",
&uuid, dummy, dummy, dummy, dummy) == 5;
}
static inline int is_uuid32(const char *string)
{
return (strlen(string) == 8 || strlen(string) == 10);
}
static inline int is_uuid16(const char *string)
{
return (strlen(string) == 4 || strlen(string) == 6);
}
static int bt_string_to_uuid16(bt_uuid_t *uuid, const char *string)
{
uint16_t u16;
char *endptr = NULL;
u16 = strtol(string, &endptr, 16);
if (endptr && (*endptr == '\0' || *endptr == '-')) {
bt_uuid16_create(uuid, u16);
return 0;
}
return -EINVAL;
}
static int bt_string_to_uuid32(bt_uuid_t *uuid, const char *string)
{
uint32_t u32;
char *endptr = NULL;
u32 = strtol(string, &endptr, 16);
if (endptr && *endptr == '\0') {
bt_uuid32_create(uuid, u32);
return 0;
}
return -EINVAL;
}
static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string)
{
uint32_t data0, data4;
uint16_t data1, data2, data3, data5;
uint128_t u128;
uint8_t *val = (uint8_t *) &u128;
if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
&data0, &data1, &data2,
&data3, &data4, &data5) != 6)
return -EINVAL;
data0 = htonl(data0);
data1 = htons(data1);
data2 = htons(data2);
data3 = htons(data3);
data4 = htonl(data4);
data5 = htons(data5);
memcpy(&val[0], &data0, 4);
memcpy(&val[4], &data1, 2);
memcpy(&val[6], &data2, 2);
memcpy(&val[8], &data3, 2);
memcpy(&val[10], &data4, 4);
memcpy(&val[14], &data5, 2);
bt_uuid128_create(uuid, u128);
return 0;
}
int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
{
if (is_base_uuid128(string))
return bt_string_to_uuid16(uuid, string + 4);
else if (is_uuid128(string))
return bt_string_to_uuid128(uuid, string);
else if (is_uuid32(string))
return bt_string_to_uuid32(uuid, string);
else if (is_uuid16(string))
return bt_string_to_uuid16(uuid, string);
return -EINVAL;
}
int bt_uuid_strcmp(const void *a, const void *b)
{
bt_uuid_t u1, u2;
if (bt_string_to_uuid(&u1, a) < 0)
return -EINVAL;
if (bt_string_to_uuid(&u2, b) < 0)
return -EINVAL;
return bt_uuid_cmp(&u1, &u2);
}
int bt_uuid_to_le(const bt_uuid_t *src, void *dst)
{
bt_uuid_t uuid;
switch (src->type) {
case BT_UUID16:
bt_put_le16(src->value.u16, dst);
return 0;
case BT_UUID32:
bt_uuid32_to_uuid128(src, &uuid);
src = &uuid;
/* Fallthrough */
case BT_UUID128:
/* Convert from 128-bit BE to LE */
bswap_128(&src->value.u128, dst);
return 0;
case BT_UUID_UNSPEC:
default:
return -EINVAL;
}
}

181
bluez/bluez5/lib/uuid.h Normal file
View File

@ -0,0 +1,181 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __BLUETOOTH_UUID_H
#define __BLUETOOTH_UUID_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805f9b34fb"
#define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb"
#define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb"
#define HFP_HS_UUID "0000111e-0000-1000-8000-00805f9b34fb"
#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
#define ADVANCED_AUDIO_UUID "0000110d-0000-1000-8000-00805f9b34fb"
#define A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb"
#define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
#define AVRCP_REMOTE_UUID "0000110e-0000-1000-8000-00805f9b34fb"
#define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb"
#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
#define BNEP_SVC_UUID "0000000f-0000-1000-8000-00805f9b34fb"
#define PNPID_UUID "00002a50-0000-1000-8000-00805f9b34fb"
#define DEVICE_INFORMATION_UUID "0000180a-0000-1000-8000-00805f9b34fb"
#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb"
#define IMMEDIATE_ALERT_UUID "00001802-0000-1000-8000-00805f9b34fb"
#define LINK_LOSS_UUID "00001803-0000-1000-8000-00805f9b34fb"
#define TX_POWER_UUID "00001804-0000-1000-8000-00805f9b34fb"
#define BATTERY_UUID "0000180f-0000-1000-8000-00805f9b34fb"
#define SCAN_PARAMETERS_UUID "00001813-0000-1000-8000-00805f9b34fb"
#define SAP_UUID "0000112D-0000-1000-8000-00805f9b34fb"
#define HEART_RATE_UUID "0000180d-0000-1000-8000-00805f9b34fb"
#define HEART_RATE_MEASUREMENT_UUID "00002a37-0000-1000-8000-00805f9b34fb"
#define BODY_SENSOR_LOCATION_UUID "00002a38-0000-1000-8000-00805f9b34fb"
#define HEART_RATE_CONTROL_POINT_UUID "00002a39-0000-1000-8000-00805f9b34fb"
#define HEALTH_THERMOMETER_UUID "00001809-0000-1000-8000-00805f9b34fb"
#define TEMPERATURE_MEASUREMENT_UUID "00002a1c-0000-1000-8000-00805f9b34fb"
#define TEMPERATURE_TYPE_UUID "00002a1d-0000-1000-8000-00805f9b34fb"
#define INTERMEDIATE_TEMPERATURE_UUID "00002a1e-0000-1000-8000-00805f9b34fb"
#define MEASUREMENT_INTERVAL_UUID "00002a21-0000-1000-8000-00805f9b34fb"
#define CYCLING_SC_UUID "00001816-0000-1000-8000-00805f9b34fb"
#define CSC_MEASUREMENT_UUID "00002a5b-0000-1000-8000-00805f9b34fb"
#define CSC_FEATURE_UUID "00002a5c-0000-1000-8000-00805f9b34fb"
#define SENSOR_LOCATION_UUID "00002a5d-0000-1000-8000-00805f9b34fb"
#define SC_CONTROL_POINT_UUID "00002a55-0000-1000-8000-00805f9b34fb"
#define RFCOMM_UUID_STR "00000003-0000-1000-8000-00805f9b34fb"
#define HDP_UUID "00001400-0000-1000-8000-00805f9b34fb"
#define HDP_SOURCE_UUID "00001401-0000-1000-8000-00805f9b34fb"
#define HDP_SINK_UUID "00001402-0000-1000-8000-00805f9b34fb"
#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
#define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb"
#define GAP_UUID "00001800-0000-1000-8000-00805f9b34fb"
#define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb"
#define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
#define OBEX_SYNC_UUID "00001104-0000-1000-8000-00805f9b34fb"
#define OBEX_OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
#define OBEX_FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
#define OBEX_PCE_UUID "0000112e-0000-1000-8000-00805f9b34fb"
#define OBEX_PSE_UUID "0000112f-0000-1000-8000-00805f9b34fb"
#define OBEX_PBAP_UUID "00001130-0000-1000-8000-00805f9b34fb"
#define OBEX_MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
#define OBEX_MNS_UUID "00001133-0000-1000-8000-00805f9b34fb"
#define OBEX_MAP_UUID "00001134-0000-1000-8000-00805f9b34fb"
/* GATT UUIDs section */
#define GATT_PRIM_SVC_UUID 0x2800
#define GATT_SND_SVC_UUID 0x2801
#define GATT_INCLUDE_UUID 0x2802
#define GATT_CHARAC_UUID 0x2803
/* GATT Characteristic Types */
#define GATT_CHARAC_DEVICE_NAME 0x2A00
#define GATT_CHARAC_APPEARANCE 0x2A01
#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02
#define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03
#define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04
#define GATT_CHARAC_SERVICE_CHANGED 0x2A05
#define GATT_CHARAC_SYSTEM_ID 0x2A23
#define GATT_CHARAC_MODEL_NUMBER_STRING 0x2A24
#define GATT_CHARAC_SERIAL_NUMBER_STRING 0x2A25
#define GATT_CHARAC_FIRMWARE_REVISION_STRING 0x2A26
#define GATT_CHARAC_HARDWARE_REVISION_STRING 0x2A27
#define GATT_CHARAC_SOFTWARE_REVISION_STRING 0x2A28
#define GATT_CHARAC_MANUFACTURER_NAME_STRING 0x2A29
#define GATT_CHARAC_PNP_ID 0x2A50
/* GATT Characteristic Descriptors */
#define GATT_CHARAC_EXT_PROPER_UUID 0x2900
#define GATT_CHARAC_USER_DESC_UUID 0x2901
#define GATT_CLIENT_CHARAC_CFG_UUID 0x2902
#define GATT_SERVER_CHARAC_CFG_UUID 0x2903
#define GATT_CHARAC_FMT_UUID 0x2904
#define GATT_CHARAC_AGREG_FMT_UUID 0x2905
#define GATT_CHARAC_VALID_RANGE_UUID 0x2906
#define GATT_EXTERNAL_REPORT_REFERENCE 0x2907
#define GATT_REPORT_REFERENCE 0x2908
typedef struct {
enum {
BT_UUID_UNSPEC = 0,
BT_UUID16 = 16,
BT_UUID32 = 32,
BT_UUID128 = 128,
} type;
union {
uint16_t u16;
uint32_t u32;
uint128_t u128;
} value;
} bt_uuid_t;
int bt_uuid_strcmp(const void *a, const void *b);
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value);
int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value);
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value);
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2);
void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
#define MAX_LEN_UUID_STR 37
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
int bt_uuid_to_le(const bt_uuid_t *uuid, void *dst);
static inline int bt_uuid_len(const bt_uuid_t *uuid)
{
return uuid->type / 8;
}
#ifdef __cplusplus
}
#endif
#endif /* __BLUETOOTH_UUID_H */

3136
bluez/bluez5/monitor/bt.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
#ifndef __UHID_H_
#define __UHID_H_
/*
* User-space I/O driver support for HID subsystem
* Copyright (c) 2012 David Herrmann
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/*
* Public header for user-space communication. We try to keep every structure
* aligned but to be safe we also use __attribute__((__packed__)). Therefore,
* the communication should be ABI compatible even between architectures.
*/
#include <linux/input.h>
#include <linux/types.h>
#include <linux/hid.h>
enum uhid_event_type {
__UHID_LEGACY_CREATE,
UHID_DESTROY,
UHID_START,
UHID_STOP,
UHID_OPEN,
UHID_CLOSE,
UHID_OUTPUT,
__UHID_LEGACY_OUTPUT_EV,
__UHID_LEGACY_INPUT,
UHID_GET_REPORT,
UHID_GET_REPORT_REPLY,
UHID_CREATE2,
UHID_INPUT2,
UHID_SET_REPORT,
UHID_SET_REPORT_REPLY,
};
struct uhid_create2_req {
__u8 name[128];
__u8 phys[64];
__u8 uniq[64];
__u16 rd_size;
__u16 bus;
__u32 vendor;
__u32 product;
__u32 version;
__u32 country;
__u8 rd_data[HID_MAX_DESCRIPTOR_SIZE];
} __attribute__((__packed__));
enum uhid_dev_flag {
UHID_DEV_NUMBERED_FEATURE_REPORTS = (1ULL << 0),
UHID_DEV_NUMBERED_OUTPUT_REPORTS = (1ULL << 1),
UHID_DEV_NUMBERED_INPUT_REPORTS = (1ULL << 2),
};
struct uhid_start_req {
__u64 dev_flags;
};
#define UHID_DATA_MAX 4096
enum uhid_report_type {
UHID_FEATURE_REPORT,
UHID_OUTPUT_REPORT,
UHID_INPUT_REPORT,
};
struct uhid_input2_req {
__u16 size;
__u8 data[UHID_DATA_MAX];
} __attribute__((__packed__));
struct uhid_output_req {
__u8 data[UHID_DATA_MAX];
__u16 size;
__u8 rtype;
} __attribute__((__packed__));
struct uhid_get_report_req {
__u32 id;
__u8 rnum;
__u8 rtype;
} __attribute__((__packed__));
struct uhid_get_report_reply_req {
__u32 id;
__u16 err;
__u16 size;
__u8 data[UHID_DATA_MAX];
} __attribute__((__packed__));
struct uhid_set_report_req {
__u32 id;
__u8 rnum;
__u8 rtype;
__u16 size;
__u8 data[UHID_DATA_MAX];
} __attribute__((__packed__));
struct uhid_set_report_reply_req {
__u32 id;
__u16 err;
} __attribute__((__packed__));
/*
* Compat Layer
* All these commands and requests are obsolete. You should avoid using them in
* new code. We support them for backwards-compatibility, but you might not get
* access to new feature in case you use them.
*/
enum uhid_legacy_event_type {
UHID_CREATE = __UHID_LEGACY_CREATE,
UHID_OUTPUT_EV = __UHID_LEGACY_OUTPUT_EV,
UHID_INPUT = __UHID_LEGACY_INPUT,
UHID_FEATURE = UHID_GET_REPORT,
UHID_FEATURE_ANSWER = UHID_GET_REPORT_REPLY,
};
/* Obsolete! Use UHID_CREATE2. */
struct uhid_create_req {
__u8 name[128];
__u8 phys[64];
__u8 uniq[64];
__u8 *rd_data;
__u16 rd_size;
__u16 bus;
__u32 vendor;
__u32 product;
__u32 version;
__u32 country;
} __attribute__((__packed__));
/* Obsolete! Use UHID_INPUT2. */
struct uhid_input_req {
__u8 data[UHID_DATA_MAX];
__u16 size;
} __attribute__((__packed__));
/* Obsolete! Kernel uses UHID_OUTPUT exclusively now. */
struct uhid_output_ev_req {
__u16 type;
__u16 code;
__s32 value;
} __attribute__((__packed__));
/* Obsolete! Kernel uses ABI compatible UHID_GET_REPORT. */
struct uhid_feature_req {
__u32 id;
__u8 rnum;
__u8 rtype;
} __attribute__((__packed__));
/* Obsolete! Use ABI compatible UHID_GET_REPORT_REPLY. */
struct uhid_feature_answer_req {
__u32 id;
__u16 err;
__u16 size;
__u8 data[UHID_DATA_MAX];
} __attribute__((__packed__));
/*
* UHID Events
* All UHID events from and to the kernel are encoded as "struct uhid_event".
* The "type" field contains a UHID_* type identifier. All payload depends on
* that type and can be accessed via ev->u.XYZ accordingly.
* If user-space writes short events, they're extended with 0s by the kernel. If
* the kernel writes short events, user-space shall extend them with 0s.
*/
struct uhid_event {
__u32 type;
union {
struct uhid_create_req create;
struct uhid_input_req input;
struct uhid_output_req output;
struct uhid_output_ev_req output_ev;
struct uhid_feature_req feature;
struct uhid_get_report_req get_report;
struct uhid_feature_answer_req feature_answer;
struct uhid_get_report_reply_req get_report_reply;
struct uhid_create2_req create2;
struct uhid_input2_req input2;
struct uhid_set_report_req set_report;
struct uhid_set_report_reply_req set_report_reply;
struct uhid_start_req start;
} u;
} __attribute__((__packed__));
#endif /* __UHID_H_ */

104
bluez/bluez5/src/eir.h Normal file
View File

@ -0,0 +1,104 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <glib.h>
#include "lib/sdp.h"
#define EIR_FLAGS 0x01 /* flags */
#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
#define EIR_NAME_SHORT 0x08 /* shortened local name */
#define EIR_NAME_COMPLETE 0x09 /* complete local name */
#define EIR_TX_POWER 0x0A /* transmit power level */
#define EIR_CLASS_OF_DEV 0x0D /* Class of Device */
#define EIR_SSP_HASH 0x0E /* SSP Hash */
#define EIR_SSP_RANDOMIZER 0x0F /* SSP Randomizer */
#define EIR_DEVICE_ID 0x10 /* device ID */
#define EIR_SOLICIT16 0x14 /* LE: Solicit UUIDs, 16-bit */
#define EIR_SOLICIT128 0x15 /* LE: Solicit UUIDs, 128-bit */
#define EIR_SVC_DATA16 0x16 /* LE: Service data, 16-bit UUID */
#define EIR_PUB_TRGT_ADDR 0x17 /* LE: Public Target Address */
#define EIR_RND_TRGT_ADDR 0x18 /* LE: Random Target Address */
#define EIR_GAP_APPEARANCE 0x19 /* GAP appearance */
#define EIR_SOLICIT32 0x1F /* LE: Solicit UUIDs, 32-bit */
#define EIR_SVC_DATA32 0x20 /* LE: Service data, 32-bit UUID */
#define EIR_SVC_DATA128 0x21 /* LE: Service data, 128-bit UUID */
#define EIR_MANUFACTURER_DATA 0xFF /* Manufacturer Specific Data */
/* Flags Descriptions */
#define EIR_LIM_DISC 0x01 /* LE Limited Discoverable Mode */
#define EIR_GEN_DISC 0x02 /* LE General Discoverable Mode */
#define EIR_BREDR_UNSUP 0x04 /* BR/EDR Not Supported */
#define EIR_CONTROLLER 0x08 /* Simultaneous LE and BR/EDR to Same
Device Capable (Controller) */
#define EIR_SIM_HOST 0x10 /* Simultaneous LE and BR/EDR to Same
Device Capable (Host) */
#define EIR_SD_MAX_LEN 238 /* 240 (EIR) - 2 (len) */
#define EIR_MSD_MAX_LEN 236 /* 240 (EIR) - 2 (len & type) - 2 */
struct eir_msd {
uint16_t company;
uint8_t data[EIR_MSD_MAX_LEN];
uint8_t data_len;
};
struct eir_sd {
char *uuid;
uint8_t data[EIR_SD_MAX_LEN];
uint8_t data_len;
};
struct eir_data {
GSList *services;
unsigned int flags;
char *name;
uint32_t class;
uint16_t appearance;
bool name_complete;
int8_t tx_power;
uint8_t *hash;
uint8_t *randomizer;
bdaddr_t addr;
uint16_t did_vendor;
uint16_t did_product;
uint16_t did_version;
uint16_t did_source;
GSList *msd_list;
GSList *sd_list;
};
void eir_data_free(struct eir_data *eir);
void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len);
int eir_parse_oob(struct eir_data *eir, uint8_t *eir_data, uint16_t eir_len);
int eir_create_oob(const bdaddr_t *addr, const char *name, uint32_t cod,
const uint8_t *hash, const uint8_t *randomizer,
uint16_t did_vendor, uint16_t did_product,
uint16_t did_version, uint16_t did_source,
sdp_list_t *uuids, uint8_t *data);

331
bluez/bluez5/src/log.c Normal file
View File

@ -0,0 +1,331 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <glib.h>
#include "lib/bluetooth.h"
#include "lib/hci.h"
#include "src/shared/util.h"
#include "log.h"
#define LOG_IDENT "bluetoothd"
#define LOG_IDENT_LEN sizeof(LOG_IDENT)
struct log_hdr {
uint16_t opcode;
uint16_t index;
uint16_t len;
uint8_t priority;
uint8_t ident_len;
} __attribute__((packed));
static int logging_fd = -1;
static void logging_open(void)
{
struct sockaddr_hci addr;
int fd;
if (logging_fd >= 0)
return;
fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (fd < 0)
return;
memset(&addr, 0, sizeof(addr));
addr.hci_family = AF_BLUETOOTH;
addr.hci_dev = HCI_DEV_NONE;
addr.hci_channel = HCI_CHANNEL_LOGGING;
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(fd);
return;
}
logging_fd = fd;
}
static void logging_close(void)
{
if (logging_fd >= 0) {
close(logging_fd);
logging_fd = -1;
}
}
static void logging_log(uint16_t index, int priority,
const char *format, va_list ap)
{
struct log_hdr hdr;
struct msghdr msg;
struct iovec iov[3];
uint16_t len;
char *str;
if (vasprintf(&str, format, ap) < 0)
return;
len = strlen(str) + 1;
hdr.opcode = cpu_to_le16(0x0000);
hdr.index = cpu_to_le16(index);
hdr.len = cpu_to_le16(2 + LOG_IDENT_LEN + len);
hdr.priority = priority;
hdr.ident_len = LOG_IDENT_LEN;
iov[0].iov_base = &hdr;
iov[0].iov_len = sizeof(hdr);
iov[1].iov_base = LOG_IDENT;
iov[1].iov_len = LOG_IDENT_LEN;
iov[2].iov_base = str;
iov[2].iov_len = len;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = 3;
if (sendmsg(logging_fd, &msg, 0) < 0) {
if (errno != ENODEV) {
close(logging_fd);
logging_fd = -1;
}
}
free(str);
}
void error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_ERR, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(HCI_DEV_NONE, LOG_ERR, format, ap);
va_end(ap);
}
void warn(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_WARNING, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(HCI_DEV_NONE, LOG_WARNING, format, ap);
va_end(ap);
}
void info(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_INFO, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(HCI_DEV_NONE, LOG_INFO, format, ap);
va_end(ap);
}
void btd_log(uint16_t index, int priority, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(priority, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(index, priority, format, ap);
va_end(ap);
}
void btd_error(uint16_t index, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_ERR, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(index, LOG_ERR, format, ap);
va_end(ap);
}
void btd_warn(uint16_t index, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_WARNING, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(index, LOG_WARNING, format, ap);
va_end(ap);
}
void btd_info(uint16_t index, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_INFO, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(index, LOG_INFO, format, ap);
va_end(ap);
}
void btd_debug(uint16_t index, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsyslog(LOG_DEBUG, format, ap);
va_end(ap);
if (logging_fd < 0)
return;
va_start(ap, format);
logging_log(index, LOG_DEBUG, format, ap);
va_end(ap);
}
extern struct btd_debug_desc __start___debug[];
extern struct btd_debug_desc __stop___debug[];
static char **enabled = NULL;
static gboolean is_enabled(struct btd_debug_desc *desc)
{
int i;
if (enabled == NULL)
return 0;
for (i = 0; enabled[i] != NULL; i++)
if (desc->file != NULL && g_pattern_match_simple(enabled[i],
desc->file) == TRUE)
return 1;
return 0;
}
void __btd_enable_debug(struct btd_debug_desc *start,
struct btd_debug_desc *stop)
{
struct btd_debug_desc *desc;
if (start == NULL || stop == NULL)
return;
for (desc = start; desc < stop; desc++) {
if (is_enabled(desc))
desc->flags |= BTD_DEBUG_FLAG_PRINT;
}
}
void __btd_toggle_debug(void)
{
struct btd_debug_desc *desc;
for (desc = __start___debug; desc < __stop___debug; desc++)
desc->flags |= BTD_DEBUG_FLAG_PRINT;
}
void __btd_log_init(const char *debug, int detach)
{
int option = LOG_NDELAY | LOG_PID;
if (debug != NULL)
enabled = g_strsplit_set(debug, ":, ", 0);
__btd_enable_debug(__start___debug, __stop___debug);
logging_open();
if (!detach)
option |= LOG_PERROR;
openlog(LOG_IDENT, option, LOG_DAEMON);
info("Bluetooth daemon %d.%d", BLUEZ_VERSION_MAJOR, BLUEZ_VERSION_MINOR);
}
void __btd_log_cleanup(void)
{
closelog();
logging_close();
g_strfreev(enabled);
}

73
bluez/bluez5/src/log.h Normal file
View File

@ -0,0 +1,73 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
void error(const char *format, ...) __attribute__((format(printf, 1, 2)));
void warn(const char *format, ...) __attribute__((format(printf, 1, 2)));
void info(const char *format, ...) __attribute__((format(printf, 1, 2)));
void btd_log(uint16_t index, int priority, const char *format, ...)
__attribute__((format(printf, 3, 4)));
void btd_error(uint16_t index, const char *format, ...)
__attribute__((format(printf, 2, 3)));
void btd_warn(uint16_t index, const char *format, ...)
__attribute__((format(printf, 2, 3)));
void btd_info(uint16_t index, const char *format, ...)
__attribute__((format(printf, 2, 3)));
void btd_debug(uint16_t index, const char *format, ...)
__attribute__((format(printf, 2, 3)));
void __btd_log_init(const char *debug, int detach);
void __btd_log_cleanup(void);
void __btd_toggle_debug(void);
struct btd_debug_desc {
const char *file;
#define BTD_DEBUG_FLAG_DEFAULT (0)
#define BTD_DEBUG_FLAG_PRINT (1 << 0)
unsigned int flags;
} __attribute__((aligned(8)));
void __btd_enable_debug(struct btd_debug_desc *start,
struct btd_debug_desc *stop);
/**
* DBG:
* @fmt: format string
* @arg...: list of arguments
*
* Simple macro around btd_debug() which also include the function
* name it is called in.
*/
#define DBG_IDX(idx, fmt, arg...) do { \
static struct btd_debug_desc __btd_debug_desc \
__attribute__((used, section("__debug"), aligned(8))) = { \
.file = __FILE__, .flags = BTD_DEBUG_FLAG_DEFAULT, \
}; \
if (__btd_debug_desc.flags & BTD_DEBUG_FLAG_PRINT) \
btd_debug(idx, "%s:%s() " fmt, __FILE__, __func__ , ## arg); \
} while (0)
#define DBG(fmt, arg...) DBG_IDX(0xffff, fmt, ## arg)

View File

@ -0,0 +1,658 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2015 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "src/shared/ad.h"
#include "src/eir.h"
#include "src/shared/queue.h"
#include "src/shared/util.h"
#define MAX_ADV_DATA_LEN 31
struct bt_ad {
int ref_count;
struct queue *service_uuids;
struct queue *manufacturer_data;
struct queue *solicit_uuids;
struct queue *service_data;
};
struct bt_ad *bt_ad_new(void)
{
struct bt_ad *ad;
ad = new0(struct bt_ad, 1);
ad->service_uuids = queue_new();
ad->manufacturer_data = queue_new();
ad->solicit_uuids = queue_new();
ad->service_data = queue_new();
return bt_ad_ref(ad);
}
struct bt_ad *bt_ad_ref(struct bt_ad *ad)
{
if (!ad)
return NULL;
ad->ref_count++;
return ad;
}
static void uuid_destroy(void *data)
{
struct bt_ad_service_data *uuid_data = data;
free(uuid_data->data);
free(uuid_data);
}
static bool uuid_data_match(const void *data, const void *elem)
{
const struct bt_ad_service_data *uuid_data = elem;
const bt_uuid_t *uuid = data;
return !bt_uuid_cmp(&uuid_data->uuid, uuid);
}
static void manuf_destroy(void *data)
{
struct bt_ad_manufacturer_data *manuf = data;
free(manuf->data);
free(manuf);
}
static bool manuf_match(const void *data, const void *elem)
{
const struct bt_ad_manufacturer_data *manuf = elem;
uint16_t manuf_id = PTR_TO_UINT(elem);
return manuf->manufacturer_id == manuf_id;
}
void bt_ad_unref(struct bt_ad *ad)
{
if (!ad)
return;
if (__sync_sub_and_fetch(&ad->ref_count, 1))
return;
queue_destroy(ad->service_uuids, free);
queue_destroy(ad->manufacturer_data, manuf_destroy);
queue_destroy(ad->solicit_uuids, free);
queue_destroy(ad->service_data, uuid_destroy);
free(ad);
}
static size_t uuid_list_length(struct queue *uuid_queue)
{
bool uuid16_included = false;
bool uuid32_included = false;
bool uuid128_included = false;
size_t length = 0;
const struct queue_entry *entry;
entry = queue_get_entries(uuid_queue);
while (entry) {
bt_uuid_t *uuid = entry->data;
length += bt_uuid_len(uuid);
if (uuid->type == BT_UUID16)
uuid16_included = true;
else if (uuid->type == BT_UUID32)
uuid32_included = true;
else
uuid128_included = true;
entry = entry->next;
}
if (uuid16_included)
length += 2;
if (uuid32_included)
length += 2;
if (uuid128_included)
length += 2;
return length;
}
static size_t mfg_data_length(struct queue *manuf_data)
{
size_t length = 0;
const struct queue_entry *entry;
entry = queue_get_entries(manuf_data);
while (entry) {
struct bt_ad_manufacturer_data *data = entry->data;
length += 2 + sizeof(uint16_t) + data->len;
entry = entry->next;
}
return length;
}
static size_t uuid_data_length(struct queue *uuid_data)
{
size_t length = 0;
const struct queue_entry *entry;
entry = queue_get_entries(uuid_data);
while (entry) {
struct bt_ad_service_data *data = entry->data;
length += 2 + bt_uuid_len(&data->uuid) + data->len;
entry = entry->next;
}
return length;
}
static size_t calculate_length(struct bt_ad *ad)
{
size_t length = 0;
length += uuid_list_length(ad->service_uuids);
length += uuid_list_length(ad->solicit_uuids);
length += mfg_data_length(ad->manufacturer_data);
length += uuid_data_length(ad->service_data);
return length;
}
static void serialize_uuids(struct queue *uuids, uint8_t uuid_type,
uint8_t ad_type, uint8_t *buf,
uint8_t *pos)
{
const struct queue_entry *entry = queue_get_entries(uuids);
bool added = false;
uint8_t length_pos = 0;
while (entry) {
bt_uuid_t *uuid = entry->data;
if (uuid->type == uuid_type) {
if (!added) {
length_pos = (*pos)++;
buf[(*pos)++] = ad_type;
added = true;
}
if (uuid_type != BT_UUID32)
bt_uuid_to_le(uuid, buf + *pos);
else
bt_put_le32(uuid->value.u32, buf + *pos);
*pos += bt_uuid_len(uuid);
}
entry = entry->next;
}
if (added)
buf[length_pos] = *pos - length_pos - 1;
}
static void serialize_service_uuids(struct queue *uuids, uint8_t *buf,
uint8_t *pos)
{
serialize_uuids(uuids, BT_UUID16, EIR_UUID16_ALL, buf, pos);
serialize_uuids(uuids, BT_UUID32, EIR_UUID32_ALL, buf, pos);
serialize_uuids(uuids, BT_UUID128, EIR_UUID128_ALL, buf, pos);
}
static void serialize_solicit_uuids(struct queue *uuids, uint8_t *buf,
uint8_t *pos)
{
serialize_uuids(uuids, BT_UUID16, EIR_SOLICIT16, buf, pos);
serialize_uuids(uuids, BT_UUID32, EIR_SOLICIT32, buf, pos);
serialize_uuids(uuids, BT_UUID128, EIR_SOLICIT128, buf, pos);
}
static void serialize_manuf_data(struct queue *manuf_data, uint8_t *buf,
uint8_t *pos)
{
const struct queue_entry *entry = queue_get_entries(manuf_data);
while (entry) {
struct bt_ad_manufacturer_data *data = entry->data;
buf[(*pos)++] = data->len + 2 + 1;
buf[(*pos)++] = EIR_MANUFACTURER_DATA;
bt_put_le16(data->manufacturer_id, buf + (*pos));
*pos += 2;
memcpy(buf + *pos, data->data, data->len);
*pos += data->len;
entry = entry->next;
}
}
static void serialize_service_data(struct queue *service_data, uint8_t *buf,
uint8_t *pos)
{
const struct queue_entry *entry = queue_get_entries(service_data);
while (entry) {
struct bt_ad_service_data *data = entry->data;
int uuid_len = bt_uuid_len(&data->uuid);
buf[(*pos)++] = uuid_len + data->len + 1;
switch (uuid_len) {
case 2:
buf[(*pos)++] = EIR_SVC_DATA16;
break;
case 4:
buf[(*pos)++] = EIR_SVC_DATA32;
break;
case 16:
buf[(*pos)++] = EIR_SVC_DATA128;
break;
}
if (uuid_len != 4)
bt_uuid_to_le(&data->uuid, buf + *pos);
else
bt_put_le32(data->uuid.value.u32, buf + *pos);
*pos += uuid_len;
memcpy(buf + *pos, data->data, data->len);
*pos += data->len;
entry = entry->next;
}
}
uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
{
uint8_t *adv_data;
uint8_t pos = 0;
if (!ad)
return NULL;
*length = calculate_length(ad);
if (*length > MAX_ADV_DATA_LEN)
return NULL;
adv_data = malloc0(*length);
if (!adv_data)
return NULL;
serialize_service_uuids(ad->service_uuids, adv_data, &pos);
serialize_solicit_uuids(ad->solicit_uuids, adv_data, &pos);
serialize_manuf_data(ad->manufacturer_data, adv_data, &pos);
serialize_service_data(ad->service_data, adv_data, &pos);
return adv_data;
}
static bool queue_add_uuid(struct queue *queue, const bt_uuid_t *uuid)
{
bt_uuid_t *new_uuid;
if (!queue)
return false;
new_uuid = new0(bt_uuid_t, 1);
*new_uuid = *uuid;
if (queue_push_tail(queue, new_uuid))
return true;
free(new_uuid);
return false;
}
static bool uuid_match(const void *data, const void *elem)
{
const bt_uuid_t *match_uuid = data;
const bt_uuid_t *uuid = elem;
return bt_uuid_cmp(match_uuid, uuid);
}
static bool queue_remove_uuid(struct queue *queue, bt_uuid_t *uuid)
{
bt_uuid_t *removed;
if (!queue || !uuid)
return false;
removed = queue_remove_if(queue, uuid_match, uuid);
if (removed) {
free(removed);
return true;
}
return false;
}
bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
{
if (!ad)
return false;
return queue_add_uuid(ad->service_uuids, uuid);
}
bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid)
{
if (!ad)
return false;
return queue_remove_uuid(ad->service_uuids, uuid);
}
void bt_ad_clear_service_uuid(struct bt_ad *ad)
{
if (!ad)
return;
queue_remove_all(ad->service_uuids, NULL, NULL, free);
}
static bool manufacturer_id_data_match(const void *data, const void *user_data)
{
const struct bt_ad_manufacturer_data *m = data;
uint16_t id = PTR_TO_UINT(user_data);
return m->manufacturer_id == id;
}
bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_id,
void *data, size_t len)
{
struct bt_ad_manufacturer_data *new_data;
if (!ad)
return false;
if (len > (MAX_ADV_DATA_LEN - 2 - sizeof(uint16_t)))
return false;
new_data = queue_find(ad->manufacturer_data, manufacturer_id_data_match,
UINT_TO_PTR(manufacturer_id));
if (new_data) {
if (new_data->len == len && !memcmp(new_data->data, data, len))
return false;
new_data->data = realloc(new_data->data, len);
memcpy(new_data->data, data, len);
new_data->len = len;
return true;
}
new_data = new0(struct bt_ad_manufacturer_data, 1);
new_data->manufacturer_id = manufacturer_id;
new_data->data = malloc(len);
if (!new_data->data) {
free(new_data);
return false;
}
memcpy(new_data->data, data, len);
new_data->len = len;
if (queue_push_tail(ad->manufacturer_data, new_data))
return true;
manuf_destroy(new_data);
return false;
}
static bool manufacturer_data_match(const void *data, const void *user_data)
{
const struct bt_ad_manufacturer_data *m1 = data;
const struct bt_ad_manufacturer_data *m2 = user_data;
if (m1->manufacturer_id != m2->manufacturer_id)
return false;
if (m1->len != m2->len)
return false;
return !memcmp(m1->data, m2->data, m1->len);
}
bool bt_ad_has_manufacturer_data(struct bt_ad *ad,
const struct bt_ad_manufacturer_data *data)
{
if (!ad)
return false;
if (!data)
return !queue_isempty(ad->manufacturer_data);
return queue_find(ad->manufacturer_data, manufacturer_data_match, data);
}
void bt_ad_foreach_manufacturer_data(struct bt_ad *ad, bt_ad_func_t func,
void *user_data)
{
if (!ad)
return;
queue_foreach(ad->manufacturer_data, func, user_data);
}
bool bt_ad_remove_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_id)
{
struct bt_ad_manufacturer_data *data;
if (!ad)
return false;
data = queue_remove_if(ad->manufacturer_data, manuf_match,
UINT_TO_PTR(manufacturer_id));
if (!data)
return false;
manuf_destroy(data);
return true;
}
void bt_ad_clear_manufacturer_data(struct bt_ad *ad)
{
if (!ad)
return;
queue_remove_all(ad->manufacturer_data, NULL, NULL, manuf_destroy);
}
bool bt_ad_add_solicit_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
{
if (!ad)
return false;
return queue_add_uuid(ad->solicit_uuids, uuid);
}
bool bt_ad_remove_solicit_uuid(struct bt_ad *ad, bt_uuid_t *uuid)
{
if (!ad)
return false;
return queue_remove_uuid(ad->solicit_uuids, uuid);
}
void bt_ad_clear_solicit_uuid(struct bt_ad *ad)
{
if (!ad)
return;
queue_remove_all(ad->solicit_uuids, NULL, NULL, free);
}
static bool service_uuid_match(const void *data, const void *user_data)
{
const struct bt_ad_service_data *s = data;
const bt_uuid_t *uuid = user_data;
return !bt_uuid_cmp(&s->uuid, uuid);
}
bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void *data,
size_t len)
{
struct bt_ad_service_data *new_data;
if (!ad)
return false;
if (len > (MAX_ADV_DATA_LEN - 2 - (size_t)bt_uuid_len(uuid)))
return false;
new_data = queue_find(ad->service_data, service_uuid_match, uuid);
if (new_data) {
if (new_data->len == len && !memcmp(new_data->data, data, len))
return false;
new_data->data = realloc(new_data->data, len);
memcpy(new_data->data, data, len);
new_data->len = len;
return true;
}
new_data = new0(struct bt_ad_service_data, 1);
new_data->uuid = *uuid;
new_data->data = malloc(len);
if (!new_data->data) {
free(new_data);
return false;
}
memcpy(new_data->data, data, len);
new_data->len = len;
if (queue_push_tail(ad->service_data, new_data))
return true;
uuid_destroy(new_data);
return false;
}
static bool service_data_match(const void *data, const void *user_data)
{
const struct bt_ad_service_data *s1 = data;
const struct bt_ad_service_data *s2 = user_data;
if (bt_uuid_cmp(&s1->uuid, &s2->uuid))
return false;
if (s1->len != s2->len)
return false;
return !memcmp(s1->data, s2->data, s1->len);
}
bool bt_ad_has_service_data(struct bt_ad *ad,
const struct bt_ad_service_data *data)
{
if (!ad)
return false;
if (!data)
return !queue_isempty(ad->service_data);
return queue_find(ad->service_data, service_data_match, data);
}
void bt_ad_foreach_service_data(struct bt_ad *ad, bt_ad_func_t func,
void *user_data)
{
if (!ad)
return;
queue_foreach(ad->service_data, func, user_data);
}
bool bt_ad_remove_service_data(struct bt_ad *ad, bt_uuid_t *uuid)
{
struct bt_ad_service_data *data;
if (!ad)
return false;
data = queue_remove_if(ad->service_data, uuid_data_match, uuid);
if (!data)
return false;
uuid_destroy(data);
return true;
}
void bt_ad_clear_service_data(struct bt_ad *ad)
{
if (!ad)
return;
queue_remove_all(ad->service_data, NULL, NULL, uuid_destroy);
}

View File

@ -0,0 +1,90 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2015 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <inttypes.h>
#include <stdbool.h>
#include "lib/bluetooth.h"
#include "lib/uuid.h"
typedef void (*bt_ad_func_t)(void *data, void *user_data);
struct bt_ad;
struct bt_ad_manufacturer_data {
uint16_t manufacturer_id;
uint8_t *data;
size_t len;
};
struct bt_ad_service_data {
bt_uuid_t uuid;
uint8_t *data;
size_t len;
};
struct bt_ad *bt_ad_new(void);
struct bt_ad *bt_ad_ref(struct bt_ad *ad);
void bt_ad_unref(struct bt_ad *ad);
uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length);
bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid);
void bt_ad_clear_service_uuid(struct bt_ad *ad);
bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_data,
void *data, size_t len);
bool bt_ad_has_manufacturer_data(struct bt_ad *ad,
const struct bt_ad_manufacturer_data *data);
void bt_ad_foreach_manufacturer_data(struct bt_ad *ad, bt_ad_func_t func,
void *user_data);
bool bt_ad_remove_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_id);
void bt_ad_clear_manufacturer_data(struct bt_ad *ad);
bool bt_ad_add_solicit_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
bool bt_ad_remove_solicit_uuid(struct bt_ad *ad, bt_uuid_t *uuid);
void bt_ad_clear_solicit_uuid(struct bt_ad *ad);
bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void *data,
size_t len);
bool bt_ad_has_service_data(struct bt_ad *ad,
const struct bt_ad_service_data *data);
void bt_ad_foreach_service_data(struct bt_ad *ad, bt_ad_func_t func,
void *user_data);
bool bt_ad_remove_service_data(struct bt_ad *ad, bt_uuid_t *uuid);
void bt_ad_clear_service_data(struct bt_ad *ad);

View File

@ -0,0 +1,156 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#define BT_ATT_SECURITY_AUTO 0
#define BT_ATT_SECURITY_LOW 1
#define BT_ATT_SECURITY_MEDIUM 2
#define BT_ATT_SECURITY_HIGH 3
#define BT_ATT_SECURITY_FIPS 4
#define BT_ATT_DEFAULT_LE_MTU 23
#define BT_ATT_MAX_LE_MTU 517
#define BT_ATT_MAX_VALUE_LEN 512
#define BT_ATT_LINK_BREDR 0x00
#define BT_ATT_LINK_LE 0x01
#define BT_ATT_LINK_LOCAL 0xff
/* ATT protocol opcodes */
#define BT_ATT_OP_ERROR_RSP 0x01
#define BT_ATT_OP_MTU_REQ 0x02
#define BT_ATT_OP_MTU_RSP 0x03
#define BT_ATT_OP_FIND_INFO_REQ 0x04
#define BT_ATT_OP_FIND_INFO_RSP 0x05
#define BT_ATT_OP_FIND_BY_TYPE_REQ 0x06
#define BT_ATT_OP_FIND_BY_TYPE_RSP 0x07
#define BT_ATT_OP_READ_BY_TYPE_REQ 0x08
#define BT_ATT_OP_READ_BY_TYPE_RSP 0x09
#define BT_ATT_OP_READ_REQ 0x0a
#define BT_ATT_OP_READ_RSP 0x0b
#define BT_ATT_OP_READ_BLOB_REQ 0x0c
#define BT_ATT_OP_READ_BLOB_RSP 0x0d
#define BT_ATT_OP_READ_MULT_REQ 0x0e
#define BT_ATT_OP_READ_MULT_RSP 0x0f
#define BT_ATT_OP_READ_BY_GRP_TYPE_REQ 0x10
#define BT_ATT_OP_READ_BY_GRP_TYPE_RSP 0x11
#define BT_ATT_OP_WRITE_REQ 0x12
#define BT_ATT_OP_WRITE_RSP 0x13
#define BT_ATT_OP_WRITE_CMD 0x52
#define BT_ATT_OP_SIGNED_WRITE_CMD 0xD2
#define BT_ATT_OP_PREP_WRITE_REQ 0x16
#define BT_ATT_OP_PREP_WRITE_RSP 0x17
#define BT_ATT_OP_EXEC_WRITE_REQ 0x18
#define BT_ATT_OP_EXEC_WRITE_RSP 0x19
#define BT_ATT_OP_HANDLE_VAL_NOT 0x1B
#define BT_ATT_OP_HANDLE_VAL_IND 0x1D
#define BT_ATT_OP_HANDLE_VAL_CONF 0x1E
/* Packed struct definitions for ATT protocol PDUs */
/* TODO: Complete these definitions for all opcodes */
struct bt_att_pdu_error_rsp {
uint8_t opcode;
uint16_t handle;
uint8_t ecode;
} __packed;
/* Special opcode to receive all requests (legacy servers) */
#define BT_ATT_ALL_REQUESTS 0x00
/* Error codes for Error response PDU */
#define BT_ATT_ERROR_INVALID_HANDLE 0x01
#define BT_ATT_ERROR_READ_NOT_PERMITTED 0x02
#define BT_ATT_ERROR_WRITE_NOT_PERMITTED 0x03
#define BT_ATT_ERROR_INVALID_PDU 0x04
#define BT_ATT_ERROR_AUTHENTICATION 0x05
#define BT_ATT_ERROR_REQUEST_NOT_SUPPORTED 0x06
#define BT_ATT_ERROR_INVALID_OFFSET 0x07
#define BT_ATT_ERROR_AUTHORIZATION 0x08
#define BT_ATT_ERROR_PREPARE_QUEUE_FULL 0x09
#define BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND 0x0A
#define BT_ATT_ERROR_ATTRIBUTE_NOT_LONG 0x0B
#define BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE 0x0C
#define BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN 0x0D
#define BT_ATT_ERROR_UNLIKELY 0x0E
#define BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION 0x0F
#define BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE 0x10
#define BT_ATT_ERROR_INSUFFICIENT_RESOURCES 0x11
/*
* Common Profile and Service Error Code descriptions (see Supplement to the
* Bluetooth Core Specification, sections 1.2 and 2). The error codes within
* 0xE0-0xFC are reserved for future use. The remaining 3 are defined as the
* following:
*/
#define BT_ERROR_CCC_IMPROPERLY_CONFIGURED 0xfd
#define BT_ERROR_ALREADY_IN_PROGRESS 0xfe
#define BT_ERROR_OUT_OF_RANGE 0xff
/*
* ATT attribute permission bitfield values. Permissions are grouped as
* "Access", "Encryption", "Authentication", and "Authorization". A bitmask of
* permissions is a byte that encodes a combination of these.
*/
#define BT_ATT_PERM_READ 0x01
#define BT_ATT_PERM_WRITE 0x02
#define BT_ATT_PERM_READ_ENCRYPT 0x04
#define BT_ATT_PERM_WRITE_ENCRYPT 0x08
#define BT_ATT_PERM_ENCRYPT (BT_ATT_PERM_READ_ENCRYPT | \
BT_ATT_PERM_WRITE_ENCRYPT)
#define BT_ATT_PERM_READ_AUTHEN 0x10
#define BT_ATT_PERM_WRITE_AUTHEN 0x20
#define BT_ATT_PERM_AUTHEN (BT_ATT_PERM_READ_AUTHEN | \
BT_ATT_PERM_WRITE_AUTHEN)
#define BT_ATT_PERM_AUTHOR 0x40
#define BT_ATT_PERM_NONE 0x80
#define BT_ATT_PERM_READ_SECURE 0x0100
#define BT_ATT_PERM_WRITE_SECURE 0x0200
#define BT_ATT_PERM_SECURE (BT_ATT_PERM_READ_SECURE | \
BT_ATT_PERM_WRITE_SECURE)
/* GATT Characteristic Properties Bitfield values */
#define BT_GATT_CHRC_PROP_BROADCAST 0x01
#define BT_GATT_CHRC_PROP_READ 0x02
#define BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP 0x04
#define BT_GATT_CHRC_PROP_WRITE 0x08
#define BT_GATT_CHRC_PROP_NOTIFY 0x10
#define BT_GATT_CHRC_PROP_INDICATE 0x20
#define BT_GATT_CHRC_PROP_AUTH 0x40
#define BT_GATT_CHRC_PROP_EXT_PROP 0x80
/* GATT Characteristic Extended Properties Bitfield values */
#define BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE 0x01
#define BT_GATT_CHRC_EXT_PROP_WRITABLE_AUX 0x02
#define BT_GATT_CHRC_EXT_PROP_ENC_READ 0x04
#define BT_GATT_CHRC_EXT_PROP_ENC_WRITE 0x08
#define BT_GATT_CHRC_EXT_PROP_ENC (BT_GATT_CHRC_EXT_PROP_ENC_READ | \
BT_GATT_CHRC_EXT_PROP_ENC_WRITE)
#define BT_GATT_CHRC_EXT_PROP_AUTH_READ 0x10
#define BT_GATT_CHRC_EXT_PROP_AUTH_WRITE 0x20
#define BT_GATT_CHRC_EXT_PROP_AUTH (BT_GATT_CHRC_EXT_PROP_AUTH_READ | \
BT_GATT_CHRC_EXT_PROP_AUTH_WRITE)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
#include "src/shared/att-types.h"
struct bt_att;
struct bt_att *bt_att_new(int fd, bool ext_signed);
struct bt_att *bt_att_ref(struct bt_att *att);
void bt_att_unref(struct bt_att *att);
bool bt_att_set_close_on_unref(struct bt_att *att, bool do_close);
int bt_att_get_fd(struct bt_att *att);
typedef void (*bt_att_response_func_t)(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data);
typedef void (*bt_att_notify_func_t)(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data);
typedef void (*bt_att_destroy_func_t)(void *user_data);
typedef void (*bt_att_debug_func_t)(const char *str, void *user_data);
typedef void (*bt_att_timeout_func_t)(unsigned int id, uint8_t opcode,
void *user_data);
typedef void (*bt_att_disconnect_func_t)(int err, void *user_data);
typedef bool (*bt_att_counter_func_t)(uint32_t *sign_cnt, void *user_data);
bool bt_att_set_debug(struct bt_att *att, bt_att_debug_func_t callback,
void *user_data, bt_att_destroy_func_t destroy);
uint16_t bt_att_get_mtu(struct bt_att *att);
bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu);
uint8_t bt_att_get_link_type(struct bt_att *att);
bool bt_att_set_timeout_cb(struct bt_att *att, bt_att_timeout_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy);
unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
const void *pdu, uint16_t length,
bt_att_response_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy);
bool bt_att_cancel(struct bt_att *att, unsigned int id);
bool bt_att_cancel_all(struct bt_att *att);
unsigned int bt_att_send_error_rsp(struct bt_att *att, uint8_t opcode,
uint16_t handle, int error);
unsigned int bt_att_register(struct bt_att *att, uint8_t opcode,
bt_att_notify_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy);
bool bt_att_unregister(struct bt_att *att, unsigned int id);
unsigned int bt_att_register_disconnect(struct bt_att *att,
bt_att_disconnect_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy);
bool bt_att_unregister_disconnect(struct bt_att *att, unsigned int id);
bool bt_att_unregister_all(struct bt_att *att);
int bt_att_get_security(struct bt_att *att);
bool bt_att_set_security(struct bt_att *att, int level);
bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16],
bt_att_counter_func_t func, void *user_data);
bool bt_att_set_remote_key(struct bt_att *att, uint8_t sign_key[16],
bt_att_counter_func_t func, void *user_data);
bool bt_att_has_crypto(struct bt_att *att);

View File

@ -0,0 +1,499 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <endian.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include "src/shared/btsnoop.h"
struct btsnoop_hdr {
uint8_t id[8]; /* Identification Pattern */
uint32_t version; /* Version Number = 1 */
uint32_t type; /* Datalink Type */
} __attribute__ ((packed));
#define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))
struct btsnoop_pkt {
uint32_t size; /* Original Length */
uint32_t len; /* Included Length */
uint32_t flags; /* Packet Flags */
uint32_t drops; /* Cumulative Drops */
uint64_t ts; /* Timestamp microseconds */
uint8_t data[0]; /* Packet Data */
} __attribute__ ((packed));
#define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))
static const uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e,
0x6f, 0x6f, 0x70, 0x00 };
static const uint32_t btsnoop_version = 1;
struct pklg_pkt {
uint32_t len;
uint64_t ts;
uint8_t type;
} __attribute__ ((packed));
#define PKLG_PKT_SIZE (sizeof(struct pklg_pkt))
struct btsnoop {
int ref_count;
int fd;
unsigned long flags;
uint32_t format;
uint16_t index;
bool aborted;
bool pklg_format;
bool pklg_v2;
};
struct btsnoop *btsnoop_open(const char *path, unsigned long flags)
{
struct btsnoop *btsnoop;
struct btsnoop_hdr hdr;
ssize_t len;
btsnoop = calloc(1, sizeof(*btsnoop));
if (!btsnoop)
return NULL;
btsnoop->fd = open(path, O_RDONLY | O_CLOEXEC);
if (btsnoop->fd < 0) {
free(btsnoop);
return NULL;
}
btsnoop->flags = flags;
len = read(btsnoop->fd, &hdr, BTSNOOP_HDR_SIZE);
if (len < 0 || len != BTSNOOP_HDR_SIZE)
goto failed;
if (!memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) {
/* Check for BTSnoop version 1 format */
if (be32toh(hdr.version) != btsnoop_version)
goto failed;
btsnoop->format = be32toh(hdr.type);
btsnoop->index = 0xffff;
} else {
if (!(btsnoop->flags & BTSNOOP_FLAG_PKLG_SUPPORT))
goto failed;
/* Check for Apple Packet Logger format */
if (hdr.id[0] != 0x00 ||
(hdr.id[1] != 0x00 && hdr.id[1] != 0x01))
goto failed;
btsnoop->format = BTSNOOP_FORMAT_MONITOR;
btsnoop->index = 0xffff;
btsnoop->pklg_format = true;
btsnoop->pklg_v2 = (hdr.id[1] == 0x01);
/* Apple Packet Logger format has no header */
lseek(btsnoop->fd, 0, SEEK_SET);
}
return btsnoop_ref(btsnoop);
failed:
close(btsnoop->fd);
free(btsnoop);
return NULL;
}
struct btsnoop *btsnoop_create(const char *path, uint32_t format)
{
struct btsnoop *btsnoop;
struct btsnoop_hdr hdr;
ssize_t written;
btsnoop = calloc(1, sizeof(*btsnoop));
if (!btsnoop)
return NULL;
btsnoop->fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (btsnoop->fd < 0) {
free(btsnoop);
return NULL;
}
btsnoop->format = format;
btsnoop->index = 0xffff;
memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
hdr.version = htobe32(btsnoop_version);
hdr.type = htobe32(btsnoop->format);
written = write(btsnoop->fd, &hdr, BTSNOOP_HDR_SIZE);
if (written < 0) {
close(btsnoop->fd);
free(btsnoop);
return NULL;
}
return btsnoop_ref(btsnoop);
}
struct btsnoop *btsnoop_ref(struct btsnoop *btsnoop)
{
if (!btsnoop)
return NULL;
__sync_fetch_and_add(&btsnoop->ref_count, 1);
return btsnoop;
}
void btsnoop_unref(struct btsnoop *btsnoop)
{
if (!btsnoop)
return;
if (__sync_sub_and_fetch(&btsnoop->ref_count, 1))
return;
if (btsnoop->fd >= 0)
close(btsnoop->fd);
free(btsnoop);
}
uint32_t btsnoop_get_format(struct btsnoop *btsnoop)
{
if (!btsnoop)
return BTSNOOP_FORMAT_INVALID;
return btsnoop->format;
}
bool btsnoop_write(struct btsnoop *btsnoop, struct timeval *tv,
uint32_t flags, uint32_t drops, const void *data,
uint16_t size)
{
struct btsnoop_pkt pkt;
uint64_t ts;
ssize_t written;
if (!btsnoop || !tv)
return false;
ts = (tv->tv_sec - 946684800ll) * 1000000ll + tv->tv_usec;
pkt.size = htobe32(size);
pkt.len = htobe32(size);
pkt.flags = htobe32(flags);
pkt.drops = htobe32(drops);
pkt.ts = htobe64(ts + 0x00E03AB44A676000ll);
written = write(btsnoop->fd, &pkt, BTSNOOP_PKT_SIZE);
if (written < 0)
return false;
if (data && size > 0) {
written = write(btsnoop->fd, data, size);
if (written < 0)
return false;
}
return true;
}
static uint32_t get_flags_from_opcode(uint16_t opcode)
{
switch (opcode) {
case BTSNOOP_OPCODE_NEW_INDEX:
case BTSNOOP_OPCODE_DEL_INDEX:
break;
case BTSNOOP_OPCODE_COMMAND_PKT:
return 0x02;
case BTSNOOP_OPCODE_EVENT_PKT:
return 0x03;
case BTSNOOP_OPCODE_ACL_TX_PKT:
return 0x00;
case BTSNOOP_OPCODE_ACL_RX_PKT:
return 0x01;
case BTSNOOP_OPCODE_SCO_TX_PKT:
case BTSNOOP_OPCODE_SCO_RX_PKT:
break;
case BTSNOOP_OPCODE_OPEN_INDEX:
case BTSNOOP_OPCODE_CLOSE_INDEX:
break;
}
return 0xff;
}
bool btsnoop_write_hci(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t index, uint16_t opcode, uint32_t drops,
const void *data, uint16_t size)
{
uint32_t flags;
if (!btsnoop)
return false;
switch (btsnoop->format) {
case BTSNOOP_FORMAT_HCI:
if (btsnoop->index == 0xffff)
btsnoop->index = index;
if (index != btsnoop->index)
return false;
flags = get_flags_from_opcode(opcode);
if (flags == 0xff)
return false;
break;
case BTSNOOP_FORMAT_MONITOR:
flags = (index << 16) | opcode;
break;
default:
return false;
}
return btsnoop_write(btsnoop, tv, flags, drops, data, size);
}
bool btsnoop_write_phy(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t frequency, const void *data, uint16_t size)
{
uint32_t flags;
if (!btsnoop)
return false;
switch (btsnoop->format) {
case BTSNOOP_FORMAT_SIMULATOR:
flags = (1 << 16) | frequency;
break;
default:
return false;
}
return btsnoop_write(btsnoop, tv, flags, 0, data, size);
}
static bool pklg_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t *index, uint16_t *opcode,
void *data, uint16_t *size)
{
struct pklg_pkt pkt;
uint32_t toread;
uint64_t ts;
ssize_t len;
len = read(btsnoop->fd, &pkt, PKLG_PKT_SIZE);
if (len == 0)
return false;
if (len < 0 || len != PKLG_PKT_SIZE) {
btsnoop->aborted = true;
return false;
}
if (btsnoop->pklg_v2) {
toread = le32toh(pkt.len) - (PKLG_PKT_SIZE - 4);
ts = le64toh(pkt.ts);
tv->tv_sec = ts & 0xffffffff;
tv->tv_usec = ts >> 32;
} else {
toread = be32toh(pkt.len) - (PKLG_PKT_SIZE - 4);
ts = be64toh(pkt.ts);
tv->tv_sec = ts >> 32;
tv->tv_usec = ts & 0xffffffff;
}
switch (pkt.type) {
case 0x00:
*index = 0x0000;
*opcode = BTSNOOP_OPCODE_COMMAND_PKT;
break;
case 0x01:
*index = 0x0000;
*opcode = BTSNOOP_OPCODE_EVENT_PKT;
break;
case 0x02:
*index = 0x0000;
*opcode = BTSNOOP_OPCODE_ACL_TX_PKT;
break;
case 0x03:
*index = 0x0000;
*opcode = BTSNOOP_OPCODE_ACL_RX_PKT;
break;
case 0x0b:
*index = 0x0000;
*opcode = BTSNOOP_OPCODE_VENDOR_DIAG;
break;
case 0xfc:
*index = 0xffff;
*opcode = BTSNOOP_OPCODE_SYSTEM_NOTE;
break;
default:
*index = 0xffff;
*opcode = 0xffff;
break;
}
len = read(btsnoop->fd, data, toread);
if (len < 0) {
btsnoop->aborted = true;
return false;
}
*size = toread;
return true;
}
static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
{
switch (type) {
case 0x01:
return BTSNOOP_OPCODE_COMMAND_PKT;
case 0x02:
if (flags & 0x01)
return BTSNOOP_OPCODE_ACL_RX_PKT;
else
return BTSNOOP_OPCODE_ACL_TX_PKT;
case 0x03:
if (flags & 0x01)
return BTSNOOP_OPCODE_SCO_RX_PKT;
else
return BTSNOOP_OPCODE_SCO_TX_PKT;
case 0x04:
return BTSNOOP_OPCODE_EVENT_PKT;
case 0xff:
if (flags & 0x02) {
if (flags & 0x01)
return BTSNOOP_OPCODE_EVENT_PKT;
else
return BTSNOOP_OPCODE_COMMAND_PKT;
} else {
if (flags & 0x01)
return BTSNOOP_OPCODE_ACL_RX_PKT;
else
return BTSNOOP_OPCODE_ACL_TX_PKT;
}
break;
}
return 0xffff;
}
bool btsnoop_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t *index, uint16_t *opcode,
void *data, uint16_t *size)
{
struct btsnoop_pkt pkt;
uint32_t toread, flags;
uint64_t ts;
uint8_t pkt_type;
ssize_t len;
if (!btsnoop || btsnoop->aborted)
return false;
if (btsnoop->pklg_format)
return pklg_read_hci(btsnoop, tv, index, opcode, data, size);
len = read(btsnoop->fd, &pkt, BTSNOOP_PKT_SIZE);
if (len == 0)
return false;
if (len < 0 || len != BTSNOOP_PKT_SIZE) {
btsnoop->aborted = true;
return false;
}
toread = be32toh(pkt.size);
if (toread > BTSNOOP_MAX_PACKET_SIZE) {
btsnoop->aborted = true;
return false;
}
flags = be32toh(pkt.flags);
ts = be64toh(pkt.ts) - 0x00E03AB44A676000ll;
tv->tv_sec = (ts / 1000000ll) + 946684800ll;
tv->tv_usec = ts % 1000000ll;
switch (btsnoop->format) {
case BTSNOOP_FORMAT_HCI:
*index = 0;
*opcode = get_opcode_from_flags(0xff, flags);
break;
case BTSNOOP_FORMAT_UART:
len = read(btsnoop->fd, &pkt_type, 1);
if (len < 0) {
btsnoop->aborted = true;
return false;
}
toread--;
*index = 0;
*opcode = get_opcode_from_flags(pkt_type, flags);
break;
case BTSNOOP_FORMAT_MONITOR:
*index = flags >> 16;
*opcode = flags & 0xffff;
break;
default:
btsnoop->aborted = true;
return false;
}
len = read(btsnoop->fd, data, toread);
if (len < 0) {
btsnoop->aborted = true;
return false;
}
*size = toread;
return true;
}
bool btsnoop_read_phy(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t *frequency, void *data, uint16_t *size)
{
return false;
}

View File

@ -0,0 +1,121 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
#include <stdbool.h>
#include <sys/time.h>
#define BTSNOOP_FORMAT_INVALID 0
#define BTSNOOP_FORMAT_HCI 1001
#define BTSNOOP_FORMAT_UART 1002
#define BTSNOOP_FORMAT_BCSP 1003
#define BTSNOOP_FORMAT_3WIRE 1004
#define BTSNOOP_FORMAT_MONITOR 2001
#define BTSNOOP_FORMAT_SIMULATOR 2002
#define BTSNOOP_FLAG_PKLG_SUPPORT (1 << 0)
#define BTSNOOP_OPCODE_NEW_INDEX 0
#define BTSNOOP_OPCODE_DEL_INDEX 1
#define BTSNOOP_OPCODE_COMMAND_PKT 2
#define BTSNOOP_OPCODE_EVENT_PKT 3
#define BTSNOOP_OPCODE_ACL_TX_PKT 4
#define BTSNOOP_OPCODE_ACL_RX_PKT 5
#define BTSNOOP_OPCODE_SCO_TX_PKT 6
#define BTSNOOP_OPCODE_SCO_RX_PKT 7
#define BTSNOOP_OPCODE_OPEN_INDEX 8
#define BTSNOOP_OPCODE_CLOSE_INDEX 9
#define BTSNOOP_OPCODE_INDEX_INFO 10
#define BTSNOOP_OPCODE_VENDOR_DIAG 11
#define BTSNOOP_OPCODE_SYSTEM_NOTE 12
#define BTSNOOP_OPCODE_USER_LOGGING 13
#define BTSNOOP_OPCODE_CTRL_OPEN 14
#define BTSNOOP_OPCODE_CTRL_CLOSE 15
#define BTSNOOP_OPCODE_CTRL_COMMAND 16
#define BTSNOOP_OPCODE_CTRL_EVENT 17
#define BTSNOOP_MAX_PACKET_SIZE (1486 + 4)
#define BTSNOOP_TYPE_PRIMARY 0
#define BTSNOOP_TYPE_AMP 1
#define BTSNOOP_BUS_VIRTUAL 0
#define BTSNOOP_BUS_USB 1
#define BTSNOOP_BUS_PCCARD 2
#define BTSNOOP_BUS_UART 3
#define BTSNOOP_BUS_RS232 4
#define BTSNOOP_BUS_PCI 5
#define BTSNOOP_BUS_SDIO 6
#define BTSNOOP_BUS_SPI 7
#define BTSNOOP_BUS_I2C 8
#define BTSNOOP_BUS_SMD 9
struct btsnoop_opcode_new_index {
uint8_t type;
uint8_t bus;
uint8_t bdaddr[6];
char name[8];
} __attribute__((packed));
struct btsnoop_opcode_index_info {
uint8_t bdaddr[6];
uint16_t manufacturer;
} __attribute__((packed));
#define BTSNOOP_PRIORITY_EMERG 0
#define BTSNOOP_PRIORITY_ALERT 1
#define BTSNOOP_PRIORITY_CRIT 2
#define BTSNOOP_PRIORITY_ERR 3
#define BTSNOOP_PRIORITY_WARNING 4
#define BTSNOOP_PRIORITY_NOTICE 5
#define BTSNOOP_PRIORITY_INFO 6
#define BTSNOOP_PRIORITY_DEBUG 7
struct btsnoop_opcode_user_logging {
uint8_t priority;
uint8_t ident_len;
} __attribute__((packed));
struct btsnoop;
struct btsnoop *btsnoop_open(const char *path, unsigned long flags);
struct btsnoop *btsnoop_create(const char *path, uint32_t format);
struct btsnoop *btsnoop_ref(struct btsnoop *btsnoop);
void btsnoop_unref(struct btsnoop *btsnoop);
uint32_t btsnoop_get_format(struct btsnoop *btsnoop);
bool btsnoop_write(struct btsnoop *btsnoop, struct timeval *tv, uint32_t flags,
uint32_t drops, const void *data, uint16_t size);
bool btsnoop_write_hci(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t index, uint16_t opcode, uint32_t drops,
const void *data, uint16_t size);
bool btsnoop_write_phy(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t frequency, const void *data, uint16_t size);
bool btsnoop_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t *index, uint16_t *opcode,
void *data, uint16_t *size);
bool btsnoop_read_phy(struct btsnoop *btsnoop, struct timeval *tv,
uint16_t *frequency, void *data, uint16_t *size);

View File

@ -0,0 +1,690 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include "src/shared/util.h"
#include "src/shared/crypto.h"
#ifndef HAVE_LINUX_IF_ALG_H
#ifndef HAVE_LINUX_TYPES_H
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef uint32_t __u32;
#else
#include <linux/types.h>
#endif
struct sockaddr_alg {
__u16 salg_family;
__u8 salg_type[14];
__u32 salg_feat;
__u32 salg_mask;
__u8 salg_name[64];
};
struct af_alg_iv {
__u32 ivlen;
__u8 iv[0];
};
#define ALG_SET_KEY 1
#define ALG_SET_IV 2
#define ALG_SET_OP 3
#define ALG_OP_DECRYPT 0
#define ALG_OP_ENCRYPT 1
#define PF_ALG 38 /* Algorithm sockets. */
#define AF_ALG PF_ALG
#else
#include <linux/if_alg.h>
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
/* Maximum message length that can be passed to aes_cmac */
#define CMAC_MSG_MAX 80
struct bt_crypto {
int ref_count;
int ecb_aes;
int urandom;
int cmac_aes;
};
static int urandom_setup(void)
{
int fd;
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
return -1;
return fd;
}
static int ecb_aes_setup(void)
{
struct sockaddr_alg salg;
int fd;
fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
if (fd < 0)
return -1;
memset(&salg, 0, sizeof(salg));
salg.salg_family = AF_ALG;
strcpy((char *) salg.salg_type, "skcipher");
strcpy((char *) salg.salg_name, "ecb(aes)");
if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
close(fd);
return -1;
}
return fd;
}
static int cmac_aes_setup(void)
{
struct sockaddr_alg salg;
int fd;
fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
if (fd < 0)
return -1;
memset(&salg, 0, sizeof(salg));
salg.salg_family = AF_ALG;
strcpy((char *) salg.salg_type, "hash");
strcpy((char *) salg.salg_name, "cmac(aes)");
if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
close(fd);
return -1;
}
return fd;
}
struct bt_crypto *bt_crypto_new(void)
{
struct bt_crypto *crypto;
crypto = new0(struct bt_crypto, 1);
crypto->ecb_aes = ecb_aes_setup();
if (crypto->ecb_aes < 0) {
free(crypto);
return NULL;
}
crypto->urandom = urandom_setup();
if (crypto->urandom < 0) {
close(crypto->ecb_aes);
free(crypto);
return NULL;
}
crypto->cmac_aes = cmac_aes_setup();
if (crypto->cmac_aes < 0) {
close(crypto->urandom);
close(crypto->ecb_aes);
free(crypto);
return NULL;
}
return bt_crypto_ref(crypto);
}
struct bt_crypto *bt_crypto_ref(struct bt_crypto *crypto)
{
if (!crypto)
return NULL;
__sync_fetch_and_add(&crypto->ref_count, 1);
return crypto;
}
void bt_crypto_unref(struct bt_crypto *crypto)
{
if (!crypto)
return;
if (__sync_sub_and_fetch(&crypto->ref_count, 1))
return;
close(crypto->urandom);
close(crypto->ecb_aes);
close(crypto->cmac_aes);
free(crypto);
}
bool bt_crypto_random_bytes(struct bt_crypto *crypto,
uint8_t *buf, uint8_t num_bytes)
{
ssize_t len;
if (!crypto)
return false;
len = read(crypto->urandom, buf, num_bytes);
if (len < num_bytes)
return false;
return true;
}
static int alg_new(int fd, const void *keyval, socklen_t keylen)
{
if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, keyval, keylen) < 0)
return -1;
/* FIXME: This should use accept4() with SOCK_CLOEXEC */
return accept(fd, NULL, 0);
}
static bool alg_encrypt(int fd, const void *inbuf, size_t inlen,
void *outbuf, size_t outlen)
{
__u32 alg_op = ALG_OP_ENCRYPT;
char cbuf[CMSG_SPACE(sizeof(alg_op))];
struct cmsghdr *cmsg;
struct msghdr msg;
struct iovec iov;
ssize_t len;
memset(cbuf, 0, sizeof(cbuf));
memset(&msg, 0, sizeof(msg));
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(sizeof(alg_op));
memcpy(CMSG_DATA(cmsg), &alg_op, sizeof(alg_op));
iov.iov_base = (void *) inbuf;
iov.iov_len = inlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
len = sendmsg(fd, &msg, 0);
if (len < 0)
return false;
len = read(fd, outbuf, outlen);
if (len < 0)
return false;
return true;
}
static inline void swap_buf(const uint8_t *src, uint8_t *dst, uint16_t len)
{
int i;
for (i = 0; i < len; i++)
dst[len - 1 - i] = src[i];
}
bool bt_crypto_sign_att(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t *m, uint16_t m_len,
uint32_t sign_cnt, uint8_t signature[12])
{
int fd;
int len;
uint8_t tmp[16], out[16];
uint16_t msg_len = m_len + sizeof(uint32_t);
uint8_t msg[msg_len];
uint8_t msg_s[msg_len];
if (!crypto)
return false;
memset(msg, 0, msg_len);
memcpy(msg, m, m_len);
/* Add sign_counter to the message */
put_le32(sign_cnt, msg + m_len);
/* The most significant octet of key corresponds to key[0] */
swap_buf(key, tmp, 16);
fd = alg_new(crypto->cmac_aes, tmp, 16);
if (fd < 0)
return false;
/* Swap msg before signing */
swap_buf(msg, msg_s, msg_len);
len = send(fd, msg_s, msg_len, 0);
if (len < 0) {
close(fd);
return false;
}
len = read(fd, out, 16);
if (len < 0) {
close(fd);
return false;
}
close(fd);
/*
* As to BT spec. 4.1 Vol[3], Part C, chapter 10.4.1 sign counter should
* be placed in the signature
*/
put_be32(sign_cnt, out + 8);
/*
* The most significant octet of hash corresponds to out[0] - swap it.
* Then truncate in most significant bit first order to a length of
* 12 octets
*/
swap_buf(out, tmp, 16);
memcpy(signature, tmp + 4, 12);
return true;
}
/*
* Security function e
*
* Security function e generates 128-bit encryptedData from a 128-bit key
* and 128-bit plaintextData using the AES-128-bit block cypher:
*
* encryptedData = e(key, plaintextData)
*
* The most significant octet of key corresponds to key[0], the most
* significant octet of plaintextData corresponds to in[0] and the
* most significant octet of encryptedData corresponds to out[0].
*
*/
bool bt_crypto_e(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t plaintext[16], uint8_t encrypted[16])
{
uint8_t tmp[16], in[16], out[16];
int fd;
if (!crypto)
return false;
/* The most significant octet of key corresponds to key[0] */
swap_buf(key, tmp, 16);
fd = alg_new(crypto->ecb_aes, tmp, 16);
if (fd < 0)
return false;
/* Most significant octet of plaintextData corresponds to in[0] */
swap_buf(plaintext, in, 16);
if (!alg_encrypt(fd, in, 16, out, 16)) {
close(fd);
return false;
}
/* Most significant octet of encryptedData corresponds to out[0] */
swap_buf(out, encrypted, 16);
close(fd);
return true;
}
/*
* Random Address Hash function ah
*
* The random address hash function ah is used to generate a hash value
* that is used in resolvable private addresses.
*
* The following are inputs to the random address hash function ah:
*
* k is 128 bits
* r is 24 bits
* padding is 104 bits
*
* r is concatenated with padding to generate r' which is used as the
* 128-bit input parameter plaintextData to security function e:
*
* r' = padding || r
*
* The least significant octet of r becomes the least significant octet
* of r and the most significant octet of padding becomes the most
* significant octet of r'.
*
* For example, if the 24-bit value r is 0x423456 then r' is
* 0x00000000000000000000000000423456.
*
* The output of the random address function ah is:
*
* ah(k, r) = e(k, r') mod 2^24
*
* The output of the security function e is then truncated to 24 bits by
* taking the least significant 24 bits of the output of e as the result
* of ah.
*/
bool bt_crypto_ah(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r[3], uint8_t hash[3])
{
uint8_t rp[16];
uint8_t encrypted[16];
if (!crypto)
return false;
/* r' = padding || r */
memcpy(rp, r, 3);
memset(rp + 3, 0, 13);
/* e(k, r') */
if (!bt_crypto_e(crypto, k, rp, encrypted))
return false;
/* ah(k, r) = e(k, r') mod 2^24 */
memcpy(hash, encrypted, 3);
return true;
}
typedef struct {
uint64_t a, b;
} u128;
static inline void u128_xor(const uint8_t p[16], const uint8_t q[16],
uint8_t r[16])
{
u128 pp, qq, rr;
memcpy(&pp, p, 16);
memcpy(&qq, q, 16);
rr.a = pp.a ^ qq.a;
rr.b = pp.b ^ qq.b;
memcpy(r, &rr, 16);
}
/*
* Confirm value generation function c1
*
* During the pairing process confirm values are exchanged. This confirm
* value generation function c1 is used to generate the confirm values.
*
* The following are inputs to the confirm value generation function c1:
*
* k is 128 bits
* r is 128 bits
* pres is 56 bits
* preq is 56 bits
* iat is 1 bit
* ia is 48 bits
* rat is 1 bit
* ra is 48 bits
* padding is 32 bits of 0
*
* iat is concatenated with 7-bits of 0 to create iat' which is 8 bits
* in length. iat is the least significant bit of iat'
*
* rat is concatenated with 7-bits of 0 to create rat' which is 8 bits
* in length. rat is the least significant bit of rat'
*
* pres, preq, rat' and iat' are concatenated to generate p1 which is
* XORed with r and used as 128-bit input parameter plaintextData to
* security function e:
*
* p1 = pres || preq || rat' || iat'
*
* The octet of iat' becomes the least significant octet of p1 and the
* most significant octet of pres becomes the most significant octet of
* p1.
*
* ra is concatenated with ia and padding to generate p2 which is XORed
* with the result of the security function e using p1 as the input
* paremter plaintextData and is then used as the 128-bit input
* parameter plaintextData to security function e:
*
* p2 = padding || ia || ra
*
* The least significant octet of ra becomes the least significant octet
* of p2 and the most significant octet of padding becomes the most
* significant octet of p2.
*
* The output of the confirm value generation function c1 is:
*
* c1(k, r, preq, pres, iat, rat, ia, ra) = e(k, e(k, r XOR p1) XOR p2)
*
* The 128-bit output of the security function e is used as the result
* of confirm value generation function c1.
*/
bool bt_crypto_c1(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r[16], const uint8_t pres[7],
const uint8_t preq[7], uint8_t iat,
const uint8_t ia[6], uint8_t rat,
const uint8_t ra[6], uint8_t res[16])
{
uint8_t p1[16], p2[16];
/* p1 = pres || preq || _rat || _iat */
p1[0] = iat;
p1[1] = rat;
memcpy(p1 + 2, preq, 7);
memcpy(p1 + 9, pres, 7);
/* p2 = padding || ia || ra */
memcpy(p2, ra, 6);
memcpy(p2 + 6, ia, 6);
memset(p2 + 12, 0, 4);
/* res = r XOR p1 */
u128_xor(r, p1, res);
/* res = e(k, res) */
if (!bt_crypto_e(crypto, k, res, res))
return false;
/* res = res XOR p2 */
u128_xor(res, p2, res);
/* res = e(k, res) */
return bt_crypto_e(crypto, k, res, res);
}
/*
* Key generation function s1
*
* The key generation function s1 is used to generate the STK during the
* pairing process.
*
* The following are inputs to the key generation function s1:
*
* k is 128 bits
* r1 is 128 bits
* r2 is 128 bits
*
* The most significant 64-bits of r1 are discarded to generate r1' and
* the most significant 64-bits of r2 are discarded to generate r2'.
*
* r1' is concatenated with r2' to generate r' which is used as the
* 128-bit input parameter plaintextData to security function e:
*
* r' = r1' || r2'
*
* The least significant octet of r2' becomes the least significant
* octet of r' and the most significant octet of r1' becomes the most
* significant octet of r'.
*
* The output of the key generation function s1 is:
*
* s1(k, r1, r2) = e(k, r')
*
* The 128-bit output of the security function e is used as the result
* of key generation function s1.
*/
bool bt_crypto_s1(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r1[16], const uint8_t r2[16],
uint8_t res[16])
{
memcpy(res, r2, 8);
memcpy(res + 8, r1, 8);
return bt_crypto_e(crypto, k, res, res);
}
static bool aes_cmac(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t *msg, size_t msg_len, uint8_t res[16])
{
uint8_t key_msb[16], out[16], msg_msb[CMAC_MSG_MAX];
ssize_t len;
int fd;
if (msg_len > CMAC_MSG_MAX)
return false;
swap_buf(key, key_msb, 16);
fd = alg_new(crypto->cmac_aes, key_msb, 16);
if (fd < 0)
return false;
swap_buf(msg, msg_msb, msg_len);
len = send(fd, msg_msb, msg_len, 0);
if (len < 0) {
close(fd);
return false;
}
len = read(fd, out, 16);
if (len < 0) {
close(fd);
return false;
}
swap_buf(out, res, 16);
close(fd);
return true;
}
bool bt_crypto_f4(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
uint8_t x[16], uint8_t z, uint8_t res[16])
{
uint8_t m[65];
if (!crypto)
return false;
m[0] = z;
memcpy(&m[1], v, 32);
memcpy(&m[33], u, 32);
return aes_cmac(crypto, x, m, sizeof(m), res);
}
bool bt_crypto_f5(struct bt_crypto *crypto, uint8_t w[32], uint8_t n1[16],
uint8_t n2[16], uint8_t a1[7], uint8_t a2[7],
uint8_t mackey[16], uint8_t ltk[16])
{
uint8_t btle[4] = { 0x65, 0x6c, 0x74, 0x62 };
uint8_t salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c };
uint8_t length[2] = { 0x00, 0x01 };
uint8_t m[53], t[16];
if (!aes_cmac(crypto, salt, w, 32, t))
return false;
memcpy(&m[0], length, 2);
memcpy(&m[2], a2, 7);
memcpy(&m[9], a1, 7);
memcpy(&m[16], n2, 16);
memcpy(&m[32], n1, 16);
memcpy(&m[48], btle, 4);
m[52] = 0; /* Counter */
if (!aes_cmac(crypto, t, m, sizeof(m), mackey))
return false;
m[52] = 1; /* Counter */
return aes_cmac(crypto, t, m, sizeof(m), ltk);
}
bool bt_crypto_f6(struct bt_crypto *crypto, uint8_t w[16], uint8_t n1[16],
uint8_t n2[16], uint8_t r[16], uint8_t io_cap[3],
uint8_t a1[7], uint8_t a2[7], uint8_t res[16])
{
uint8_t m[65];
memcpy(&m[0], a2, 7);
memcpy(&m[7], a1, 7);
memcpy(&m[14], io_cap, 3);
memcpy(&m[17], r, 16);
memcpy(&m[33], n2, 16);
memcpy(&m[49], n1, 16);
return aes_cmac(crypto, w, m, sizeof(m), res);
}
bool bt_crypto_g2(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
uint8_t x[16], uint8_t y[16], uint32_t *val)
{
uint8_t m[80], tmp[16];
memcpy(&m[0], y, 16);
memcpy(&m[16], v, 32);
memcpy(&m[48], u, 32);
if (!aes_cmac(crypto, x, m, sizeof(m), tmp))
return false;
*val = get_le32(tmp);
*val %= 1000000;
return true;
}
bool bt_crypto_h6(struct bt_crypto *crypto, const uint8_t w[16],
const uint8_t keyid[4], uint8_t res[16])
{
if (!aes_cmac(crypto, w, keyid, 4, res))
return false;
return true;
}

View File

@ -0,0 +1,63 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
struct bt_crypto;
struct bt_crypto *bt_crypto_new(void);
struct bt_crypto *bt_crypto_ref(struct bt_crypto *crypto);
void bt_crypto_unref(struct bt_crypto *crypto);
bool bt_crypto_random_bytes(struct bt_crypto *crypto,
uint8_t *buf, uint8_t num_bytes);
bool bt_crypto_e(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t plaintext[16], uint8_t encrypted[16]);
bool bt_crypto_ah(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r[3], uint8_t hash[3]);
bool bt_crypto_c1(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r[16], const uint8_t pres[7],
const uint8_t preq[7], uint8_t iat,
const uint8_t ia[6], uint8_t rat,
const uint8_t ra[6], uint8_t res[16]);
bool bt_crypto_s1(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r1[16], const uint8_t r2[16],
uint8_t res[16]);
bool bt_crypto_f4(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
uint8_t x[16], uint8_t z, uint8_t res[16]);
bool bt_crypto_f5(struct bt_crypto *crypto, uint8_t w[32], uint8_t n1[16],
uint8_t n2[16], uint8_t a1[7], uint8_t a2[7],
uint8_t mackey[16], uint8_t ltk[16]);
bool bt_crypto_f6(struct bt_crypto *crypto, uint8_t w[16], uint8_t n1[16],
uint8_t n2[16], uint8_t r[16], uint8_t io_cap[3],
uint8_t a1[7], uint8_t a2[7], uint8_t res[16]);
bool bt_crypto_g2(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
uint8_t x[16], uint8_t y[16], uint32_t *val);
bool bt_crypto_h6(struct bt_crypto *crypto, const uint8_t w[16],
const uint8_t keyid[4], uint8_t res[16]);
bool bt_crypto_sign_att(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t *m, uint16_t m_len,
uint32_t sign_cnt, uint8_t signature[12]);

View File

@ -0,0 +1,861 @@
/*
* Copyright (c) 2013, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include "ecc.h"
/* 256-bit curve */
#define ECC_BYTES 32
/* Number of uint64_t's needed */
#define NUM_ECC_DIGITS (ECC_BYTES / 8)
struct ecc_point {
uint64_t x[NUM_ECC_DIGITS];
uint64_t y[NUM_ECC_DIGITS];
};
#define MAX_TRIES 16
typedef struct {
uint64_t m_low;
uint64_t m_high;
} uint128_t;
#define CURVE_P_32 { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
0x0000000000000000ull, 0xFFFFFFFF00000001ull }
#define CURVE_G_32 { \
{ 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull, \
0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }, \
{ 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull, \
0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull } \
}
#define CURVE_N_32 { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull, \
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
static uint64_t curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
static struct ecc_point curve_g = CURVE_G_32;
static uint64_t curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
static bool get_random_number(uint64_t *vli)
{
char *ptr = (char *) vli;
size_t left = ECC_BYTES;
int fd;
fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
if (fd < 0)
return false;
}
while (left > 0) {
ssize_t ret;
ret = read(fd, ptr, left);
if (ret <= 0) {
close(fd);
return false;
}
left -= ret;
ptr += ret;
}
close(fd);
return true;
}
static void vli_clear(uint64_t *vli)
{
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++)
vli[i] = 0;
}
/* Returns true if vli == 0, false otherwise. */
static bool vli_is_zero(const uint64_t *vli)
{
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
if (vli[i])
return false;
}
return true;
}
/* Returns nonzero if bit bit of vli is set. */
static uint64_t vli_test_bit(const uint64_t *vli, unsigned int bit)
{
return (vli[bit / 64] & ((uint64_t) 1 << (bit % 64)));
}
/* Counts the number of 64-bit "digits" in vli. */
static unsigned int vli_num_digits(const uint64_t *vli)
{
int i;
/* Search from the end until we find a non-zero digit.
* We do it in reverse because we expect that most digits will
* be nonzero.
*/
for (i = NUM_ECC_DIGITS - 1; i >= 0 && vli[i] == 0; i--);
return (i + 1);
}
/* Counts the number of bits required for vli. */
static unsigned int vli_num_bits(const uint64_t *vli)
{
unsigned int i, num_digits;
uint64_t digit;
num_digits = vli_num_digits(vli);
if (num_digits == 0)
return 0;
digit = vli[num_digits - 1];
for (i = 0; digit; i++)
digit >>= 1;
return ((num_digits - 1) * 64 + i);
}
/* Sets dest = src. */
static void vli_set(uint64_t *dest, const uint64_t *src)
{
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++)
dest[i] = src[i];
}
/* Returns sign of left - right. */
static int vli_cmp(const uint64_t *left, const uint64_t *right)
{
int i;
for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
if (left[i] > right[i])
return 1;
else if (left[i] < right[i])
return -1;
}
return 0;
}
/* Computes result = in << c, returning carry. Can modify in place
* (if result == in). 0 < shift < 64.
*/
static uint64_t vli_lshift(uint64_t *result, const uint64_t *in,
unsigned int shift)
{
uint64_t carry = 0;
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
uint64_t temp = in[i];
result[i] = (temp << shift) | carry;
carry = temp >> (64 - shift);
}
return carry;
}
/* Computes vli = vli >> 1. */
static void vli_rshift1(uint64_t *vli)
{
uint64_t *end = vli;
uint64_t carry = 0;
vli += NUM_ECC_DIGITS;
while (vli-- > end) {
uint64_t temp = *vli;
*vli = (temp >> 1) | carry;
carry = temp << 63;
}
}
/* Computes result = left + right, returning carry. Can modify in place. */
static uint64_t vli_add(uint64_t *result, const uint64_t *left,
const uint64_t *right)
{
uint64_t carry = 0;
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
uint64_t sum;
sum = left[i] + right[i] + carry;
if (sum != left[i])
carry = (sum < left[i]);
result[i] = sum;
}
return carry;
}
/* Computes result = left - right, returning borrow. Can modify in place. */
static uint64_t vli_sub(uint64_t *result, const uint64_t *left,
const uint64_t *right)
{
uint64_t borrow = 0;
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
uint64_t diff;
diff = left[i] - right[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
result[i] = diff;
}
return borrow;
}
static uint128_t mul_64_64(uint64_t left, uint64_t right)
{
uint64_t a0 = left & 0xffffffffull;
uint64_t a1 = left >> 32;
uint64_t b0 = right & 0xffffffffull;
uint64_t b1 = right >> 32;
uint64_t m0 = a0 * b0;
uint64_t m1 = a0 * b1;
uint64_t m2 = a1 * b0;
uint64_t m3 = a1 * b1;
uint128_t result;
m2 += (m0 >> 32);
m2 += m1;
/* Overflow */
if (m2 < m1)
m3 += 0x100000000ull;
result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
result.m_high = m3 + (m2 >> 32);
return result;
}
static uint128_t add_128_128(uint128_t a, uint128_t b)
{
uint128_t result;
result.m_low = a.m_low + b.m_low;
result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
return result;
}
static void vli_mult(uint64_t *result, const uint64_t *left,
const uint64_t *right)
{
uint128_t r01 = { 0, 0 };
uint64_t r2 = 0;
unsigned int i, k;
/* Compute each digit of result in sequence, maintaining the
* carries.
*/
for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
unsigned int min;
if (k < NUM_ECC_DIGITS)
min = 0;
else
min = (k + 1) - NUM_ECC_DIGITS;
for (i = min; i <= k && i < NUM_ECC_DIGITS; i++) {
uint128_t product;
product = mul_64_64(left[i], right[k - i]);
r01 = add_128_128(r01, product);
r2 += (r01.m_high < product.m_high);
}
result[k] = r01.m_low;
r01.m_low = r01.m_high;
r01.m_high = r2;
r2 = 0;
}
result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
}
static void vli_square(uint64_t *result, const uint64_t *left)
{
uint128_t r01 = { 0, 0 };
uint64_t r2 = 0;
int i, k;
for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
unsigned int min;
if (k < NUM_ECC_DIGITS)
min = 0;
else
min = (k + 1) - NUM_ECC_DIGITS;
for (i = min; i <= k && i <= k - i; i++) {
uint128_t product;
product = mul_64_64(left[i], left[k - i]);
if (i < k - i) {
r2 += product.m_high >> 63;
product.m_high = (product.m_high << 1) |
(product.m_low >> 63);
product.m_low <<= 1;
}
r01 = add_128_128(r01, product);
r2 += (r01.m_high < product.m_high);
}
result[k] = r01.m_low;
r01.m_low = r01.m_high;
r01.m_high = r2;
r2 = 0;
}
result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
}
/* Computes result = (left + right) % mod.
* Assumes that left < mod and right < mod, result != mod.
*/
static void vli_mod_add(uint64_t *result, const uint64_t *left,
const uint64_t *right, const uint64_t *mod)
{
uint64_t carry;
carry = vli_add(result, left, right);
/* result > mod (result = mod + remainder), so subtract mod to
* get remainder.
*/
if (carry || vli_cmp(result, mod) >= 0)
vli_sub(result, result, mod);
}
/* Computes result = (left - right) % mod.
* Assumes that left < mod and right < mod, result != mod.
*/
static void vli_mod_sub(uint64_t *result, const uint64_t *left,
const uint64_t *right, const uint64_t *mod)
{
uint64_t borrow = vli_sub(result, left, right);
/* In this case, p_result == -diff == (max int) - diff.
* Since -x % d == d - x, we can get the correct result from
* result + mod (with overflow).
*/
if (borrow)
vli_add(result, result, mod);
}
/* Computes result = product % curve_p
from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void vli_mmod_fast(uint64_t *result, const uint64_t *product)
{
uint64_t tmp[NUM_ECC_DIGITS];
int carry;
/* t */
vli_set(result, product);
/* s1 */
tmp[0] = 0;
tmp[1] = product[5] & 0xffffffff00000000ull;
tmp[2] = product[6];
tmp[3] = product[7];
carry = vli_lshift(tmp, tmp, 1);
carry += vli_add(result, result, tmp);
/* s2 */
tmp[1] = product[6] << 32;
tmp[2] = (product[6] >> 32) | (product[7] << 32);
tmp[3] = product[7] >> 32;
carry += vli_lshift(tmp, tmp, 1);
carry += vli_add(result, result, tmp);
/* s3 */
tmp[0] = product[4];
tmp[1] = product[5] & 0xffffffff;
tmp[2] = 0;
tmp[3] = product[7];
carry += vli_add(result, result, tmp);
/* s4 */
tmp[0] = (product[4] >> 32) | (product[5] << 32);
tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
tmp[2] = product[7];
tmp[3] = (product[6] >> 32) | (product[4] << 32);
carry += vli_add(result, result, tmp);
/* d1 */
tmp[0] = (product[5] >> 32) | (product[6] << 32);
tmp[1] = (product[6] >> 32);
tmp[2] = 0;
tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
carry -= vli_sub(result, result, tmp);
/* d2 */
tmp[0] = product[6];
tmp[1] = product[7];
tmp[2] = 0;
tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
carry -= vli_sub(result, result, tmp);
/* d3 */
tmp[0] = (product[6] >> 32) | (product[7] << 32);
tmp[1] = (product[7] >> 32) | (product[4] << 32);
tmp[2] = (product[4] >> 32) | (product[5] << 32);
tmp[3] = (product[6] << 32);
carry -= vli_sub(result, result, tmp);
/* d4 */
tmp[0] = product[7];
tmp[1] = product[4] & 0xffffffff00000000ull;
tmp[2] = product[5];
tmp[3] = product[6] & 0xffffffff00000000ull;
carry -= vli_sub(result, result, tmp);
if (carry < 0) {
do {
carry += vli_add(result, result, curve_p);
} while (carry < 0);
} else {
while (carry || vli_cmp(curve_p, result) != 1)
carry -= vli_sub(result, result, curve_p);
}
}
/* Computes result = (left * right) % curve_p. */
static void vli_mod_mult_fast(uint64_t *result, const uint64_t *left,
const uint64_t *right)
{
uint64_t product[2 * NUM_ECC_DIGITS];
vli_mult(product, left, right);
vli_mmod_fast(result, product);
}
/* Computes result = left^2 % curve_p. */
static void vli_mod_square_fast(uint64_t *result, const uint64_t *left)
{
uint64_t product[2 * NUM_ECC_DIGITS];
vli_square(product, left);
vli_mmod_fast(result, product);
}
#define EVEN(vli) (!(vli[0] & 1))
/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
* See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
* https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
*/
static void vli_mod_inv(uint64_t *result, const uint64_t *input,
const uint64_t *mod)
{
uint64_t a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS];
uint64_t u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
uint64_t carry;
int cmp_result;
if (vli_is_zero(input)) {
vli_clear(result);
return;
}
vli_set(a, input);
vli_set(b, mod);
vli_clear(u);
u[0] = 1;
vli_clear(v);
while ((cmp_result = vli_cmp(a, b)) != 0) {
carry = 0;
if (EVEN(a)) {
vli_rshift1(a);
if (!EVEN(u))
carry = vli_add(u, u, mod);
vli_rshift1(u);
if (carry)
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
} else if (EVEN(b)) {
vli_rshift1(b);
if (!EVEN(v))
carry = vli_add(v, v, mod);
vli_rshift1(v);
if (carry)
v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
} else if (cmp_result > 0) {
vli_sub(a, a, b);
vli_rshift1(a);
if (vli_cmp(u, v) < 0)
vli_add(u, u, mod);
vli_sub(u, u, v);
if (!EVEN(u))
carry = vli_add(u, u, mod);
vli_rshift1(u);
if (carry)
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
} else {
vli_sub(b, b, a);
vli_rshift1(b);
if (vli_cmp(v, u) < 0)
vli_add(v, v, mod);
vli_sub(v, v, u);
if (!EVEN(v))
carry = vli_add(v, v, mod);
vli_rshift1(v);
if (carry)
v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
}
}
vli_set(result, u);
}
/* ------ Point operations ------ */
/* Returns true if p_point is the point at infinity, false otherwise. */
static bool ecc_point_is_zero(const struct ecc_point *point)
{
return (vli_is_zero(point->x) && vli_is_zero(point->y));
}
/* Point multiplication algorithm using Montgomery's ladder with co-Z
* coordinates. From http://eprint.iacr.org/2011/338.pdf
*/
/* Double in place */
static void ecc_point_double_jacobian(uint64_t *x1, uint64_t *y1, uint64_t *z1)
{
/* t1 = x, t2 = y, t3 = z */
uint64_t t4[NUM_ECC_DIGITS];
uint64_t t5[NUM_ECC_DIGITS];
if (vli_is_zero(z1))
return;
vli_mod_square_fast(t4, y1); /* t4 = y1^2 */
vli_mod_mult_fast(t5, x1, t4); /* t5 = x1*y1^2 = A */
vli_mod_square_fast(t4, t4); /* t4 = y1^4 */
vli_mod_mult_fast(y1, y1, z1); /* t2 = y1*z1 = z3 */
vli_mod_square_fast(z1, z1); /* t3 = z1^2 */
vli_mod_add(x1, x1, z1, curve_p); /* t1 = x1 + z1^2 */
vli_mod_add(z1, z1, z1, curve_p); /* t3 = 2*z1^2 */
vli_mod_sub(z1, x1, z1, curve_p); /* t3 = x1 - z1^2 */
vli_mod_mult_fast(x1, x1, z1); /* t1 = x1^2 - z1^4 */
vli_mod_add(z1, x1, x1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
vli_mod_add(x1, x1, z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
if (vli_test_bit(x1, 0)) {
uint64_t carry = vli_add(x1, x1, curve_p);
vli_rshift1(x1);
x1[NUM_ECC_DIGITS - 1] |= carry << 63;
} else {
vli_rshift1(x1);
}
/* t1 = 3/2*(x1^2 - z1^4) = B */
vli_mod_square_fast(z1, x1); /* t3 = B^2 */
vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - A */
vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
vli_mod_sub(t5, t5, z1, curve_p); /* t5 = A - x3 */
vli_mod_mult_fast(x1, x1, t5); /* t1 = B * (A - x3) */
vli_mod_sub(t4, x1, t4, curve_p); /* t4 = B * (A - x3) - y1^4 = y3 */
vli_set(x1, z1);
vli_set(z1, y1);
vli_set(y1, t4);
}
/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
static void apply_z(uint64_t *x1, uint64_t *y1, uint64_t *z)
{
uint64_t t1[NUM_ECC_DIGITS];
vli_mod_square_fast(t1, z); /* z^2 */
vli_mod_mult_fast(x1, x1, t1); /* x1 * z^2 */
vli_mod_mult_fast(t1, t1, z); /* z^3 */
vli_mod_mult_fast(y1, y1, t1); /* y1 * z^3 */
}
/* P = (x1, y1) => 2P, (x2, y2) => P' */
static void xycz_initial_double(uint64_t *x1, uint64_t *y1, uint64_t *x2,
uint64_t *y2, uint64_t *p_initial_z)
{
uint64_t z[NUM_ECC_DIGITS];
vli_set(x2, x1);
vli_set(y2, y1);
vli_clear(z);
z[0] = 1;
if (p_initial_z)
vli_set(z, p_initial_z);
apply_z(x1, y1, z);
ecc_point_double_jacobian(x1, y1, z);
apply_z(x2, y2, z);
}
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
* Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
* or P => P', Q => P + Q
*/
static void xycz_add(uint64_t *x1, uint64_t *y1, uint64_t *x2, uint64_t *y2)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uint64_t t5[NUM_ECC_DIGITS];
vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
vli_mod_square_fast(t5, y2); /* t5 = (y2 - y1)^2 = D */
vli_mod_sub(t5, t5, x1, curve_p); /* t5 = D - B */
vli_mod_sub(t5, t5, x2, curve_p); /* t5 = D - B - C = x3 */
vli_mod_sub(x2, x2, x1, curve_p); /* t3 = C - B */
vli_mod_mult_fast(y1, y1, x2); /* t2 = y1*(C - B) */
vli_mod_sub(x2, x1, t5, curve_p); /* t3 = B - x3 */
vli_mod_mult_fast(y2, y2, x2); /* t4 = (y2 - y1)*(B - x3) */
vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
vli_set(x2, t5);
}
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
* Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
* or P => P - Q, Q => P + Q
*/
static void xycz_add_c(uint64_t *x1, uint64_t *y1, uint64_t *x2, uint64_t *y2)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uint64_t t5[NUM_ECC_DIGITS];
uint64_t t6[NUM_ECC_DIGITS];
uint64_t t7[NUM_ECC_DIGITS];
vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
vli_mod_add(t5, y2, y1, curve_p); /* t4 = y2 + y1 */
vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
vli_mod_sub(t6, x2, x1, curve_p); /* t6 = C - B */
vli_mod_mult_fast(y1, y1, t6); /* t2 = y1 * (C - B) */
vli_mod_add(t6, x1, x2, curve_p); /* t6 = B + C */
vli_mod_square_fast(x2, y2); /* t3 = (y2 - y1)^2 */
vli_mod_sub(x2, x2, t6, curve_p); /* t3 = x3 */
vli_mod_sub(t7, x1, x2, curve_p); /* t7 = B - x3 */
vli_mod_mult_fast(y2, y2, t7); /* t4 = (y2 - y1)*(B - x3) */
vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
vli_mod_square_fast(t7, t5); /* t7 = (y2 + y1)^2 = F */
vli_mod_sub(t7, t7, t6, curve_p); /* t7 = x3' */
vli_mod_sub(t6, t7, x1, curve_p); /* t6 = x3' - B */
vli_mod_mult_fast(t6, t6, t5); /* t6 = (y2 + y1)*(x3' - B) */
vli_mod_sub(y1, t6, y1, curve_p); /* t2 = y3' */
vli_set(x1, t7);
}
static void ecc_point_mult(struct ecc_point *result,
const struct ecc_point *point,
uint64_t *scalar, uint64_t *initial_z,
int num_bits)
{
/* R0 and R1 */
uint64_t rx[2][NUM_ECC_DIGITS];
uint64_t ry[2][NUM_ECC_DIGITS];
uint64_t z[NUM_ECC_DIGITS];
int i, nb;
vli_set(rx[1], point->x);
vli_set(ry[1], point->y);
xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z);
for (i = num_bits - 2; i > 0; i--) {
nb = !vli_test_bit(scalar, i);
xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
}
nb = !vli_test_bit(scalar, 0);
xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
/* Find final 1/Z value. */
vli_mod_sub(z, rx[1], rx[0], curve_p); /* X1 - X0 */
vli_mod_mult_fast(z, z, ry[1 - nb]); /* Yb * (X1 - X0) */
vli_mod_mult_fast(z, z, point->x); /* xP * Yb * (X1 - X0) */
vli_mod_inv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0)) */
vli_mod_mult_fast(z, z, point->y); /* yP / (xP * Yb * (X1 - X0)) */
vli_mod_mult_fast(z, z, rx[1 - nb]); /* Xb * yP / (xP * Yb * (X1 - X0)) */
/* End 1/Z calculation */
xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
apply_z(rx[0], ry[0], z);
vli_set(result->x, rx[0]);
vli_set(result->y, ry[0]);
}
/* Little endian byte-array to native conversion */
static void ecc_bytes2native(const uint8_t bytes[ECC_BYTES],
uint64_t native[NUM_ECC_DIGITS])
{
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
const uint8_t *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
native[NUM_ECC_DIGITS - 1 - i] =
((uint64_t) digit[0] << 0) |
((uint64_t) digit[1] << 8) |
((uint64_t) digit[2] << 16) |
((uint64_t) digit[3] << 24) |
((uint64_t) digit[4] << 32) |
((uint64_t) digit[5] << 40) |
((uint64_t) digit[6] << 48) |
((uint64_t) digit[7] << 56);
}
}
/* Native to little endian byte-array conversion */
static void ecc_native2bytes(const uint64_t native[NUM_ECC_DIGITS],
uint8_t bytes[ECC_BYTES])
{
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
uint8_t *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
digit[0] = native[NUM_ECC_DIGITS - 1 - i] >> 0;
digit[1] = native[NUM_ECC_DIGITS - 1 - i] >> 8;
digit[2] = native[NUM_ECC_DIGITS - 1 - i] >> 16;
digit[3] = native[NUM_ECC_DIGITS - 1 - i] >> 24;
digit[4] = native[NUM_ECC_DIGITS - 1 - i] >> 32;
digit[5] = native[NUM_ECC_DIGITS - 1 - i] >> 40;
digit[6] = native[NUM_ECC_DIGITS - 1 - i] >> 48;
digit[7] = native[NUM_ECC_DIGITS - 1 - i] >> 56;
}
}
bool ecc_make_key(uint8_t public_key[64], uint8_t private_key[32])
{
struct ecc_point pk;
uint64_t priv[NUM_ECC_DIGITS];
unsigned tries = 0;
do {
if (!get_random_number(priv) || (tries++ >= MAX_TRIES))
return false;
if (vli_is_zero(priv))
continue;
/* Make sure the private key is in the range [1, n-1]. */
if (vli_cmp(curve_n, priv) != 1)
continue;
ecc_point_mult(&pk, &curve_g, priv, NULL, vli_num_bits(priv));
} while (ecc_point_is_zero(&pk));
ecc_native2bytes(priv, private_key);
ecc_native2bytes(pk.x, public_key);
ecc_native2bytes(pk.y, &public_key[32]);
return true;
}
bool ecdh_shared_secret(const uint8_t public_key[64],
const uint8_t private_key[32],
uint8_t secret[32])
{
uint64_t priv[NUM_ECC_DIGITS];
uint64_t rand[NUM_ECC_DIGITS];
struct ecc_point product, pk;
if (!get_random_number(rand))
return false;
ecc_bytes2native(public_key, pk.x);
ecc_bytes2native(&public_key[32], pk.y);
ecc_bytes2native(private_key, priv);
ecc_point_mult(&product, &pk, priv, rand, vli_num_bits(priv));
ecc_native2bytes(product.x, secret);
return !ecc_point_is_zero(&product);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2013, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
*
* 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.
*/
#include <stdbool.h>
#include <stdint.h>
/* Create a public/private key pair.
* Outputs:
* public_key - Will be filled in with the public key.
* private_Key - Will be filled in with the private key.
*
* Returns true if the key pair was generated successfully, false
* if an error occurred. They keys are with the LSB first.
*/
bool ecc_make_key(uint8_t public_key[64], uint8_t private_key[32]);
/* Compute a shared secret given your secret key and someone else's
* public key.
* Note: It is recommended that you hash the result of ecdh_shared_secret
* before using it for symmetric encryption or HMAC.
*
* Inputs:
* public_key - The public key of the remote party.
* private_Key - Your private key.
*
* Outputs:
* secret - Will be filled in with the shared secret value.
*
* Returns true if the shared secret was generated successfully, false
* if an error occurred. Both input and output parameters are with the
* LSB first.
*/
bool ecdh_shared_secret(const uint8_t public_key[64],
const uint8_t private_key[32],
uint8_t secret[32]);

View File

@ -0,0 +1,278 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
#include "src/shared/mgmt.h"
#include "src/shared/gap.h"
#define FLAG_MGMT_CONN_CONTROL (0 << 1)
struct bt_gap {
int ref_count;
uint16_t index;
struct mgmt *mgmt;
uint8_t mgmt_version;
uint16_t mgmt_revision;
bool mgmt_ready;
unsigned long flags;
bt_gap_ready_func_t ready_handler;
bt_gap_destroy_func_t ready_destroy;
void *ready_data;
uint8_t static_addr[6];
uint8_t local_irk[16];
struct queue *irk_list;
};
struct irk_entry {
uint8_t addr_type;
uint8_t addr[6];
uint8_t key[16];
};
static void irk_entry_free(void *data)
{
struct irk_entry *irk = data;
free(irk);
}
static void ready_status(struct bt_gap *gap, bool status)
{
gap->mgmt_ready = status;
if (gap->ready_handler)
gap->ready_handler(status, gap->ready_data);
}
static void read_commands_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
struct bt_gap *gap = user_data;
const struct mgmt_rp_read_commands *rp = param;
uint16_t num_commands, num_events;
const uint16_t *opcode;
size_t expected_len;
int i;
if (status != MGMT_STATUS_SUCCESS) {
ready_status(gap, false);
return;
}
if (length < sizeof(*rp)) {
ready_status(gap, false);
return;
}
num_commands = le16_to_cpu(rp->num_commands);
num_events = le16_to_cpu(rp->num_events);
expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
num_events * sizeof(uint16_t);
if (length < expected_len) {
ready_status(gap, false);
return;
}
opcode = rp->opcodes;
for (i = 0; i < num_commands; i++) {
uint16_t op = get_le16(opcode++);
if (op == MGMT_OP_ADD_DEVICE)
gap->flags |= FLAG_MGMT_CONN_CONTROL;
}
ready_status(gap, true);
}
static void read_version_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
struct bt_gap *gap = user_data;
const struct mgmt_rp_read_version *rp = param;
if (status != MGMT_STATUS_SUCCESS) {
ready_status(gap, false);
return;
}
if (length < sizeof(*rp)) {
ready_status(gap, false);
return;
}
gap->mgmt_version = rp->version;
gap->mgmt_revision = le16_to_cpu(rp->revision);
if (!mgmt_send(gap->mgmt, MGMT_OP_READ_COMMANDS,
MGMT_INDEX_NONE, 0, NULL,
read_commands_complete, gap, NULL)) {
ready_status(gap, false);
return;
}
}
struct bt_gap *bt_gap_new_default(void)
{
return bt_gap_new_index(0x0000);
}
struct bt_gap *bt_gap_new_index(uint16_t index)
{
struct bt_gap *gap;
if (index == MGMT_INDEX_NONE)
return NULL;
gap = new0(struct bt_gap, 1);
gap->index = index;
gap->mgmt = mgmt_new_default();
if (!gap->mgmt) {
free(gap);
return NULL;
}
gap->irk_list = queue_new();
gap->mgmt_ready = false;
if (!mgmt_send(gap->mgmt, MGMT_OP_READ_VERSION,
MGMT_INDEX_NONE, 0, NULL,
read_version_complete, gap, NULL)) {
mgmt_unref(gap->mgmt);
return NULL;
}
return bt_gap_ref(gap);
}
struct bt_gap *bt_gap_ref(struct bt_gap *gap)
{
if (!gap)
return NULL;
__sync_fetch_and_add(&gap->ref_count, 1);
return gap;
}
void bt_gap_unref(struct bt_gap *gap)
{
if (!gap)
return;
if (__sync_sub_and_fetch(&gap->ref_count, 1))
return;
gap->mgmt_ready = false;
mgmt_cancel_all(gap->mgmt);
mgmt_unregister_all(gap->mgmt);
if (gap->ready_destroy)
gap->ready_destroy(gap->ready_data);
queue_destroy(gap->irk_list, irk_entry_free);
mgmt_unref(gap->mgmt);
free(gap);
}
bool bt_gap_set_ready_handler(struct bt_gap *gap,
bt_gap_ready_func_t handler, void *user_data,
bt_gap_destroy_func_t destroy)
{
if (!gap)
return false;
if (gap->ready_destroy)
gap->ready_destroy(gap->ready_data);
gap->ready_handler = handler;
gap->ready_destroy = destroy;
gap->ready_data = user_data;
return true;
}
bool bt_gap_set_static_addr(struct bt_gap *gap, uint8_t addr[6])
{
if (!gap)
return false;
memcpy(gap->static_addr, addr, 6);
return true;
}
bool bt_gap_set_local_irk(struct bt_gap *gap, uint8_t key[16])
{
if (!gap)
return false;
memcpy(gap->local_irk, key, 16);
return true;
}
bool bt_gap_add_peer_irk(struct bt_gap *gap, uint8_t addr_type,
uint8_t addr[6], uint8_t key[16])
{
struct irk_entry *irk;
if (!gap)
return false;
if (addr_type > BT_GAP_ADDR_TYPE_LE_RANDOM)
return false;
irk = new0(struct irk_entry, 1);
irk->addr_type = addr_type;
memcpy(irk->addr, addr, 6);
memcpy(irk->key, key, 16);
if (!queue_push_tail(gap->irk_list, irk)) {
free(irk);
return false;
}
return true;
}

View File

@ -0,0 +1,49 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
#define BT_GAP_ADDR_TYPE_BREDR 0x00
#define BT_GAP_ADDR_TYPE_LE_PUBLIC 0x01
#define BT_GAP_ADDR_TYPE_LE_RANDOM 0x02
struct bt_gap;
struct bt_gap *bt_gap_new_default(void);
struct bt_gap *bt_gap_new_index(uint16_t index);
struct bt_gap *bt_gap_ref(struct bt_gap *gap);
void bt_gap_unref(struct bt_gap *gap);
typedef void (*bt_gap_destroy_func_t)(void *user_data);
typedef void (*bt_gap_ready_func_t)(bool success, void *user_data);
bool bt_gap_set_ready_handler(struct bt_gap *gap,
bt_gap_ready_func_t handler, void *user_data,
bt_gap_destroy_func_t destroy);
bool bt_gap_set_static_addr(struct bt_gap *gap, uint8_t addr[6]);
bool bt_gap_set_local_irk(struct bt_gap *gap, uint8_t key[16]);
bool bt_gap_add_peer_irk(struct bt_gap *gap, uint8_t addr_type,
uint8_t addr[6], uint8_t key[16]);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#define BT_GATT_UUID_SIZE 16
struct bt_gatt_client;
struct bt_gatt_client *bt_gatt_client_new(struct gatt_db *db,
struct bt_att *att,
uint16_t mtu);
struct bt_gatt_client *bt_gatt_client_clone(struct bt_gatt_client *client);
struct bt_gatt_client *bt_gatt_client_ref(struct bt_gatt_client *client);
void bt_gatt_client_unref(struct bt_gatt_client *client);
typedef void (*bt_gatt_client_destroy_func_t)(void *user_data);
typedef void (*bt_gatt_client_callback_t)(bool success, uint8_t att_ecode,
void *user_data);
typedef void (*bt_gatt_client_debug_func_t)(const char *str, void *user_data);
typedef void (*bt_gatt_client_read_callback_t)(bool success, uint8_t att_ecode,
const uint8_t *value, uint16_t length,
void *user_data);
typedef void (*bt_gatt_client_write_long_callback_t)(bool success,
bool reliable_error, uint8_t att_ecode,
void *user_data);
typedef void (*bt_gatt_client_notify_callback_t)(uint16_t value_handle,
const uint8_t *value, uint16_t length,
void *user_data);
typedef void (*bt_gatt_client_register_callback_t)(uint16_t att_ecode,
void *user_data);
typedef void (*bt_gatt_client_service_changed_callback_t)(uint16_t start_handle,
uint16_t end_handle,
void *user_data);
bool bt_gatt_client_is_ready(struct bt_gatt_client *client);
bool bt_gatt_client_set_ready_handler(struct bt_gatt_client *client,
bt_gatt_client_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
bool bt_gatt_client_set_service_changed(struct bt_gatt_client *client,
bt_gatt_client_service_changed_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
bt_gatt_client_debug_func_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client *client);
struct gatt_db *bt_gatt_client_get_db(struct bt_gatt_client *client);
bool bt_gatt_client_cancel(struct bt_gatt_client *client, unsigned int id);
bool bt_gatt_client_cancel_all(struct bt_gatt_client *client);
unsigned int bt_gatt_client_read_value(struct bt_gatt_client *client,
uint16_t value_handle,
bt_gatt_client_read_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_read_long_value(struct bt_gatt_client *client,
uint16_t value_handle, uint16_t offset,
bt_gatt_client_read_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client,
uint16_t *handles, uint8_t num_handles,
bt_gatt_client_read_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_write_without_response(
struct bt_gatt_client *client,
uint16_t value_handle,
bool signed_write,
const uint8_t *value, uint16_t length);
unsigned int bt_gatt_client_write_value(struct bt_gatt_client *client,
uint16_t value_handle,
const uint8_t *value, uint16_t length,
bt_gatt_client_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_write_long_value(struct bt_gatt_client *client,
bool reliable,
uint16_t value_handle, uint16_t offset,
const uint8_t *value, uint16_t length,
bt_gatt_client_write_long_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_prepare_write(struct bt_gatt_client *client,
unsigned int id,
uint16_t value_handle, uint16_t offset,
const uint8_t *value, uint16_t length,
bt_gatt_client_write_long_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_write_execute(struct bt_gatt_client *client,
unsigned int id,
bt_gatt_client_callback_t callback,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client,
uint16_t chrc_value_handle,
bt_gatt_client_register_callback_t callback,
bt_gatt_client_notify_callback_t notify,
void *user_data,
bt_gatt_client_destroy_func_t destroy);
bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
unsigned int id);
bool bt_gatt_client_set_security(struct bt_gatt_client *client, int level);
int bt_gatt_client_get_security(struct bt_gatt_client *client);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,237 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
struct gatt_db;
struct gatt_db_attribute;
struct gatt_db *gatt_db_new(void);
struct gatt_db *gatt_db_ref(struct gatt_db *db);
void gatt_db_unref(struct gatt_db *db);
bool gatt_db_isempty(struct gatt_db *db);
struct gatt_db_attribute *gatt_db_add_service(struct gatt_db *db,
const bt_uuid_t *uuid,
bool primary,
uint16_t num_handles);
bool gatt_db_remove_service(struct gatt_db *db,
struct gatt_db_attribute *attrib);
bool gatt_db_clear(struct gatt_db *db);
bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle);
struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
uint16_t handle,
const bt_uuid_t *uuid,
bool primary,
uint16_t num_handles);
typedef void (*gatt_db_read_t) (struct gatt_db_attribute *attrib,
unsigned int id, uint16_t offset,
uint8_t opcode, struct bt_att *att,
void *user_data);
typedef void (*gatt_db_write_t) (struct gatt_db_attribute *attrib,
unsigned int id, uint16_t offset,
const uint8_t *value, size_t len,
uint8_t opcode, struct bt_att *att,
void *user_data);
struct gatt_db_attribute *
gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
gatt_db_read_t read_func,
gatt_db_write_t write_func,
void *user_data);
struct gatt_db_attribute *
gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
uint16_t handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
gatt_db_read_t read_func,
gatt_db_write_t write_func,
void *user_data);
struct gatt_db_attribute *
gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
const bt_uuid_t *uuid,
uint32_t permissions,
gatt_db_read_t read_func,
gatt_db_write_t write_func,
void *user_data);
struct gatt_db_attribute *
gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
uint16_t handle,
const bt_uuid_t *uuid,
uint32_t permissions,
gatt_db_read_t read_func,
gatt_db_write_t write_func,
void *user_data);
struct gatt_db_attribute *
gatt_db_service_add_included(struct gatt_db_attribute *attrib,
struct gatt_db_attribute *include);
bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active);
bool gatt_db_service_get_active(struct gatt_db_attribute *attrib);
bool gatt_db_service_set_claimed(struct gatt_db_attribute *attrib,
bool claimed);
bool gatt_db_service_get_claimed(struct gatt_db_attribute *attrib);
typedef void (*gatt_db_attribute_cb_t)(struct gatt_db_attribute *attrib,
void *user_data);
void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle,
const bt_uuid_t type,
struct queue *queue);
unsigned int gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle,
const bt_uuid_t *type,
gatt_db_attribute_cb_t func,
void *user_data);
unsigned int gatt_db_find_by_type_value(struct gatt_db *db,
uint16_t start_handle,
uint16_t end_handle,
const bt_uuid_t *type,
const void *value,
size_t value_len,
gatt_db_attribute_cb_t func,
void *user_data);
void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle,
const bt_uuid_t type,
struct queue *queue);
void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle,
struct queue *queue);
void gatt_db_foreach_service(struct gatt_db *db, const bt_uuid_t *uuid,
gatt_db_attribute_cb_t func,
void *user_data);
void gatt_db_foreach_service_in_range(struct gatt_db *db,
const bt_uuid_t *uuid,
gatt_db_attribute_cb_t func,
void *user_data,
uint16_t start_handle,
uint16_t end_handle);
void gatt_db_service_foreach(struct gatt_db_attribute *attrib,
const bt_uuid_t *uuid,
gatt_db_attribute_cb_t func,
void *user_data);
void gatt_db_service_foreach_char(struct gatt_db_attribute *attrib,
gatt_db_attribute_cb_t func,
void *user_data);
void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib,
gatt_db_attribute_cb_t func,
void *user_data);
void gatt_db_service_foreach_incl(struct gatt_db_attribute *attrib,
gatt_db_attribute_cb_t func,
void *user_data);
typedef void (*gatt_db_destroy_func_t)(void *user_data);
unsigned int gatt_db_register(struct gatt_db *db,
gatt_db_attribute_cb_t service_added,
gatt_db_attribute_cb_t service_removed,
void *user_data,
gatt_db_destroy_func_t destroy);
bool gatt_db_unregister(struct gatt_db *db, unsigned int id);
struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
uint16_t handle);
struct gatt_db_attribute *gatt_db_get_service_with_uuid(struct gatt_db *db,
const bt_uuid_t *uuid);
const bt_uuid_t *gatt_db_attribute_get_type(
const struct gatt_db_attribute *attrib);
uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib);
bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib,
bt_uuid_t *uuid);
bool gatt_db_attribute_get_service_handles(
const struct gatt_db_attribute *attrib,
uint16_t *start_handle,
uint16_t *end_handle);
bool gatt_db_attribute_get_service_data(const struct gatt_db_attribute *attrib,
uint16_t *start_handle,
uint16_t *end_handle,
bool *primary,
bt_uuid_t *uuid);
bool gatt_db_attribute_get_char_data(const struct gatt_db_attribute *attrib,
uint16_t *handle,
uint16_t *value_handle,
uint8_t *properties,
uint16_t *ext_prop,
bt_uuid_t *uuid);
bool gatt_db_attribute_get_incl_data(const struct gatt_db_attribute *attrib,
uint16_t *handle,
uint16_t *start_handle,
uint16_t *end_handle);
uint32_t
gatt_db_attribute_get_permissions(const struct gatt_db_attribute *attrib);
typedef void (*gatt_db_attribute_read_t) (struct gatt_db_attribute *attrib,
int err, const uint8_t *value,
size_t length, void *user_data);
bool gatt_db_attribute_read(struct gatt_db_attribute *attrib, uint16_t offset,
uint8_t opcode, struct bt_att *att,
gatt_db_attribute_read_t func, void *user_data);
bool gatt_db_attribute_read_result(struct gatt_db_attribute *attrib,
unsigned int id, int err,
const uint8_t *value, size_t length);
typedef void (*gatt_db_attribute_write_t) (struct gatt_db_attribute *attrib,
int err, void *user_data);
bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
const uint8_t *value, size_t len,
uint8_t opcode, struct bt_att *att,
gatt_db_attribute_write_t func,
void *user_data);
bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib,
unsigned int id, int err);
bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* This file defines helpers for performing client-side procedures defined by
* the Generic Attribute Profile.
*/
#include <stdbool.h>
#include <stdint.h>
struct bt_gatt_result;
struct bt_gatt_iter {
struct bt_gatt_result *result;
uint16_t pos;
};
unsigned int bt_gatt_result_service_count(struct bt_gatt_result *result);
unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result);
unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result);
unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result);
bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result);
bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
uint16_t *start_handle, uint16_t *end_handle,
uint8_t uuid[16]);
bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
uint16_t *start_handle, uint16_t *end_handle,
uint16_t *value_handle, uint8_t *properties,
uint8_t uuid[16]);
bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t *handle,
uint8_t uuid[16]);
bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
uint16_t *handle, uint16_t *start_handle,
uint16_t *end_handle, uint8_t uuid[16]);
bool bt_gatt_iter_next_read_by_type(struct bt_gatt_iter *iter,
uint16_t *handle, uint16_t *length,
const uint8_t **value);
typedef void (*bt_gatt_destroy_func_t)(void *user_data);
typedef void (*bt_gatt_result_callback_t)(bool success, uint8_t att_ecode,
void *user_data);
typedef void (*bt_gatt_request_callback_t)(bool success, uint8_t att_ecode,
struct bt_gatt_result *result,
void *user_data);
struct bt_gatt_request;
struct bt_gatt_request *bt_gatt_request_ref(struct bt_gatt_request *req);
void bt_gatt_request_unref(struct bt_gatt_request *req);
void bt_gatt_request_cancel(struct bt_gatt_request *req);
unsigned int bt_gatt_exchange_mtu(struct bt_att *att, uint16_t client_rx_mtu,
bt_gatt_result_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_all_primary_services(
struct bt_att *att, bt_uuid_t *uuid,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_primary_services(
struct bt_att *att, bt_uuid_t *uuid,
uint16_t start, uint16_t end,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_secondary_services(
struct bt_att *att, bt_uuid_t *uuid,
uint16_t start, uint16_t end,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_characteristics(struct bt_att *att,
uint16_t start, uint16_t end,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
struct bt_gatt_request *bt_gatt_discover_descriptors(struct bt_att *att,
uint16_t start, uint16_t end,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
bool bt_gatt_read_by_type(struct bt_att *att, uint16_t start, uint16_t end,
const bt_uuid_t *uuid,
bt_gatt_request_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2014 Google Inc.
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
struct bt_gatt_server;
struct bt_gatt_server *bt_gatt_server_new(struct gatt_db *db,
struct bt_att *att, uint16_t mtu);
struct bt_gatt_server *bt_gatt_server_ref(struct bt_gatt_server *server);
void bt_gatt_server_unref(struct bt_gatt_server *server);
typedef void (*bt_gatt_server_destroy_func_t)(void *user_data);
typedef void (*bt_gatt_server_debug_func_t)(const char *str, void *user_data);
typedef void (*bt_gatt_server_conf_func_t)(void *user_data);
bool bt_gatt_server_set_debug(struct bt_gatt_server *server,
bt_gatt_server_debug_func_t callback,
void *user_data,
bt_gatt_server_destroy_func_t destroy);
bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
uint16_t handle, const uint8_t *value,
uint16_t length);
bool bt_gatt_server_send_indication(struct bt_gatt_server *server,
uint16_t handle, const uint8_t *value,
uint16_t length,
bt_gatt_server_conf_func_t callback,
void *user_data,
bt_gatt_server_destroy_func_t destroy);

View File

@ -0,0 +1,172 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2013-2014 Intel Corporation
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include "monitor/bt.h"
#include "src/shared/util.h"
#include "src/shared/hci.h"
#include "src/shared/hci-crypto.h"
struct crypto_data {
uint8_t size;
bt_hci_crypto_func_t callback;
void *user_data;
};
static void le_encrypt_callback(const void *response, uint8_t size,
void *user_data)
{
struct crypto_data *data = user_data;
const struct bt_hci_rsp_le_encrypt *rsp = response;
if (rsp->status) {
data->callback(NULL, 0, data->user_data);
return;
}
data->callback(rsp->data, data->size, data->user_data);
}
static bool le_encrypt(struct bt_hci *hci, uint8_t size,
const uint8_t key[16], const uint8_t plaintext[16],
bt_hci_crypto_func_t callback, void *user_data)
{
struct crypto_data *data;
struct bt_hci_cmd_le_encrypt cmd;
if (!callback || !size || size > 16)
return false;
memcpy(cmd.key, key, 16);
memcpy(cmd.plaintext, plaintext, 16);
data = new0(struct crypto_data, 1);
data->size = size;
data->callback = callback;
data->user_data = user_data;
if (!bt_hci_send(hci, BT_HCI_CMD_LE_ENCRYPT, &cmd, sizeof(cmd),
le_encrypt_callback, data, free)) {
free(data);
return false;
}
return true;
}
static void prand_callback(const void *response, uint8_t size,
void *user_data)
{
struct crypto_data *data = user_data;
const struct bt_hci_rsp_le_rand *rsp = response;
uint8_t prand[3];
if (rsp->status) {
data->callback(NULL, 0, data->user_data);
return;
}
prand[0] = (rsp->number & 0xff0000) >> 16;
prand[1] = (rsp->number & 0x00ff00) >> 8;
prand[2] = (rsp->number & 0x00003f) | 0x40;
data->callback(prand, 3, data->user_data);
}
bool bt_hci_crypto_prand(struct bt_hci *hci,
bt_hci_crypto_func_t callback, void *user_data)
{
struct crypto_data *data;
if (!callback)
return false;
data = new0(struct crypto_data, 1);
data->callback = callback;
data->user_data = user_data;
if (!bt_hci_send(hci, BT_HCI_CMD_LE_RAND, NULL, 0,
prand_callback, data, free)) {
free(data);
return false;
}
return true;
}
bool bt_hci_crypto_e(struct bt_hci *hci,
const uint8_t key[16], const uint8_t plaintext[16],
bt_hci_crypto_func_t callback, void *user_data)
{
return le_encrypt(hci, 16, key, plaintext, callback, user_data);
}
bool bt_hci_crypto_d1(struct bt_hci *hci,
const uint8_t k[16], uint16_t d, uint16_t r,
bt_hci_crypto_func_t callback, void *user_data)
{
uint8_t dp[16];
/* d' = padding || r || d */
dp[0] = d & 0xff;
dp[1] = d >> 8;
dp[2] = r & 0xff;
dp[3] = r >> 8;
memset(dp + 4, 0, 12);
/* d1(k, d, r) = e(k, d') */
return le_encrypt(hci, 16, k, dp, callback, user_data);
}
bool bt_hci_crypto_dm(struct bt_hci *hci,
const uint8_t k[16], const uint8_t r[8],
bt_hci_crypto_func_t callback, void *user_data)
{
uint8_t rp[16];
/* r' = padding || r */
memcpy(rp, r, 8);
memset(rp + 8, 0, 8);
/* dm(k, r) = e(k, r') mod 2^16 */
return le_encrypt(hci, 8, k, rp, callback, user_data);
}
bool bt_hci_crypto_ah(struct bt_hci *hci,
const uint8_t k[16], const uint8_t r[3],
bt_hci_crypto_func_t callback, void *user_data)
{
uint8_t rp[16];
/* r' = padding || r */
memcpy(rp, r, 3);
memset(rp + 3, 0, 13);
/* ah(k, r) = e(k, r') mod 2^24 */
return le_encrypt(hci, 3, k, rp, callback, user_data);
}

View File

@ -0,0 +1,45 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2013-2014 Intel Corporation
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
struct bt_hci;
typedef void (*bt_hci_crypto_func_t)(const void *data, uint8_t size,
void *user_data);
bool bt_hci_crypto_prand(struct bt_hci *hci,
bt_hci_crypto_func_t callback, void *user_data);
bool bt_hci_crypto_e(struct bt_hci *hci,
const uint8_t key[16], const uint8_t plaintext[16],
bt_hci_crypto_func_t callback, void *user_data);
bool bt_hci_crypto_d1(struct bt_hci *hci,
const uint8_t k[16], uint16_t d, uint16_t r,
bt_hci_crypto_func_t callback, void *user_data);
bool bt_hci_crypto_dm(struct bt_hci *hci,
const uint8_t k[16], const uint8_t r[8],
bt_hci_crypto_func_t callback, void *user_data);
bool bt_hci_crypto_ah(struct bt_hci *hci,
const uint8_t k[16], const uint8_t r[3],
bt_hci_crypto_func_t callback, void *user_data);

View File

@ -0,0 +1,586 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include "monitor/bt.h"
#include "src/shared/mainloop.h"
#include "src/shared/io.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
#include "src/shared/hci.h"
#define BTPROTO_HCI 1
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
#define HCI_CHANNEL_RAW 0
#define HCI_CHANNEL_USER 1
#define SOL_HCI 0
#define HCI_FILTER 2
struct hci_filter {
uint32_t type_mask;
uint32_t event_mask[2];
uint16_t opcode;
};
struct bt_hci {
int ref_count;
struct io *io;
bool is_stream;
bool writer_active;
uint8_t num_cmds;
unsigned int next_cmd_id;
unsigned int next_evt_id;
struct queue *cmd_queue;
struct queue *rsp_queue;
struct queue *evt_list;
};
struct cmd {
unsigned int id;
uint16_t opcode;
void *data;
uint8_t size;
bt_hci_callback_func_t callback;
bt_hci_destroy_func_t destroy;
void *user_data;
};
struct evt {
unsigned int id;
uint8_t event;
bt_hci_callback_func_t callback;
bt_hci_destroy_func_t destroy;
void *user_data;
};
static void cmd_free(void *data)
{
struct cmd *cmd = data;
if (cmd->destroy)
cmd->destroy(cmd->user_data);
free(cmd->data);
free(cmd);
}
static void evt_free(void *data)
{
struct evt *evt = data;
if (evt->destroy)
evt->destroy(evt->user_data);
free(evt);
}
static void send_command(struct bt_hci *hci, uint16_t opcode,
void *data, uint8_t size)
{
uint8_t type = BT_H4_CMD_PKT;
struct bt_hci_cmd_hdr hdr;
struct iovec iov[3];
int iovcnt;
if (hci->num_cmds < 1)
return;
hdr.opcode = cpu_to_le16(opcode);
hdr.plen = size;
iov[0].iov_base = &type;
iov[0].iov_len = 1;
iov[1].iov_base = &hdr;
iov[1].iov_len = sizeof(hdr);
if (size > 0) {
iov[2].iov_base = data;
iov[2].iov_len = size;
iovcnt = 3;
} else
iovcnt = 2;
if (io_send(hci->io, iov, iovcnt) < 0)
return;
hci->num_cmds--;
}
static bool io_write_callback(struct io *io, void *user_data)
{
struct bt_hci *hci = user_data;
struct cmd *cmd;
cmd = queue_pop_head(hci->cmd_queue);
if (cmd) {
send_command(hci, cmd->opcode, cmd->data, cmd->size);
queue_push_tail(hci->rsp_queue, cmd);
}
hci->writer_active = false;
return false;
}
static void wakeup_writer(struct bt_hci *hci)
{
if (hci->writer_active)
return;
if (hci->num_cmds < 1)
return;
if (queue_isempty(hci->cmd_queue))
return;
if (!io_set_write_handler(hci->io, io_write_callback, hci, NULL))
return;
hci->writer_active = true;
}
static bool match_cmd_opcode(const void *a, const void *b)
{
const struct cmd *cmd = a;
uint16_t opcode = PTR_TO_UINT(b);
return cmd->opcode == opcode;
}
static void process_response(struct bt_hci *hci, uint16_t opcode,
const void *data, size_t size)
{
struct cmd *cmd;
if (opcode == BT_HCI_CMD_NOP)
goto done;
cmd = queue_remove_if(hci->rsp_queue, match_cmd_opcode,
UINT_TO_PTR(opcode));
if (!cmd)
return;
if (cmd->callback)
cmd->callback(data, size, cmd->user_data);
cmd_free(cmd);
done:
wakeup_writer(hci);
}
static void process_notify(void *data, void *user_data)
{
struct bt_hci_evt_hdr *hdr = user_data;
struct evt *evt = data;
if (evt->event == hdr->evt)
evt->callback(user_data + sizeof(struct bt_hci_evt_hdr),
hdr->plen, evt->user_data);
}
static void process_event(struct bt_hci *hci, const void *data, size_t size)
{
const struct bt_hci_evt_hdr *hdr = data;
const struct bt_hci_evt_cmd_complete *cc;
const struct bt_hci_evt_cmd_status *cs;
if (size < sizeof(struct bt_hci_evt_hdr))
return;
data += sizeof(struct bt_hci_evt_hdr);
size -= sizeof(struct bt_hci_evt_hdr);
if (hdr->plen != size)
return;
switch (hdr->evt) {
case BT_HCI_EVT_CMD_COMPLETE:
if (size < sizeof(*cc))
return;
cc = data;
hci->num_cmds = cc->ncmd;
process_response(hci, le16_to_cpu(cc->opcode),
data + sizeof(*cc),
size - sizeof(*cc));
break;
case BT_HCI_EVT_CMD_STATUS:
if (size < sizeof(*cs))
return;
cs = data;
hci->num_cmds = cs->ncmd;
process_response(hci, le16_to_cpu(cs->opcode), &cs->status, 1);
break;
default:
queue_foreach(hci->evt_list, process_notify, (void *) hdr);
break;
}
}
static bool io_read_callback(struct io *io, void *user_data)
{
struct bt_hci *hci = user_data;
uint8_t buf[512];
ssize_t len;
int fd;
fd = io_get_fd(hci->io);
if (fd < 0)
return false;
if (hci->is_stream)
return false;
len = read(fd, buf, sizeof(buf));
if (len < 0)
return false;
if (len < 1)
return true;
switch (buf[0]) {
case BT_H4_EVT_PKT:
process_event(hci, buf + 1, len - 1);
break;
}
return true;
}
static struct bt_hci *create_hci(int fd)
{
struct bt_hci *hci;
if (fd < 0)
return NULL;
hci = new0(struct bt_hci, 1);
hci->io = io_new(fd);
if (!hci->io) {
free(hci);
return NULL;
}
hci->is_stream = true;
hci->writer_active = false;
hci->num_cmds = 1;
hci->next_cmd_id = 1;
hci->next_evt_id = 1;
hci->cmd_queue = queue_new();
hci->rsp_queue = queue_new();
hci->evt_list = queue_new();
if (!io_set_read_handler(hci->io, io_read_callback, hci, NULL)) {
queue_destroy(hci->evt_list, NULL);
queue_destroy(hci->rsp_queue, NULL);
queue_destroy(hci->cmd_queue, NULL);
io_destroy(hci->io);
free(hci);
return NULL;
}
return bt_hci_ref(hci);
}
struct bt_hci *bt_hci_new(int fd)
{
struct bt_hci *hci;
hci = create_hci(fd);
if (!hci)
return NULL;
return hci;
}
static int create_socket(uint16_t index, uint16_t channel)
{
struct sockaddr_hci addr;
int fd;
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
BTPROTO_HCI);
if (fd < 0)
return -1;
memset(&addr, 0, sizeof(addr));
addr.hci_family = AF_BLUETOOTH;
addr.hci_dev = index;
addr.hci_channel = channel;
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(fd);
return -1;
}
return fd;
}
struct bt_hci *bt_hci_new_user_channel(uint16_t index)
{
struct bt_hci *hci;
int fd;
fd = create_socket(index, HCI_CHANNEL_USER);
if (fd < 0)
return NULL;
hci = create_hci(fd);
if (!hci) {
close(fd);
return NULL;
}
hci->is_stream = false;
bt_hci_set_close_on_unref(hci, true);
return hci;
}
struct bt_hci *bt_hci_new_raw_device(uint16_t index)
{
struct bt_hci *hci;
struct hci_filter flt;
int fd;
fd = create_socket(index, HCI_CHANNEL_RAW);
if (fd < 0)
return NULL;
memset(&flt, 0, sizeof(flt));
flt.type_mask = 1 << BT_H4_EVT_PKT;
flt.event_mask[0] = 0xffffffff;
flt.event_mask[1] = 0xffffffff;
if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
close(fd);
return NULL;
}
hci = create_hci(fd);
if (!hci) {
close(fd);
return NULL;
}
hci->is_stream = false;
bt_hci_set_close_on_unref(hci, true);
return hci;
}
struct bt_hci *bt_hci_ref(struct bt_hci *hci)
{
if (!hci)
return NULL;
__sync_fetch_and_add(&hci->ref_count, 1);
return hci;
}
void bt_hci_unref(struct bt_hci *hci)
{
if (!hci)
return;
if (__sync_sub_and_fetch(&hci->ref_count, 1))
return;
queue_destroy(hci->evt_list, evt_free);
queue_destroy(hci->cmd_queue, cmd_free);
queue_destroy(hci->rsp_queue, cmd_free);
io_destroy(hci->io);
free(hci);
}
bool bt_hci_set_close_on_unref(struct bt_hci *hci, bool do_close)
{
if (!hci)
return false;
return io_set_close_on_destroy(hci->io, do_close);
}
unsigned int bt_hci_send(struct bt_hci *hci, uint16_t opcode,
const void *data, uint8_t size,
bt_hci_callback_func_t callback,
void *user_data, bt_hci_destroy_func_t destroy)
{
struct cmd *cmd;
if (!hci)
return 0;
cmd = new0(struct cmd, 1);
cmd->opcode = opcode;
cmd->size = size;
if (cmd->size > 0) {
cmd->data = malloc(cmd->size);
if (!cmd->data) {
free(cmd);
return 0;
}
memcpy(cmd->data, data, cmd->size);
}
if (hci->next_cmd_id < 1)
hci->next_cmd_id = 1;
cmd->id = hci->next_cmd_id++;
cmd->callback = callback;
cmd->destroy = destroy;
cmd->user_data = user_data;
if (!queue_push_tail(hci->cmd_queue, cmd)) {
free(cmd->data);
free(cmd);
return 0;
}
wakeup_writer(hci);
return cmd->id;
}
static bool match_cmd_id(const void *a, const void *b)
{
const struct cmd *cmd = a;
unsigned int id = PTR_TO_UINT(b);
return cmd->id == id;
}
bool bt_hci_cancel(struct bt_hci *hci, unsigned int id)
{
struct cmd *cmd;
if (!hci || !id)
return false;
cmd = queue_remove_if(hci->cmd_queue, match_cmd_id, UINT_TO_PTR(id));
if (!cmd) {
cmd = queue_remove_if(hci->rsp_queue, match_cmd_id,
UINT_TO_PTR(id));
if (!cmd)
return false;
}
cmd_free(cmd);
wakeup_writer(hci);
return true;
}
bool bt_hci_flush(struct bt_hci *hci)
{
if (!hci)
return false;
if (hci->writer_active) {
io_set_write_handler(hci->io, NULL, NULL, NULL);
hci->writer_active = false;
}
queue_remove_all(hci->cmd_queue, NULL, NULL, cmd_free);
queue_remove_all(hci->rsp_queue, NULL, NULL, cmd_free);
return true;
}
unsigned int bt_hci_register(struct bt_hci *hci, uint8_t event,
bt_hci_callback_func_t callback,
void *user_data, bt_hci_destroy_func_t destroy)
{
struct evt *evt;
if (!hci)
return 0;
evt = new0(struct evt, 1);
evt->event = event;
if (hci->next_evt_id < 1)
hci->next_evt_id = 1;
evt->id = hci->next_evt_id++;
evt->callback = callback;
evt->destroy = destroy;
evt->user_data = user_data;
if (!queue_push_tail(hci->evt_list, evt)) {
free(evt);
return 0;
}
return evt->id;
}
static bool match_evt_id(const void *a, const void *b)
{
const struct evt *evt = a;
unsigned int id = PTR_TO_UINT(b);
return evt->id == id;
}
bool bt_hci_unregister(struct bt_hci *hci, unsigned int id)
{
struct evt *evt;
if (!hci || !id)
return false;
evt = queue_remove_if(hci->evt_list, match_evt_id, UINT_TO_PTR(id));
if (!evt)
return false;
evt_free(evt);
return true;
}

View File

@ -0,0 +1,53 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
typedef void (*bt_hci_destroy_func_t)(void *user_data);
struct bt_hci;
struct bt_hci *bt_hci_new(int fd);
struct bt_hci *bt_hci_new_user_channel(uint16_t index);
struct bt_hci *bt_hci_new_raw_device(uint16_t index);
struct bt_hci *bt_hci_ref(struct bt_hci *hci);
void bt_hci_unref(struct bt_hci *hci);
bool bt_hci_set_close_on_unref(struct bt_hci *hci, bool do_close);
typedef void (*bt_hci_callback_func_t)(const void *data, uint8_t size,
void *user_data);
unsigned int bt_hci_send(struct bt_hci *hci, uint16_t opcode,
const void *data, uint8_t size,
bt_hci_callback_func_t callback,
void *user_data, bt_hci_destroy_func_t destroy);
bool bt_hci_cancel(struct bt_hci *hci, unsigned int id);
bool bt_hci_flush(struct bt_hci *hci);
unsigned int bt_hci_register(struct bt_hci *hci, uint8_t event,
bt_hci_callback_func_t callback,
void *user_data, bt_hci_destroy_func_t destroy);
bool bt_hci_unregister(struct bt_hci *hci, unsigned int id);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
enum hfp_result {
HFP_RESULT_OK = 0,
HFP_RESULT_CONNECT = 1,
HFP_RESULT_RING = 2,
HFP_RESULT_NO_CARRIER = 3,
HFP_RESULT_ERROR = 4,
HFP_RESULT_NO_DIALTONE = 6,
HFP_RESULT_BUSY = 7,
HFP_RESULT_NO_ANSWER = 8,
HFP_RESULT_DELAYED = 9,
HFP_RESULT_BLACKLISTED = 10,
HFP_RESULT_CME_ERROR = 11,
};
enum hfp_error {
HFP_ERROR_AG_FAILURE = 0,
HFP_ERROR_NO_CONNECTION_TO_PHONE = 1,
HFP_ERROR_OPERATION_NOT_ALLOWED = 3,
HFP_ERROR_OPERATION_NOT_SUPPORTED = 4,
HFP_ERROR_PH_SIM_PIN_REQUIRED = 5,
HFP_ERROR_SIM_NOT_INSERTED = 10,
HFP_ERROR_SIM_PIN_REQUIRED = 11,
HFP_ERROR_SIM_PUK_REQUIRED = 12,
HFP_ERROR_SIM_FAILURE = 13,
HFP_ERROR_SIM_BUSY = 14,
HFP_ERROR_INCORRECT_PASSWORD = 16,
HFP_ERROR_SIM_PIN2_REQUIRED = 17,
HFP_ERROR_SIM_PUK2_REQUIRED = 18,
HFP_ERROR_MEMORY_FULL = 20,
HFP_ERROR_INVALID_INDEX = 21,
HFP_ERROR_MEMORY_FAILURE = 23,
HFP_ERROR_TEXT_STRING_TOO_LONG = 24,
HFP_ERROR_INVALID_CHARS_IN_TEXT_STRING = 25,
HFP_ERROR_DIAL_STRING_TO_LONG = 26,
HFP_ERROR_INVALID_CHARS_IN_DIAL_STRING = 27,
HFP_ERROR_NO_NETWORK_SERVICE = 30,
HFP_ERROR_NETWORK_TIMEOUT = 31,
HFP_ERROR_NETWORK_NOT_ALLOWED = 32,
};
enum hfp_gw_cmd_type {
HFP_GW_CMD_TYPE_READ,
HFP_GW_CMD_TYPE_SET,
HFP_GW_CMD_TYPE_TEST,
HFP_GW_CMD_TYPE_COMMAND
};
struct hfp_context;
typedef void (*hfp_result_func_t)(struct hfp_context *context,
enum hfp_gw_cmd_type type, void *user_data);
typedef void (*hfp_destroy_func_t)(void *user_data);
typedef void (*hfp_debug_func_t)(const char *str, void *user_data);
typedef void (*hfp_command_func_t)(const char *command, void *user_data);
typedef void (*hfp_disconnect_func_t)(void *user_data);
struct hfp_gw;
struct hfp_gw *hfp_gw_new(int fd);
struct hfp_gw *hfp_gw_ref(struct hfp_gw *hfp);
void hfp_gw_unref(struct hfp_gw *hfp);
bool hfp_gw_set_debug(struct hfp_gw *hfp, hfp_debug_func_t callback,
void *user_data, hfp_destroy_func_t destroy);
bool hfp_gw_set_close_on_unref(struct hfp_gw *hfp, bool do_close);
bool hfp_gw_set_permissive_syntax(struct hfp_gw *hfp, bool permissive);
bool hfp_gw_send_result(struct hfp_gw *hfp, enum hfp_result result);
bool hfp_gw_send_error(struct hfp_gw *hfp, enum hfp_error error);
bool hfp_gw_send_info(struct hfp_gw *hfp, const char *format, ...)
__attribute__((format(printf, 2, 3)));
bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
hfp_command_func_t callback,
void *user_data, hfp_destroy_func_t destroy);
bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
hfp_disconnect_func_t callback,
void *user_data,
hfp_destroy_func_t destroy);
bool hfp_gw_disconnect(struct hfp_gw *hfp);
bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
const char *prefix,
void *user_data,
hfp_destroy_func_t destroy);
bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);
bool hfp_context_get_number(struct hfp_context *context,
unsigned int *val);
bool hfp_context_get_number_default(struct hfp_context *context,
unsigned int *val,
unsigned int default_val);
bool hfp_context_open_container(struct hfp_context *context);
bool hfp_context_close_container(struct hfp_context *context);
bool hfp_context_get_string(struct hfp_context *context, char *buf,
uint8_t len);
bool hfp_context_get_unquoted_string(struct hfp_context *context,
char *buf, uint8_t len);
bool hfp_context_get_range(struct hfp_context *context, unsigned int *min,
unsigned int *max);
bool hfp_context_has_next(struct hfp_context *context);
void hfp_context_skip_field(struct hfp_context *context);
typedef void (*hfp_hf_result_func_t)(struct hfp_context *context,
void *user_data);
typedef void (*hfp_response_func_t)(enum hfp_result result,
enum hfp_error cme_err,
void *user_data);
struct hfp_hf;
struct hfp_hf *hfp_hf_new(int fd);
struct hfp_hf *hfp_hf_ref(struct hfp_hf *hfp);
void hfp_hf_unref(struct hfp_hf *hfp);
bool hfp_hf_set_debug(struct hfp_hf *hfp, hfp_debug_func_t callback,
void *user_data, hfp_destroy_func_t destroy);
bool hfp_hf_set_close_on_unref(struct hfp_hf *hfp, bool do_close);
bool hfp_hf_set_disconnect_handler(struct hfp_hf *hfp,
hfp_disconnect_func_t callback,
void *user_data,
hfp_destroy_func_t destroy);
bool hfp_hf_disconnect(struct hfp_hf *hfp);
bool hfp_hf_register(struct hfp_hf *hfp, hfp_hf_result_func_t callback,
const char *prefix, void *user_data,
hfp_destroy_func_t destroy);
bool hfp_hf_unregister(struct hfp_hf *hfp, const char *prefix);
bool hfp_hf_send_command(struct hfp_hf *hfp, hfp_response_func_t resp_cb,
void *user_data, const char *format, ...);

View File

@ -0,0 +1,291 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <glib.h>
#include "src/shared/io.h"
#include "gattlib_internal.h"
struct io_watch {
struct io *io;
GSource* id;
io_callback_func_t callback;
io_destroy_func_t destroy;
void *user_data;
};
struct io {
int ref_count;
GIOChannel *channel;
struct io_watch *read_watch;
struct io_watch *write_watch;
struct io_watch *disconnect_watch;
};
static struct io *io_ref(struct io *io)
{
if (!io)
return NULL;
__sync_fetch_and_add(&io->ref_count, 1);
return io;
}
static void io_unref(struct io *io)
{
if (!io)
return;
if (__sync_sub_and_fetch(&io->ref_count, 1))
return;
g_free(io);
}
struct io *io_new(int fd)
{
struct io *io;
if (fd < 0)
return NULL;
io = g_try_new0(struct io, 1);
if (!io)
return NULL;
io->channel = g_io_channel_unix_new(fd);
g_io_channel_set_encoding(io->channel, NULL, NULL);
g_io_channel_set_buffered(io->channel, FALSE);
g_io_channel_set_close_on_unref(io->channel, FALSE);
return io_ref(io);
}
static void watch_destroy(void *user_data)
{
struct io_watch *watch = user_data;
struct io *io = watch->io;
if (watch == io->read_watch)
io->read_watch = NULL;
else if (watch == io->write_watch)
io->write_watch = NULL;
else if (watch == io->disconnect_watch)
io->disconnect_watch = NULL;
if (watch->destroy)
watch->destroy(watch->user_data);
io_unref(watch->io);
g_free(watch);
}
void io_destroy(struct io *io)
{
if (!io)
return;
if (io->read_watch) {
g_source_destroy(io->read_watch->id);
io->read_watch = NULL;
}
if (io->write_watch) {
g_source_destroy(io->write_watch->id);
io->write_watch = NULL;
}
if (io->disconnect_watch) {
g_source_destroy(io->disconnect_watch->id);
io->disconnect_watch = NULL;
}
g_io_channel_unref(io->channel);
io->channel = NULL;
io_unref(io);
}
int io_get_fd(struct io *io)
{
if (!io)
return -ENOTCONN;
return g_io_channel_unix_get_fd(io->channel);
}
bool io_set_close_on_destroy(struct io *io, bool do_close)
{
if (!io)
return false;
if (do_close)
g_io_channel_set_close_on_unref(io->channel, TRUE);
else
g_io_channel_set_close_on_unref(io->channel, FALSE);
return true;
}
static gboolean watch_callback(GIOChannel *channel, GIOCondition cond,
gpointer user_data)
{
struct io_watch *watch = user_data;
bool result, destroy;
destroy = watch == watch->io->disconnect_watch;
if (!destroy && (cond & (G_IO_ERR | G_IO_NVAL)))
return FALSE;
if (watch->callback)
result = watch->callback(watch->io, watch->user_data);
else
result = false;
return result ? TRUE : FALSE;
}
static struct io_watch *watch_new(struct io *io, GIOCondition cond,
io_callback_func_t callback, void *user_data,
io_destroy_func_t destroy)
{
struct io_watch *watch;
watch = g_try_new0(struct io_watch, 1);
if (!watch)
return NULL;
watch->io = io_ref(io);
watch->callback = callback;
watch->destroy = destroy;
watch->user_data = user_data;
watch->id = gattlib_watch_connection_full(io->channel,
cond | G_IO_ERR | G_IO_NVAL,
watch_callback, watch,
watch_destroy);
if (watch->id == NULL) {
watch_destroy(watch);
return NULL;
}
return watch;
}
static bool io_set_handler(struct io *io, GIOCondition cond,
io_callback_func_t callback, void *user_data,
io_destroy_func_t destroy)
{
struct io_watch **watch;
if (!io)
return false;
switch (cond) {
case G_IO_IN:
watch = &io->read_watch;
break;
case G_IO_OUT:
watch = &io->write_watch;
break;
case G_IO_HUP:
watch = &io->disconnect_watch;
break;
case G_IO_PRI:
case G_IO_ERR:
case G_IO_NVAL:
default:
return false;
}
if (*watch) {
g_source_destroy((*watch)->id);
*watch = NULL;
}
if (!callback)
return true;
*watch = watch_new(io, cond, callback, user_data, destroy);
if (!*watch)
return false;
return true;
}
bool io_set_read_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy)
{
return io_set_handler(io, G_IO_IN, callback, user_data, destroy);
}
bool io_set_write_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy)
{
return io_set_handler(io, G_IO_OUT, callback, user_data, destroy);
}
bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy)
{
return io_set_handler(io, G_IO_HUP, callback, user_data, destroy);
}
ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
{
int fd;
ssize_t ret;
if (!io || !io->channel)
return -ENOTCONN;
fd = io_get_fd(io);
do {
ret = writev(fd, iov, iovcnt);
} while (ret < 0 && errno == EINTR);
if (ret < 0)
return -errno;
return ret;
}
bool io_shutdown(struct io *io)
{
if (!io || !io->channel)
return false;
return g_io_channel_shutdown(io->channel, TRUE, NULL)
== G_IO_STATUS_NORMAL;
}

View File

@ -0,0 +1,47 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <sys/uio.h>
typedef void (*io_destroy_func_t)(void *data);
struct io;
struct io *io_new(int fd);
void io_destroy(struct io *io);
int io_get_fd(struct io *io);
bool io_set_close_on_destroy(struct io *io, bool do_close);
ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt);
bool io_shutdown(struct io *io);
typedef bool (*io_callback_func_t)(struct io *io, void *user_data);
bool io_set_read_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy);
bool io_set_write_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy);
bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy);

View File

@ -0,0 +1,402 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011-2014 Intel Corporation
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include "mainloop.h"
#define MAX_EPOLL_EVENTS 10
static int epoll_fd;
static int epoll_terminate;
static int exit_status;
struct mainloop_data {
int fd;
uint32_t events;
mainloop_event_func callback;
mainloop_destroy_func destroy;
void *user_data;
};
#define MAX_MAINLOOP_ENTRIES 128
static struct mainloop_data *mainloop_list[MAX_MAINLOOP_ENTRIES];
struct timeout_data {
int fd;
mainloop_timeout_func callback;
mainloop_destroy_func destroy;
void *user_data;
};
struct signal_data {
int fd;
sigset_t mask;
mainloop_signal_func callback;
mainloop_destroy_func destroy;
void *user_data;
};
static struct signal_data *signal_data;
void mainloop_init(void)
{
unsigned int i;
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
for (i = 0; i < MAX_MAINLOOP_ENTRIES; i++)
mainloop_list[i] = NULL;
epoll_terminate = 0;
}
void mainloop_quit(void)
{
epoll_terminate = 1;
}
void mainloop_exit_success(void)
{
exit_status = EXIT_SUCCESS;
epoll_terminate = 1;
}
void mainloop_exit_failure(void)
{
exit_status = EXIT_FAILURE;
epoll_terminate = 1;
}
static void signal_callback(int fd, uint32_t events, void *user_data)
{
struct signal_data *data = user_data;
struct signalfd_siginfo si;
ssize_t result;
if (events & (EPOLLERR | EPOLLHUP)) {
mainloop_quit();
return;
}
result = read(fd, &si, sizeof(si));
if (result != sizeof(si))
return;
if (data->callback)
data->callback(si.ssi_signo, data->user_data);
}
int mainloop_run(void)
{
unsigned int i;
if (signal_data) {
if (sigprocmask(SIG_BLOCK, &signal_data->mask, NULL) < 0)
return EXIT_FAILURE;
signal_data->fd = signalfd(-1, &signal_data->mask,
SFD_NONBLOCK | SFD_CLOEXEC);
if (signal_data->fd < 0)
return EXIT_FAILURE;
if (mainloop_add_fd(signal_data->fd, EPOLLIN,
signal_callback, signal_data, NULL) < 0) {
close(signal_data->fd);
return EXIT_FAILURE;
}
}
exit_status = EXIT_SUCCESS;
while (!epoll_terminate) {
struct epoll_event events[MAX_EPOLL_EVENTS];
int n, nfds;
nfds = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, -1);
if (nfds < 0)
continue;
for (n = 0; n < nfds; n++) {
struct mainloop_data *data = events[n].data.ptr;
data->callback(data->fd, events[n].events,
data->user_data);
}
}
if (signal_data) {
mainloop_remove_fd(signal_data->fd);
close(signal_data->fd);
if (signal_data->destroy)
signal_data->destroy(signal_data->user_data);
}
for (i = 0; i < MAX_MAINLOOP_ENTRIES; i++) {
struct mainloop_data *data = mainloop_list[i];
mainloop_list[i] = NULL;
if (data) {
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, data->fd, NULL);
if (data->destroy)
data->destroy(data->user_data);
free(data);
}
}
close(epoll_fd);
epoll_fd = 0;
return exit_status;
}
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct mainloop_data *data;
struct epoll_event ev;
int err;
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1 || !callback)
return -EINVAL;
data = malloc(sizeof(*data));
if (!data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
data->fd = fd;
data->events = events;
data->callback = callback;
data->destroy = destroy;
data->user_data = user_data;
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.ptr = data;
err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev);
if (err < 0) {
free(data);
return err;
}
mainloop_list[fd] = data;
return 0;
}
int mainloop_modify_fd(int fd, uint32_t events)
{
struct mainloop_data *data;
struct epoll_event ev;
int err;
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1)
return -EINVAL;
data = mainloop_list[fd];
if (!data)
return -ENXIO;
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.ptr = data;
err = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, data->fd, &ev);
if (err < 0)
return err;
data->events = events;
return 0;
}
int mainloop_remove_fd(int fd)
{
struct mainloop_data *data;
int err;
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1)
return -EINVAL;
data = mainloop_list[fd];
if (!data)
return -ENXIO;
mainloop_list[fd] = NULL;
err = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, data->fd, NULL);
if (data->destroy)
data->destroy(data->user_data);
free(data);
return err;
}
static void timeout_destroy(void *user_data)
{
struct timeout_data *data = user_data;
close(data->fd);
data->fd = -1;
if (data->destroy)
data->destroy(data->user_data);
}
static void timeout_callback(int fd, uint32_t events, void *user_data)
{
struct timeout_data *data = user_data;
uint64_t expired;
ssize_t result;
if (events & (EPOLLERR | EPOLLHUP))
return;
result = read(data->fd, &expired, sizeof(expired));
if (result != sizeof(expired))
return;
if (data->callback)
data->callback(data->fd, data->user_data);
}
static inline int timeout_set(int fd, unsigned int msec)
{
struct itimerspec itimer;
unsigned int sec = msec / 1000;
memset(&itimer, 0, sizeof(itimer));
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_nsec = 0;
itimer.it_value.tv_sec = sec;
itimer.it_value.tv_nsec = (msec - (sec * 1000)) * 1000;
return timerfd_settime(fd, 0, &itimer, NULL);
}
int mainloop_add_timeout(unsigned int msec, mainloop_timeout_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct timeout_data *data;
if (!callback)
return -EINVAL;
data = malloc(sizeof(*data));
if (!data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
data->callback = callback;
data->destroy = destroy;
data->user_data = user_data;
data->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (data->fd < 0) {
free(data);
return -EIO;
}
if (msec > 0) {
if (timeout_set(data->fd, msec) < 0) {
close(data->fd);
free(data);
return -EIO;
}
}
if (mainloop_add_fd(data->fd, EPOLLIN | EPOLLONESHOT,
timeout_callback, data, timeout_destroy) < 0) {
close(data->fd);
free(data);
return -EIO;
}
return data->fd;
}
int mainloop_modify_timeout(int id, unsigned int msec)
{
if (msec > 0) {
if (timeout_set(id, msec) < 0)
return -EIO;
}
if (mainloop_modify_fd(id, EPOLLIN | EPOLLONESHOT) < 0)
return -EIO;
return 0;
}
int mainloop_remove_timeout(int id)
{
return mainloop_remove_fd(id);
}
int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct signal_data *data;
if (!mask || !callback)
return -EINVAL;
data = malloc(sizeof(*data));
if (!data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
data->callback = callback;
data->destroy = destroy;
data->user_data = user_data;
data->fd = -1;
memcpy(&data->mask, mask, sizeof(sigset_t));
free(signal_data);
signal_data = data;
return 0;
}

View File

@ -0,0 +1,51 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2011-2014 Intel Corporation
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
*
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <signal.h>
#include <sys/epoll.h>
typedef void (*mainloop_destroy_func) (void *user_data);
typedef void (*mainloop_event_func) (int fd, uint32_t events, void *user_data);
typedef void (*mainloop_timeout_func) (int id, void *user_data);
typedef void (*mainloop_signal_func) (int signum, void *user_data);
void mainloop_init(void);
void mainloop_quit(void);
void mainloop_exit_success(void);
void mainloop_exit_failure(void);
int mainloop_run(void);
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy);
int mainloop_modify_fd(int fd, uint32_t events);
int mainloop_remove_fd(int fd);
int mainloop_add_timeout(unsigned int msec, mainloop_timeout_func callback,
void *user_data, mainloop_destroy_func destroy);
int mainloop_modify_timeout(int fd, unsigned int msec);
int mainloop_remove_timeout(int id);
int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback,
void *user_data, mainloop_destroy_func destroy);

View File

@ -0,0 +1,801 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
#include "lib/hci.h"
#include "src/shared/io.h"
#include "src/shared/queue.h"
#include "src/shared/util.h"
#include "src/shared/mgmt.h"
struct mgmt {
int ref_count;
int fd;
bool close_on_unref;
struct io *io;
bool writer_active;
struct queue *request_queue;
struct queue *reply_queue;
struct queue *pending_list;
struct queue *notify_list;
unsigned int next_request_id;
unsigned int next_notify_id;
bool need_notify_cleanup;
bool in_notify;
void *buf;
uint16_t len;
mgmt_debug_func_t debug_callback;
mgmt_destroy_func_t debug_destroy;
void *debug_data;
};
struct mgmt_request {
unsigned int id;
uint16_t opcode;
uint16_t index;
void *buf;
uint16_t len;
mgmt_request_func_t callback;
mgmt_destroy_func_t destroy;
void *user_data;
};
struct mgmt_notify {
unsigned int id;
uint16_t event;
uint16_t index;
bool removed;
mgmt_notify_func_t callback;
mgmt_destroy_func_t destroy;
void *user_data;
};
static void destroy_request(void *data)
{
struct mgmt_request *request = data;
if (request->destroy)
request->destroy(request->user_data);
free(request->buf);
free(request);
}
static bool match_request_id(const void *a, const void *b)
{
const struct mgmt_request *request = a;
unsigned int id = PTR_TO_UINT(b);
return request->id == id;
}
static bool match_request_index(const void *a, const void *b)
{
const struct mgmt_request *request = a;
uint16_t index = PTR_TO_UINT(b);
return request->index == index;
}
static void destroy_notify(void *data)
{
struct mgmt_notify *notify = data;
if (notify->destroy)
notify->destroy(notify->user_data);
free(notify);
}
static bool match_notify_id(const void *a, const void *b)
{
const struct mgmt_notify *notify = a;
unsigned int id = PTR_TO_UINT(b);
return notify->id == id;
}
static bool match_notify_index(const void *a, const void *b)
{
const struct mgmt_notify *notify = a;
uint16_t index = PTR_TO_UINT(b);
return notify->index == index;
}
static bool match_notify_removed(const void *a, const void *b)
{
const struct mgmt_notify *notify = a;
return notify->removed;
}
static void mark_notify_removed(void *data , void *user_data)
{
struct mgmt_notify *notify = data;
uint16_t index = PTR_TO_UINT(user_data);
if (notify->index == index || index == MGMT_INDEX_NONE)
notify->removed = true;
}
static void write_watch_destroy(void *user_data)
{
struct mgmt *mgmt = user_data;
mgmt->writer_active = false;
}
static bool send_request(struct mgmt *mgmt, struct mgmt_request *request)
{
struct iovec iov;
ssize_t ret;
iov.iov_base = request->buf;
iov.iov_len = request->len;
ret = io_send(mgmt->io, &iov, 1);
if (ret < 0) {
util_debug(mgmt->debug_callback, mgmt->debug_data,
"write failed: %s", strerror(-ret));
if (request->callback)
request->callback(MGMT_STATUS_FAILED, 0, NULL,
request->user_data);
destroy_request(request);
return false;
}
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] command 0x%04x",
request->index, request->opcode);
util_hexdump('<', request->buf, ret, mgmt->debug_callback,
mgmt->debug_data);
queue_push_tail(mgmt->pending_list, request);
return true;
}
static bool can_write_data(struct io *io, void *user_data)
{
struct mgmt *mgmt = user_data;
struct mgmt_request *request;
bool can_write;
request = queue_pop_head(mgmt->reply_queue);
if (!request) {
/* only reply commands can jump the queue */
if (!queue_isempty(mgmt->pending_list))
return false;
request = queue_pop_head(mgmt->request_queue);
if (!request)
return false;
can_write = false;
} else {
/* allow multiple replies to jump the queue */
can_write = !queue_isempty(mgmt->reply_queue);
}
if (!send_request(mgmt, request))
return true;
return can_write;
}
static void wakeup_writer(struct mgmt *mgmt)
{
if (!queue_isempty(mgmt->pending_list)) {
/* only queued reply commands trigger wakeup */
if (queue_isempty(mgmt->reply_queue))
return;
}
if (mgmt->writer_active)
return;
mgmt->writer_active = true;
io_set_write_handler(mgmt->io, can_write_data, mgmt,
write_watch_destroy);
}
struct opcode_index {
uint16_t opcode;
uint16_t index;
};
static bool match_request_opcode_index(const void *a, const void *b)
{
const struct mgmt_request *request = a;
const struct opcode_index *match = b;
return request->opcode == match->opcode &&
request->index == match->index;
}
static void request_complete(struct mgmt *mgmt, uint8_t status,
uint16_t opcode, uint16_t index,
uint16_t length, const void *param)
{
struct opcode_index match = { .opcode = opcode, .index = index };
struct mgmt_request *request;
request = queue_remove_if(mgmt->pending_list,
match_request_opcode_index, &match);
if (request) {
if (request->callback)
request->callback(status, length, param,
request->user_data);
destroy_request(request);
}
wakeup_writer(mgmt);
}
struct event_index {
uint16_t event;
uint16_t index;
uint16_t length;
const void *param;
};
static void notify_handler(void *data, void *user_data)
{
struct mgmt_notify *notify = data;
struct event_index *match = user_data;
if (notify->removed)
return;
if (notify->event != match->event)
return;
if (notify->index != match->index && notify->index != MGMT_INDEX_NONE)
return;
if (notify->callback)
notify->callback(match->index, match->length, match->param,
notify->user_data);
}
static void process_notify(struct mgmt *mgmt, uint16_t event, uint16_t index,
uint16_t length, const void *param)
{
struct event_index match = { .event = event, .index = index,
.length = length, .param = param };
mgmt->in_notify = true;
queue_foreach(mgmt->notify_list, notify_handler, &match);
mgmt->in_notify = false;
if (mgmt->need_notify_cleanup) {
queue_remove_all(mgmt->notify_list, match_notify_removed,
NULL, destroy_notify);
mgmt->need_notify_cleanup = false;
}
}
static bool can_read_data(struct io *io, void *user_data)
{
struct mgmt *mgmt = user_data;
struct mgmt_hdr *hdr;
struct mgmt_ev_cmd_complete *cc;
struct mgmt_ev_cmd_status *cs;
ssize_t bytes_read;
uint16_t opcode, event, index, length;
bytes_read = read(mgmt->fd, mgmt->buf, mgmt->len);
if (bytes_read < 0)
return false;
util_hexdump('>', mgmt->buf, bytes_read,
mgmt->debug_callback, mgmt->debug_data);
if (bytes_read < MGMT_HDR_SIZE)
return true;
hdr = mgmt->buf;
event = btohs(hdr->opcode);
index = btohs(hdr->index);
length = btohs(hdr->len);
if (bytes_read < length + MGMT_HDR_SIZE)
return true;
mgmt_ref(mgmt);
switch (event) {
case MGMT_EV_CMD_COMPLETE:
cc = mgmt->buf + MGMT_HDR_SIZE;
opcode = btohs(cc->opcode);
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] command 0x%04x complete: 0x%02x",
index, opcode, cc->status);
request_complete(mgmt, cc->status, opcode, index, length - 3,
mgmt->buf + MGMT_HDR_SIZE + 3);
break;
case MGMT_EV_CMD_STATUS:
cs = mgmt->buf + MGMT_HDR_SIZE;
opcode = btohs(cs->opcode);
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] command 0x%02x status: 0x%02x",
index, opcode, cs->status);
request_complete(mgmt, cs->status, opcode, index, 0, NULL);
break;
default:
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] event 0x%04x", index, event);
process_notify(mgmt, event, index, length,
mgmt->buf + MGMT_HDR_SIZE);
break;
}
mgmt_unref(mgmt);
return true;
}
struct mgmt *mgmt_new(int fd)
{
struct mgmt *mgmt;
if (fd < 0)
return NULL;
mgmt = new0(struct mgmt, 1);
mgmt->fd = fd;
mgmt->close_on_unref = false;
mgmt->len = 512;
mgmt->buf = malloc(mgmt->len);
if (!mgmt->buf) {
free(mgmt);
return NULL;
}
mgmt->io = io_new(fd);
if (!mgmt->io) {
free(mgmt->buf);
free(mgmt);
return NULL;
}
mgmt->request_queue = queue_new();
mgmt->reply_queue = queue_new();
mgmt->pending_list = queue_new();
mgmt->notify_list = queue_new();
if (!io_set_read_handler(mgmt->io, can_read_data, mgmt, NULL)) {
queue_destroy(mgmt->notify_list, NULL);
queue_destroy(mgmt->pending_list, NULL);
queue_destroy(mgmt->reply_queue, NULL);
queue_destroy(mgmt->request_queue, NULL);
io_destroy(mgmt->io);
free(mgmt->buf);
free(mgmt);
return NULL;
}
mgmt->writer_active = false;
return mgmt_ref(mgmt);
}
struct mgmt *mgmt_new_default(void)
{
struct mgmt *mgmt;
union {
struct sockaddr common;
struct sockaddr_hci hci;
} addr;
int fd;
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
BTPROTO_HCI);
if (fd < 0)
return NULL;
memset(&addr, 0, sizeof(addr));
addr.hci.hci_family = AF_BLUETOOTH;
addr.hci.hci_dev = HCI_DEV_NONE;
addr.hci.hci_channel = HCI_CHANNEL_CONTROL;
if (bind(fd, &addr.common, sizeof(addr.hci)) < 0) {
close(fd);
return NULL;
}
mgmt = mgmt_new(fd);
if (!mgmt) {
close(fd);
return NULL;
}
mgmt->close_on_unref = true;
return mgmt;
}
struct mgmt *mgmt_ref(struct mgmt *mgmt)
{
if (!mgmt)
return NULL;
__sync_fetch_and_add(&mgmt->ref_count, 1);
return mgmt;
}
void mgmt_unref(struct mgmt *mgmt)
{
if (!mgmt)
return;
if (__sync_sub_and_fetch(&mgmt->ref_count, 1))
return;
mgmt_unregister_all(mgmt);
mgmt_cancel_all(mgmt);
queue_destroy(mgmt->reply_queue, NULL);
queue_destroy(mgmt->request_queue, NULL);
io_set_write_handler(mgmt->io, NULL, NULL, NULL);
io_set_read_handler(mgmt->io, NULL, NULL, NULL);
io_destroy(mgmt->io);
mgmt->io = NULL;
if (mgmt->close_on_unref)
close(mgmt->fd);
if (mgmt->debug_destroy)
mgmt->debug_destroy(mgmt->debug_data);
free(mgmt->buf);
mgmt->buf = NULL;
if (!mgmt->in_notify) {
queue_destroy(mgmt->notify_list, NULL);
queue_destroy(mgmt->pending_list, NULL);
free(mgmt);
return;
}
}
bool mgmt_set_debug(struct mgmt *mgmt, mgmt_debug_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
if (!mgmt)
return false;
if (mgmt->debug_destroy)
mgmt->debug_destroy(mgmt->debug_data);
mgmt->debug_callback = callback;
mgmt->debug_destroy = destroy;
mgmt->debug_data = user_data;
return true;
}
bool mgmt_set_close_on_unref(struct mgmt *mgmt, bool do_close)
{
if (!mgmt)
return false;
mgmt->close_on_unref = do_close;
return true;
}
static struct mgmt_request *create_request(uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
struct mgmt_request *request;
struct mgmt_hdr *hdr;
if (!opcode)
return NULL;
if (length > 0 && !param)
return NULL;
request = new0(struct mgmt_request, 1);
request->len = length + MGMT_HDR_SIZE;
request->buf = malloc(request->len);
if (!request->buf) {
free(request);
return NULL;
}
if (length > 0)
memcpy(request->buf + MGMT_HDR_SIZE, param, length);
hdr = request->buf;
hdr->opcode = htobs(opcode);
hdr->index = htobs(index);
hdr->len = htobs(length);
request->opcode = opcode;
request->index = index;
request->callback = callback;
request->destroy = destroy;
request->user_data = user_data;
return request;
}
unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
struct mgmt_request *request;
if (!mgmt)
return 0;
request = create_request(opcode, index, length, param,
callback, user_data, destroy);
if (!request)
return 0;
if (mgmt->next_request_id < 1)
mgmt->next_request_id = 1;
request->id = mgmt->next_request_id++;
if (!queue_push_tail(mgmt->request_queue, request)) {
free(request->buf);
free(request);
return 0;
}
wakeup_writer(mgmt);
return request->id;
}
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
struct mgmt_request *request;
if (!mgmt)
return 0;
request = create_request(opcode, index, length, param,
callback, user_data, destroy);
if (!request)
return 0;
if (mgmt->next_request_id < 1)
mgmt->next_request_id = 1;
request->id = mgmt->next_request_id++;
if (!send_request(mgmt, request))
return 0;
return request->id;
}
unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
struct mgmt_request *request;
if (!mgmt)
return 0;
request = create_request(opcode, index, length, param,
callback, user_data, destroy);
if (!request)
return 0;
if (mgmt->next_request_id < 1)
mgmt->next_request_id = 1;
request->id = mgmt->next_request_id++;
if (!queue_push_tail(mgmt->reply_queue, request)) {
free(request->buf);
free(request);
return 0;
}
wakeup_writer(mgmt);
return request->id;
}
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id)
{
struct mgmt_request *request;
if (!mgmt || !id)
return false;
request = queue_remove_if(mgmt->request_queue, match_request_id,
UINT_TO_PTR(id));
if (request)
goto done;
request = queue_remove_if(mgmt->reply_queue, match_request_id,
UINT_TO_PTR(id));
if (request)
goto done;
request = queue_remove_if(mgmt->pending_list, match_request_id,
UINT_TO_PTR(id));
if (!request)
return false;
done:
destroy_request(request);
wakeup_writer(mgmt);
return true;
}
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index)
{
if (!mgmt)
return false;
queue_remove_all(mgmt->request_queue, match_request_index,
UINT_TO_PTR(index), destroy_request);
queue_remove_all(mgmt->reply_queue, match_request_index,
UINT_TO_PTR(index), destroy_request);
queue_remove_all(mgmt->pending_list, match_request_index,
UINT_TO_PTR(index), destroy_request);
return true;
}
bool mgmt_cancel_all(struct mgmt *mgmt)
{
if (!mgmt)
return false;
queue_remove_all(mgmt->pending_list, NULL, NULL, destroy_request);
queue_remove_all(mgmt->reply_queue, NULL, NULL, destroy_request);
queue_remove_all(mgmt->request_queue, NULL, NULL, destroy_request);
return true;
}
unsigned int mgmt_register(struct mgmt *mgmt, uint16_t event, uint16_t index,
mgmt_notify_func_t callback,
void *user_data, mgmt_destroy_func_t destroy)
{
struct mgmt_notify *notify;
if (!mgmt || !event)
return 0;
notify = new0(struct mgmt_notify, 1);
notify->event = event;
notify->index = index;
notify->callback = callback;
notify->destroy = destroy;
notify->user_data = user_data;
if (mgmt->next_notify_id < 1)
mgmt->next_notify_id = 1;
notify->id = mgmt->next_notify_id++;
if (!queue_push_tail(mgmt->notify_list, notify)) {
free(notify);
return 0;
}
return notify->id;
}
bool mgmt_unregister(struct mgmt *mgmt, unsigned int id)
{
struct mgmt_notify *notify;
if (!mgmt || !id)
return false;
notify = queue_remove_if(mgmt->notify_list, match_notify_id,
UINT_TO_PTR(id));
if (!notify)
return false;
if (!mgmt->in_notify) {
destroy_notify(notify);
return true;
}
notify->removed = true;
mgmt->need_notify_cleanup = true;
return true;
}
bool mgmt_unregister_index(struct mgmt *mgmt, uint16_t index)
{
if (!mgmt)
return false;
if (mgmt->in_notify) {
queue_foreach(mgmt->notify_list, mark_notify_removed,
UINT_TO_PTR(index));
mgmt->need_notify_cleanup = true;
} else
queue_remove_all(mgmt->notify_list, match_notify_index,
UINT_TO_PTR(index), destroy_notify);
return true;
}
bool mgmt_unregister_all(struct mgmt *mgmt)
{
if (!mgmt)
return false;
if (mgmt->in_notify) {
queue_foreach(mgmt->notify_list, mark_notify_removed,
UINT_TO_PTR(MGMT_INDEX_NONE));
mgmt->need_notify_cleanup = true;
} else
queue_remove_all(mgmt->notify_list, NULL, NULL, destroy_notify);
return true;
}

View File

@ -0,0 +1,73 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdbool.h>
#include <stdint.h>
#define MGMT_VERSION(v, r) (((v) << 16) + (r))
typedef void (*mgmt_destroy_func_t)(void *user_data);
struct mgmt;
struct mgmt *mgmt_new(int fd);
struct mgmt *mgmt_new_default(void);
struct mgmt *mgmt_ref(struct mgmt *mgmt);
void mgmt_unref(struct mgmt *mgmt);
typedef void (*mgmt_debug_func_t)(const char *str, void *user_data);
bool mgmt_set_debug(struct mgmt *mgmt, mgmt_debug_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
bool mgmt_set_close_on_unref(struct mgmt *mgmt, bool do_close);
typedef void (*mgmt_request_func_t)(uint8_t status, uint16_t length,
const void *param, void *user_data);
unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id);
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index);
bool mgmt_cancel_all(struct mgmt *mgmt);
typedef void (*mgmt_notify_func_t)(uint16_t index, uint16_t length,
const void *param, void *user_data);
unsigned int mgmt_register(struct mgmt *mgmt, uint16_t event, uint16_t index,
mgmt_notify_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
bool mgmt_unregister(struct mgmt *mgmt, unsigned int id);
bool mgmt_unregister_index(struct mgmt *mgmt, uint16_t index);
bool mgmt_unregister_all(struct mgmt *mgmt);

View File

@ -0,0 +1,233 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2012-2014 Intel Corporation. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "src/shared/util.h"
#include "src/shared/pcap.h"
struct pcap_hdr {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} __attribute__ ((packed));
#define PCAP_HDR_SIZE (sizeof(struct pcap_hdr))
struct pcap_pkt {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} __attribute__ ((packed));
#define PCAP_PKT_SIZE (sizeof(struct pcap_pkt))
struct pcap_ppi {
uint8_t version; /* version, currently 0 */
uint8_t flags; /* flags */
uint16_t len; /* length of entire message */
uint32_t dlt; /* data link type */
} __attribute__ ((packed));
#define PCAP_PPI_SIZE (sizeof(struct pcap_ppi))
struct pcap {
int ref_count;
int fd;
uint32_t type;
uint32_t snaplen;
};
struct pcap *pcap_open(const char *path)
{
struct pcap *pcap;
struct pcap_hdr hdr;
ssize_t len;
pcap = calloc(1, sizeof(*pcap));
if (!pcap)
return NULL;
pcap->fd = open(path, O_RDONLY | O_CLOEXEC);
if (pcap->fd < 0) {
free(pcap);
return NULL;
}
len = read(pcap->fd, &hdr, PCAP_HDR_SIZE);
if (len < 0 || len != PCAP_HDR_SIZE)
goto failed;
if (hdr.magic_number != 0xa1b2c3d4)
goto failed;
if (hdr.version_major != 2 || hdr.version_minor != 4)
goto failed;
pcap->snaplen = hdr.snaplen;
pcap->type = hdr.network;
return pcap_ref(pcap);
failed:
close(pcap->fd);
free(pcap);
return NULL;
}
struct pcap *pcap_ref(struct pcap *pcap)
{
if (!pcap)
return NULL;
__sync_fetch_and_add(&pcap->ref_count, 1);
return pcap;
}
void pcap_unref(struct pcap *pcap)
{
if (!pcap)
return;
if (__sync_sub_and_fetch(&pcap->ref_count, 1))
return;
if (pcap->fd >= 0)
close(pcap->fd);
free(pcap);
}
uint32_t pcap_get_type(struct pcap *pcap)
{
if (!pcap)
return PCAP_TYPE_INVALID;
return pcap->type;
}
uint32_t pcap_get_snaplen(struct pcap *pcap)
{
if (!pcap)
return 0;
return pcap->snaplen;
}
bool pcap_read(struct pcap *pcap, struct timeval *tv,
void *data, uint32_t size, uint32_t *len)
{
struct pcap_pkt pkt;
uint32_t toread;
ssize_t bytes_read;
if (!pcap)
return false;
bytes_read = read(pcap->fd, &pkt, PCAP_PKT_SIZE);
if (bytes_read != PCAP_PKT_SIZE)
return false;
if (pkt.incl_len > size)
toread = size;
else
toread = pkt.incl_len;
bytes_read = read(pcap->fd, data, toread);
if (bytes_read < 0)
return false;
if (tv) {
tv->tv_sec = pkt.ts_sec;
tv->tv_usec = pkt.ts_usec;
}
if (len)
*len = toread;
return true;
}
bool pcap_read_ppi(struct pcap *pcap, struct timeval *tv, uint32_t *type,
void *data, uint32_t size,
uint32_t *offset, uint32_t *len)
{
struct pcap_pkt pkt;
struct pcap_ppi ppi;
uint16_t pph_len;
uint32_t toread;
ssize_t bytes_read;
if (!pcap)
return false;
bytes_read = read(pcap->fd, &pkt, PCAP_PKT_SIZE);
if (bytes_read != PCAP_PKT_SIZE)
return false;
if (pkt.incl_len > size)
toread = size;
else
toread = pkt.incl_len;
bytes_read = read(pcap->fd, &ppi, PCAP_PPI_SIZE);
if (bytes_read != PCAP_PPI_SIZE)
return false;
if (ppi.flags)
return false;
pph_len = le16_to_cpu(ppi.len);
if (pph_len < PCAP_PPI_SIZE)
return false;
bytes_read = read(pcap->fd, data, toread - PCAP_PPI_SIZE);
if (bytes_read < 0)
return false;
if (tv) {
tv->tv_sec = pkt.ts_sec;
tv->tv_usec = pkt.ts_usec;
}
if (type)
*type = le32_to_cpu(ppi.dlt);
if (offset)
*offset = pph_len - PCAP_PPI_SIZE;
if (len)
*len = toread - pph_len;
return true;
}

Some files were not shown because too many files have changed in this diff Show More